]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Work around K8 errata on x86-64
authorAndi Kleen <ak@muc.de>
Sun, 9 Nov 2003 01:51:23 +0000 (17:51 -0800)
committerLinus Torvalds <torvalds@home.osdl.org>
Sun, 9 Nov 2003 01:51:23 +0000 (17:51 -0800)
K8 has an erratum (#100) that essentially causes some compat mode processes
to fault occassionally. The issue can be worked around in the OS. It only
applies to x86-64, in 32bit it is fine.

This adds a check to the page fault handler that checks for addresses >4GB
from compat mode. If they happen just return; the CPU will reexecute
the instruction and the condition that caused the problem is gone.

More details in Opteron/Athlon64 specification update on the AMD website.

Also I removed a left over debugging printk in the prefetch handling code.

arch/x86_64/mm/fault.c

index da216232e53f8620abd0558380569c0da126e2b2..48676d0e17b6f12019814f78e679cbee375f6d80 100644 (file)
@@ -126,12 +126,6 @@ static int is_prefetch(struct pt_regs *regs, unsigned long addr)
                        break;
                } 
        }
-
-#if 1
-       if (prefetch)
-               printk("%s: prefetch caused page fault at %lx/%lx\n", current->comm,
-                      regs->rip, addr);
-#endif
        return prefetch;
 }
 
@@ -241,6 +235,15 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
        if (unlikely(in_atomic() || !mm))
                goto bad_area_nosemaphore;
 
+       /* Work around K8 erratum #100
+          K8 in compat mode occasionally jumps to illegal addresses >4GB.
+          We catch this here in the page fault handler because these
+          addresses are not reachable. Just detect this case and return.
+          Any code segment in LDT is compatibility mode. */
+       if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) &&
+               (address >> 32))
+               return;
+
  again:
        down_read(&mm->mmap_sem);