--==_Exmh_19399604480
Content-Type: text/plain; charset=us-ascii
This is what should hopefully be a final fix for the F0 0F bug even on SMP
machines.
It includes Linus' tidy up of the code, including the removal of the extra unlock_kernel() which was pointed out by ganesh@cse.iitb.ernet.in.
It also includes my patch to make sure the new idt gets loaded on all the
processors, rather than just the boot one.
It's against 2.1.63-VGER; I'm going to go and fetch a pre-64 and make a patch
against that in a few minutes. For those whose are still on the real 63, this
should patch for you if you replace all occurrences of
"boot_cpu_data.f00f_bug" in it with "pentium_f00f_bug" before you try to apply
it.
dwmw2:/ $ cat /proc/cpuinfo
processor : 0
cpu family : 5
model : Pentium 75+
vendor_id : GenuineIntel
stepping : 12
fdiv_bug : no
hlt_bug : no
sep_bug : no
f00f_bug : yes
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr mce cx8 apic
bogomips : 79.46
processor : 1
cpu family : 5
model : Pentium 75+
vendor_id : GenuineIntel
stepping : 12
fdiv_bug : no
hlt_bug : no
sep_bug : no
f00f_bug : yes
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr mce cx8 apic
bogomips : 79.46
dwmw2:/ $ while true; do ./Crashme & done
... happily catches a few hundred of them.
--==_Exmh_19399604480
Content-Type: text/plain ; name="f00fbug-smp-63v-3"; charset=us-ascii
Content-Description: f00fbug-smp-63v-3
Content-Disposition: attachment; filename="f00fbug-smp-63v-3"
--- test/linux/arch/i386/kernel/smp.c Mon Nov 3 00:03:26 1997
+++ linux/arch/i386/kernel/smp.c Thu Nov 13 15:02:48 1997
@@ -644,6 +644,7 @@
static int cpucount = 0;
extern int cpu_idle(void * unused);
+extern struct f00fbug_idt_struct idt_d;
/*
* Activate a secondary processor.
@@ -651,6 +652,9 @@
__initfunc(int start_secondary(void *unused))
{
smp_callin();
+ if (boot_cpu_data.f00f_bug) {
+ __asm__ __volatile__("\tlidt %0": "=m" (idt_d));
+ }
while (!smp_commenced)
barrier();
return cpu_idle(NULL);
--- test/linux/arch/i386/mm/fault.c Thu Nov 13 15:13:15 1997
+++ linux/arch/i386/mm/fault.c Thu Nov 13 15:04:09 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);
@@ -188,44 +180,27 @@
goto out;
}
- printk("<%p/%p>\n", idt2, (void *)address);
/*
* Pentium F0 0F C7 C8 bug workaround:
*/
- if ( boot_cpu_data.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 ( boot_cpu_data.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? */
--- test/linux/include/asm-i386/bugs.h Thu Nov 13 15:13:35 1997
+++ linux/include/asm-i386/bugs.h Thu Nov 13 15:09:37 1997
@@ -177,18 +177,15 @@
/*
* Pentium and Pentium MMX
*/
- printk("checking for F00F bug ...");
+ boot_cpu_data.f00f_bug = 0;
if(boot_cpu_data.x86 == 5 &&
!memcmp(boot_cpu_data.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");
+ printk(KERN_INFO "Intel Pentium with F0 0F bug - workaround enabled.\n");
boot_cpu_data.f00f_bug = 1;
trap_init_f00f_bug();
- } else {
- printk(KERN_INFO " no F0 0F bug in this CPU, great!\n");
- boot_cpu_data.f00f_bug = 0;
}
}
--- test/linux/include/asm-i386/processor.h Thu Nov 13 15:13:35 1997
+++ linux/include/asm-i386/processor.h Thu Nov 13 15:03:00 1997
@@ -216,4 +216,10 @@
#define init_task (init_task_union.task)
#define init_stack (init_task_union.stack)
+struct f00fbug_idt_struct {
+ short limit __attribute__((packed));
+ void * addr __attribute__((packed));
+ short __pad __attribute__((packed));
+};
+
#endif /* __ASM_I386_PROCESSOR_H */
--==_Exmh_19399604480
Content-Type: text/plain; charset=us-ascii
---- ---- ----
David Woodhouse, Robinson College, CB3 9AN, England. (+44) 0976 658355
dwmw2@cam.ac.uk http://dwmw2.robinson.cam.ac.uk
finger pgp@dwmw2.robinson.cam.ac.uk for PGP key.
--==_Exmh_19399604480--