Re: whee, first Linux workaround for the F0 0F bug found!

Linus Torvalds (torvalds@transmeta.com)
Wed, 12 Nov 1997 13:46:10 -0800 (PST)


Ingo, Alan, others,
I have a quick cleanup of 2.1.63 that looks a bit better wrt the F0 0F
bug, and also avoids the double SMP unlock that somebody noticed (sorry
for not giving attribution, I've been pretty rushed today trying to get
the stuff out quickly to people to test).

I still don't have any pentium closeby to actually test this, so I'm
appending patches relative to 2.1.63. Does this still work for people with
the bug?

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? */