Commit 90d0999c authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] Work around K8 errata on x86-64

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.
parent 445c90b5
...@@ -126,12 +126,6 @@ static int is_prefetch(struct pt_regs *regs, unsigned long addr) ...@@ -126,12 +126,6 @@ static int is_prefetch(struct pt_regs *regs, unsigned long addr)
break; break;
} }
} }
#if 1
if (prefetch)
printk("%s: prefetch caused page fault at %lx/%lx\n", current->comm,
regs->rip, addr);
#endif
return prefetch; return prefetch;
} }
...@@ -241,6 +235,15 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -241,6 +235,15 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
if (unlikely(in_atomic() || !mm)) if (unlikely(in_atomic() || !mm))
goto bad_area_nosemaphore; 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: again:
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment