aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/fault.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/fault.c')
-rw-r--r--arch/x86/mm/fault.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 2dbf6bf4c7e..0d17c8c50ac 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -17,6 +17,7 @@
17#include <asm/traps.h> /* dotraplinkage, ... */ 17#include <asm/traps.h> /* dotraplinkage, ... */
18#include <asm/pgalloc.h> /* pgd_*(), ... */ 18#include <asm/pgalloc.h> /* pgd_*(), ... */
19#include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ 19#include <asm/kmemcheck.h> /* kmemcheck_*(), ... */
20#include <asm/vsyscall.h>
20 21
21/* 22/*
22 * Page fault error code bits: 23 * Page fault error code bits:
@@ -105,7 +106,7 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,
105 * but for now it's good enough to assume that long 106 * but for now it's good enough to assume that long
106 * mode only uses well known segments or kernel. 107 * mode only uses well known segments or kernel.
107 */ 108 */
108 return (!user_mode(regs)) || (regs->cs == __USER_CS); 109 return (!user_mode(regs) || user_64bit_mode(regs));
109#endif 110#endif
110 case 0x60: 111 case 0x60:
111 /* 0x64 thru 0x67 are valid prefixes in all modes. */ 112 /* 0x64 thru 0x67 are valid prefixes in all modes. */
@@ -720,6 +721,18 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
720 if (is_errata100(regs, address)) 721 if (is_errata100(regs, address))
721 return; 722 return;
722 723
724#ifdef CONFIG_X86_64
725 /*
726 * Instruction fetch faults in the vsyscall page might need
727 * emulation.
728 */
729 if (unlikely((error_code & PF_INSTR) &&
730 ((address & ~0xfff) == VSYSCALL_START))) {
731 if (emulate_vsyscall(regs, address))
732 return;
733 }
734#endif
735
723 if (unlikely(show_unhandled_signals)) 736 if (unlikely(show_unhandled_signals))
724 show_signal_msg(regs, error_code, address, tsk); 737 show_signal_msg(regs, error_code, address, tsk);
725 738
@@ -1059,7 +1072,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
1059 if (unlikely(error_code & PF_RSVD)) 1072 if (unlikely(error_code & PF_RSVD))
1060 pgtable_bad(regs, error_code, address); 1073 pgtable_bad(regs, error_code, address);
1061 1074
1062 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); 1075 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
1063 1076
1064 /* 1077 /*
1065 * If we're in an interrupt, have no user context or are running 1078 * If we're in an interrupt, have no user context or are running
@@ -1161,11 +1174,11 @@ good_area:
1161 if (flags & FAULT_FLAG_ALLOW_RETRY) { 1174 if (flags & FAULT_FLAG_ALLOW_RETRY) {
1162 if (fault & VM_FAULT_MAJOR) { 1175 if (fault & VM_FAULT_MAJOR) {
1163 tsk->maj_flt++; 1176 tsk->maj_flt++;
1164 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, 1177 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
1165 regs, address); 1178 regs, address);
1166 } else { 1179 } else {
1167 tsk->min_flt++; 1180 tsk->min_flt++;
1168 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, 1181 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
1169 regs, address); 1182 regs, address);
1170 } 1183 }
1171 if (fault & VM_FAULT_RETRY) { 1184 if (fault & VM_FAULT_RETRY) {