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.c43
1 files changed, 22 insertions, 21 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 654be4ae3047..3aaeffcfd67a 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -842,23 +842,15 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
842 force_sig_info_fault(SIGBUS, code, address, tsk, fault); 842 force_sig_info_fault(SIGBUS, code, address, tsk, fault);
843} 843}
844 844
845static noinline int 845static noinline void
846mm_fault_error(struct pt_regs *regs, unsigned long error_code, 846mm_fault_error(struct pt_regs *regs, unsigned long error_code,
847 unsigned long address, unsigned int fault) 847 unsigned long address, unsigned int fault)
848{ 848{
849 /* 849 if (fatal_signal_pending(current) && !(error_code & PF_USER)) {
850 * Pagefault was interrupted by SIGKILL. We have no reason to 850 up_read(&current->mm->mmap_sem);
851 * continue pagefault. 851 no_context(regs, error_code, address, 0, 0);
852 */ 852 return;
853 if (fatal_signal_pending(current)) {
854 if (!(fault & VM_FAULT_RETRY))
855 up_read(&current->mm->mmap_sem);
856 if (!(error_code & PF_USER))
857 no_context(regs, error_code, address, 0, 0);
858 return 1;
859 } 853 }
860 if (!(fault & VM_FAULT_ERROR))
861 return 0;
862 854
863 if (fault & VM_FAULT_OOM) { 855 if (fault & VM_FAULT_OOM) {
864 /* Kernel mode? Handle exceptions or die: */ 856 /* Kernel mode? Handle exceptions or die: */
@@ -866,7 +858,7 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
866 up_read(&current->mm->mmap_sem); 858 up_read(&current->mm->mmap_sem);
867 no_context(regs, error_code, address, 859 no_context(regs, error_code, address,
868 SIGSEGV, SEGV_MAPERR); 860 SIGSEGV, SEGV_MAPERR);
869 return 1; 861 return;
870 } 862 }
871 863
872 up_read(&current->mm->mmap_sem); 864 up_read(&current->mm->mmap_sem);
@@ -884,7 +876,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
884 else 876 else
885 BUG(); 877 BUG();
886 } 878 }
887 return 1;
888} 879}
889 880
890static int spurious_fault_check(unsigned long error_code, pte_t *pte) 881static int spurious_fault_check(unsigned long error_code, pte_t *pte)
@@ -1011,9 +1002,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
1011 unsigned long address; 1002 unsigned long address;
1012 struct mm_struct *mm; 1003 struct mm_struct *mm;
1013 int fault; 1004 int fault;
1014 int write = error_code & PF_WRITE; 1005 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
1015 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
1016 (write ? FAULT_FLAG_WRITE : 0);
1017 1006
1018 tsk = current; 1007 tsk = current;
1019 mm = tsk->mm; 1008 mm = tsk->mm;
@@ -1083,6 +1072,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
1083 if (user_mode_vm(regs)) { 1072 if (user_mode_vm(regs)) {
1084 local_irq_enable(); 1073 local_irq_enable();
1085 error_code |= PF_USER; 1074 error_code |= PF_USER;
1075 flags |= FAULT_FLAG_USER;
1086 } else { 1076 } else {
1087 if (regs->flags & X86_EFLAGS_IF) 1077 if (regs->flags & X86_EFLAGS_IF)
1088 local_irq_enable(); 1078 local_irq_enable();
@@ -1109,6 +1099,9 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
1109 return; 1099 return;
1110 } 1100 }
1111 1101
1102 if (error_code & PF_WRITE)
1103 flags |= FAULT_FLAG_WRITE;
1104
1112 /* 1105 /*
1113 * When running in the kernel we expect faults to occur only to 1106 * When running in the kernel we expect faults to occur only to
1114 * addresses in user space. All other faults represent errors in 1107 * addresses in user space. All other faults represent errors in
@@ -1187,9 +1180,17 @@ good_area:
1187 */ 1180 */
1188 fault = handle_mm_fault(mm, vma, address, flags); 1181 fault = handle_mm_fault(mm, vma, address, flags);
1189 1182
1190 if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) { 1183 /*
1191 if (mm_fault_error(regs, error_code, address, fault)) 1184 * If we need to retry but a fatal signal is pending, handle the
1192 return; 1185 * signal first. We do not need to release the mmap_sem because it
1186 * would already be released in __lock_page_or_retry in mm/filemap.c.
1187 */
1188 if (unlikely((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)))
1189 return;
1190
1191 if (unlikely(fault & VM_FAULT_ERROR)) {
1192 mm_fault_error(regs, error_code, address, fault);
1193 return;
1193 } 1194 }
1194 1195
1195 /* 1196 /*