diff options
Diffstat (limited to 'arch/x86/mm/fault_64.c')
-rw-r--r-- | arch/x86/mm/fault_64.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c index df13487aa83a..ccbb8e30d9f5 100644 --- a/arch/x86/mm/fault_64.c +++ b/arch/x86/mm/fault_64.c | |||
@@ -256,6 +256,22 @@ static int is_errata93(struct pt_regs *regs, unsigned long address) | |||
256 | return 0; | 256 | return 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | /* | ||
260 | * Work around K8 erratum #100 K8 in compat mode occasionally jumps to illegal | ||
261 | * addresses >4GB. We catch this in the page fault handler because these | ||
262 | * addresses are not reachable. Just detect this case and return. Any code | ||
263 | * segment in LDT is compatibility mode. | ||
264 | */ | ||
265 | static int is_errata100(struct pt_regs *regs, unsigned long address) | ||
266 | { | ||
267 | #ifdef CONFIG_X86_64 | ||
268 | if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) && | ||
269 | (address >> 32)) | ||
270 | return 1; | ||
271 | #endif | ||
272 | return 0; | ||
273 | } | ||
274 | |||
259 | void do_invalid_op(struct pt_regs *, unsigned long); | 275 | void do_invalid_op(struct pt_regs *, unsigned long); |
260 | 276 | ||
261 | static int is_f00f_bug(struct pt_regs *regs, unsigned long address) | 277 | static int is_f00f_bug(struct pt_regs *regs, unsigned long address) |
@@ -568,14 +584,7 @@ bad_area_nosemaphore: | |||
568 | if (is_prefetch(regs, address, error_code)) | 584 | if (is_prefetch(regs, address, error_code)) |
569 | return; | 585 | return; |
570 | 586 | ||
571 | /* Work around K8 erratum #100 K8 in compat mode | 587 | if (is_errata100(regs, address)) |
572 | occasionally jumps to illegal addresses >4GB. We | ||
573 | catch this here in the page fault handler because | ||
574 | these addresses are not reachable. Just detect this | ||
575 | case and return. Any code segment in LDT is | ||
576 | compatibility mode. */ | ||
577 | if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) && | ||
578 | (address >> 32)) | ||
579 | return; | 588 | return; |
580 | 589 | ||
581 | if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && | 590 | if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && |