Messages in this thread Patch in this message | | | Subject | F0 0F bug - stable and happy on SMP now. | Date | Thu, 13 Nov 1997 15:42:24 +0000 | From | David Woodhouse <> |
| |
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. --- 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 */---- ---- ---- 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.
| |