Re: 2.1.63 - testing Pentium bug workaround..

Linus Torvalds (torvalds@transmeta.com)
Wed, 12 Nov 1997 18:05:29 -0800 (PST)


On Wed, 12 Nov 1997, Simon's Mailing List Account wrote:
>
> The pentium bugfix works the first time an 'exploit' is run,
> but the chip locks the second time.
>
> P54C/133mhz 112MB, kernel compiled with gcc 2.7.2.1
> kernel compiled (accidentally) for SMP because I forgot to undefine
> (i'm trying with a uniprocessor kernel now, will report with anything
> different)

The second lock-up is hopefully due to the bug with the double unlock of
the SMP kernel lock - when the pentium workaround triggers, it incorrectly
releases the kernel lock twice in 2.1.63. Could you try it on UP, _and_ in
addition try this updated patch (patch relative to clean 2.1.63) which
should hopefully make it SMP-safe too..

NOTE! I'm _very_ interested in hearing about CPU's that aren't fixed by
this patch. I'm also interested in hearing just a quick "works for me"
message from people that it _does_ work for. I'm essentially trying to get
both confirmation that yes, it does work, and at the same time trying to
see if there are any circumstances under which it fails - so that we can
try to track down _why_ it fails.

So if you have a pentium, and the patches do work for you (try the exploit
programs a few times), just send me a quick email with the subject "works
for me" or something like that.. On the other hand, if it doesn't work,
I'd like to get a more complete email with system setup information etc.

Linus

-----
diff -u --recursive --new-file v2.1.63/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v2.1.63/linux/arch/i386/mm/fault.c Wed Nov 12 13:34:25 1997
+++ linux/arch/i386/mm/fault.c Wed Nov 12 13:33:48 1997
@@ -74,14 +74,6 @@
return 0;
}

-asmlinkage void divide_error(void);
-asmlinkage void debug(void);
-asmlinkage void nmi(void);
-asmlinkage void int3(void);
-asmlinkage void overflow(void);
-asmlinkage void bounds(void);
-asmlinkage void invalid_op(void);
-
asmlinkage void do_divide_error (struct pt_regs *, unsigned long);
asmlinkage void do_debug (struct pt_regs *, unsigned long);
asmlinkage void do_nmi (struct pt_regs *, unsigned long);
@@ -189,44 +181,27 @@
goto out;
}

- printk("<%p/%p>\n", idt2, (void *)address);
/*
* Pentium F0 0F C7 C8 bug workaround:
*/
- if ( pentium_f00f_bug && (address >= (unsigned long)idt2) &&
- (address < (unsigned long)idt2+256*8) ) {
-
- void (*handler) (void);
- int nr = (address-(unsigned long)idt2)/8;
- unsigned long low, high;
-
- low = idt[nr].a;
- high = idt[nr].b;
-
- handler = (void (*) (void)) ((low&0x0000ffff) | (high&0xffff0000));
- printk("<handler %p... ", handler);
- unlock_kernel();
-
- if (handler==divide_error)
- do_divide_error(regs,error_code);
- else if (handler==debug)
- do_debug(regs,error_code);
- else if (handler==nmi)
- do_nmi(regs,error_code);
- else if (handler==int3)
- do_int3(regs,error_code);
- else if (handler==overflow)
- do_overflow(regs,error_code);
- else if (handler==bounds)
- do_bounds(regs,error_code);
- else if (handler==invalid_op)
- do_invalid_op(regs,error_code);
- else {
- printk("INVALID HANDLER!\n");
- for (;;) __cli();
+ if ( pentium_f00f_bug ) {
+ unsigned long nr;
+
+ nr = (address - (unsigned long) idt2) >> 3;
+
+ if (nr < 7) {
+ static void (*handler[])(struct pt_regs *, unsigned long) = {
+ do_divide_error, /* 0 - divide overflow */
+ do_debug, /* 1 - debug trap */
+ do_nmi, /* 2 - NMI */
+ do_int3, /* 3 - int 3 */
+ do_overflow, /* 4 - overflow */
+ do_bounds, /* 5 - bound range */
+ do_invalid_op }; /* 6 - invalid opcode */
+ unlock_kernel();
+ handler[nr](regs, error_code);
+ return;
}
- printk("... done>\n");
- goto out;
}

/* Are we prepared to handle this kernel fault? */
diff -u --recursive --new-file v2.1.63/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- v2.1.63/linux/include/asm-i386/bugs.h Wed Nov 12 13:34:27 1997
+++ linux/include/asm-i386/bugs.h Wed Nov 12 17:24:07 1997
@@ -142,7 +142,7 @@
: "edx" (inp)
: "eax", "ecx", "edx", "edi" );
/* If this fails, it means that any user program may lock CPU hard. Too bad. */
- if (res != 12345678) printk( "Bad.\n" );
+ if (res != 12345678) printk( "Buggy.\n" );
else printk( "Ok.\n" );
#endif
}
@@ -172,23 +172,19 @@
*/

extern int pentium_f00f_bug;
+extern void trap_init_f00f_bug(void);
+

__initfunc(static void check_pentium_f00f(void))
{
/*
* Pentium and Pentium MMX
*/
- printk("checking for F00F bug ...");
- if(x86==5 && !memcmp(x86_vendor_id, "GenuineIntel", 12))
- {
- extern void trap_init_f00f_bug(void);
-
- printk(KERN_INFO "\nIntel Pentium/[MMX] F0 0F bug detected - turning on workaround.\n");
+ pentium_f00f_bug = 0;
+ if (x86==5 && !memcmp(x86_vendor_id, "GenuineIntel", 12)) {
+ printk(KERN_INFO "Intel Pentium with F0 0F bug - workaround enabled.\n");
pentium_f00f_bug = 1;
trap_init_f00f_bug();
- } else {
- printk(KERN_INFO " no F0 0F bug in this CPU, great!\n");
- pentium_f00f_bug = 0;
}
}