From owner-freebsd-bugs Fri Nov 14 21:34:42 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id VAA01473 for bugs-outgoing; Fri, 14 Nov 1997 21:34:42 -0800 (PST) (envelope-from owner-freebsd-bugs) Received: from implode.root.com (implode.root.com [198.145.90.17]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id VAA01457 for ; Fri, 14 Nov 1997 21:34:37 -0800 (PST) (envelope-from root@implode.root.com) Received: from implode.root.com (localhost [127.0.0.1]) by implode.root.com (8.8.5/8.8.5) with ESMTP id VAA15414; Fri, 14 Nov 1997 21:35:51 -0800 (PST) Message-Id: <199711150535.VAA15414@implode.root.com> To: Brett Glass cc: bugs@FreeBSD.ORG Subject: Re: Foof! bug fix? In-reply-to: Your message of "Fri, 14 Nov 1997 17:57:37 MST." <3.0.5.32.19971114175737.00928b90@mail.lariat.org> From: David Greenman Reply-To: dg@root.com Date: Fri, 14 Nov 1997 21:35:51 -0800 Sender: owner-freebsd-bugs@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk >Have our trusty kernel hackers implemented Intel's fix for the "Foof!" bug? > Apparently, it involves moving the IDT so that it spans a page boundary > just so, then adding a bit of code to the page fault handler. The fix is at > http://support.intel.com/support/processors/pentium/ppiie/index.htm on the > Web. We're evaluating what looks to be a far superior (and simpler!) fix that was proposed by Jonathan Lemon (a FreeBSD contributor). Again, we want the "right" fix, not just the "right now" fix. I've appended Jonathan's proposal to the end of the message in case you need something "right now". :-) -DG David Greenman Core-team/Principal Architect, The FreeBSD Project >Date: Fri, 14 Nov 1997 17:12:15 -0600 >From: Jonathan Lemon >To: hackers@FreeBSD.ORG >Subject: FreeBSD Pentium Bug fix (proposed) Alright, I've been watching the debate about the LOCK CMPXCHG8 bug, and decided to take a crack at it. While I believe that for the most case, this is probably just a tempest in a teapot, for some, it probably represents a serious DOS that should be addressed. IMHO, the "take page fault on any trapno < 7" solution is a very ugly hack, but it got me thinking about a better way to solve this. The solution seems to depend on the fact that a page fault has a higher priority than an illegal instruction fault, and thus, if both are posted first, then the page fault takes precedence. This made me think that there might be other faults that also have higher precedence than the illegal instruction fault, and which could be localized to just the #UD handler. It turns out that exceeding the segment limit is one of them. My ``fix'' is to have the IDT descriptor reference a segemnt which has a length of 0. This has the effect of mapping SIGILL into SIGBUS, so that the `cmpxchg8' crash now generates a Bus error. (I didn't bother returning the correct signal; it can probably be added if it is important) This fix works on my machine, takes no overhead, and the only breaks BDE_DEBUGGER, which wants to hoard all the GDT entries for itself. :-) I'd appreciate it if interested parties could try this out and see if it also fixes the problem on other machines. -- Jonathan --------------------------------- cut here --------------------------------- Index: machdep.c =================================================================== RCS file: /tuna/ncvs/src/sys/i386/i386/machdep.c,v retrieving revision 1.270 diff -c -r1.270 machdep.c *************** *** 981,986 **** --- 993,1009 ---- 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, + #ifdef CMPXCHG8_BUG + /* GBUG_SEL 11 Invalid Descriptor for CMPXCHG8_BUG */ + { 0x0, /* segment base address */ + 0x0, /* length - none */ + SDT_MEMERA, /* segment type */ + 0, /* segment descriptor priority level */ + 1, /* segment descriptor present */ + 0, 0, + 1, /* default 32 vs 16 bit size */ + 1 /* limit granularity (byte/page units)*/ }, + #endif }; static struct soft_segment_descriptor ldt_segs[] = { *************** *** 1209,1216 **** --- 1232,1244 ---- #endif finishidentcpu(); /* Final stage of CPU initialization */ + #ifdef CMPXCHG8_BUG + setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GBUG_SEL, SEL_KPL)); + #else setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + #endif initializecpu(); /* Initialize CPU registers */ + /* Use BIOS values stored in RTC CMOS RAM, since probing * breaks certain 386 AT relics. Index: include/segments.h =================================================================== RCS file: /tuna/ncvs/src/sys/i386/include/segments.h,v retrieving revision 1.17 diff -c -r1.17 segments.h *** segments.h 1997/08/21 06:32:49 1.17 --- segments.h 1997/11/14 22:34:58 *************** *** 215,225 **** --- 215,232 ---- #define GAPMCODE32_SEL 8 /* APM BIOS 32-bit interface (32bit Code) */ #define GAPMCODE16_SEL 9 /* APM BIOS 32-bit interface (16bit Code) */ #define GAPMDATA_SEL 10 /* APM BIOS 32-bit interface (Data) */ + #ifdef CMPXCHG8_BUG + #define GBUG_SEL 11 /* Invalid Descriptor for CMPXCHG8_BUG */ + #endif #ifdef BDE_DEBUGGER #define NGDT 18 /* some of 11-17 are reserved for debugger */ #else + #ifdef CMPXCHG8_BUG + #define NGDT (GBUG_SEL + 1) + #else #define NGDT (GAPMDATA_SEL + 1) + #endif #endif /*