diff -u linux/arch/x86_64/mm/fault.c-ERRATA93 linux/arch/x86_64/mm/fault.c --- linux/arch/x86_64/mm/fault.c-ERRATA93 2004-01-08 16:56:58.000000000 +0100 +++ linux/arch/x86_64/mm/fault.c 2004-01-13 16:08:27.000000000 +0100 @@ -173,6 +173,40 @@ return prefetch; } +static const char errata93_warning[] = +KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n" +KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n" +KERN_ERR "******* Please consider a BIOS update.\n" +KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n"; + +/* Workaround for K8 erratum #93 & buggy BIOS. + BIOS SMM functions are required to use a specific workaround + to avoid corruption of the 64bit RIP register on C stepping K8. + A lot of BIOS that didn't get tested properly miss this. + The OS sees this as a page fault with the upper 32bits of RIP cleared. + Try to work around it here. + Note we only handle faults in kernel here. */ + +static int is_errata93(struct pt_regs *regs, unsigned long address) +{ + static int warned; + if (address != regs->rip) + return 0; + if ((address >> 32) != 0) + return 0; + address |= 0xffffffffUL << 32; + if ((address >= _stext && address <= _etext) || + (address >= MODULES_VADDR && address <= MODULES_END)) { + if (!warned) { + printk(errata93_warning); + warned = 1; + } + regs->rip = address; + return 1; + } + return 0; +} + int page_fault_trace; int exception_trace = 1; @@ -350,9 +384,16 @@ return; } + /* + * Hall of shame of CPU/BIOS bugs. + */ + if (is_prefetch(regs, address)) return; + if (is_errata93(regs, address)) + return; + /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice.