aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/mm/fault.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 6dea040cc3a1..e7fa28bf3262 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1022,11 +1022,11 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs)
1022 * routines. 1022 * routines.
1023 */ 1023 */
1024static void __kprobes 1024static void __kprobes
1025__do_page_fault(struct pt_regs *regs, unsigned long error_code) 1025__do_page_fault(struct pt_regs *regs, unsigned long error_code,
1026 unsigned long address)
1026{ 1027{
1027 struct vm_area_struct *vma; 1028 struct vm_area_struct *vma;
1028 struct task_struct *tsk; 1029 struct task_struct *tsk;
1029 unsigned long address;
1030 struct mm_struct *mm; 1030 struct mm_struct *mm;
1031 int fault; 1031 int fault;
1032 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; 1032 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
@@ -1034,9 +1034,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
1034 tsk = current; 1034 tsk = current;
1035 mm = tsk->mm; 1035 mm = tsk->mm;
1036 1036
1037 /* Get the faulting address: */
1038 address = read_cr2();
1039
1040 /* 1037 /*
1041 * Detect and handle instructions that would cause a page fault for 1038 * Detect and handle instructions that would cause a page fault for
1042 * both a tracked kernel page and a userspace page. 1039 * both a tracked kernel page and a userspace page.
@@ -1252,9 +1249,11 @@ dotraplinkage void __kprobes
1252do_page_fault(struct pt_regs *regs, unsigned long error_code) 1249do_page_fault(struct pt_regs *regs, unsigned long error_code)
1253{ 1250{
1254 enum ctx_state prev_state; 1251 enum ctx_state prev_state;
1252 /* Get the faulting address: */
1253 unsigned long address = read_cr2();
1255 1254
1256 prev_state = exception_enter(); 1255 prev_state = exception_enter();
1257 __do_page_fault(regs, error_code); 1256 __do_page_fault(regs, error_code, address);
1258 exception_exit(prev_state); 1257 exception_exit(prev_state);
1259} 1258}
1260 1259
@@ -1271,9 +1270,16 @@ dotraplinkage void __kprobes
1271trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) 1270trace_do_page_fault(struct pt_regs *regs, unsigned long error_code)
1272{ 1271{
1273 enum ctx_state prev_state; 1272 enum ctx_state prev_state;
1273 /*
1274 * The exception_enter and tracepoint processing could
1275 * trigger another page faults (user space callchain
1276 * reading) and destroy the original cr2 value, so read
1277 * the faulting address now.
1278 */
1279 unsigned long address = read_cr2();
1274 1280
1275 prev_state = exception_enter(); 1281 prev_state = exception_enter();
1276 trace_page_fault_entries(regs, error_code); 1282 trace_page_fault_entries(regs, error_code);
1277 __do_page_fault(regs, error_code); 1283 __do_page_fault(regs, error_code, address);
1278 exception_exit(prev_state); 1284 exception_exit(prev_state);
1279} 1285}