aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/mm/fault.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/mm/fault.c')
-rw-r--r--arch/xtensa/mm/fault.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index b17885a0b508..5a74c53bc69c 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -44,6 +44,7 @@ void do_page_fault(struct pt_regs *regs)
44 44
45 int is_write, is_exec; 45 int is_write, is_exec;
46 int fault; 46 int fault;
47 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
47 48
48 info.si_code = SEGV_MAPERR; 49 info.si_code = SEGV_MAPERR;
49 50
@@ -71,6 +72,7 @@ void do_page_fault(struct pt_regs *regs)
71 address, exccause, regs->pc, is_write? "w":"", is_exec? "x":""); 72 address, exccause, regs->pc, is_write? "w":"", is_exec? "x":"");
72#endif 73#endif
73 74
75retry:
74 down_read(&mm->mmap_sem); 76 down_read(&mm->mmap_sem);
75 vma = find_vma(mm, address); 77 vma = find_vma(mm, address);
76 78
@@ -93,6 +95,7 @@ good_area:
93 if (is_write) { 95 if (is_write) {
94 if (!(vma->vm_flags & VM_WRITE)) 96 if (!(vma->vm_flags & VM_WRITE))
95 goto bad_area; 97 goto bad_area;
98 flags |= FAULT_FLAG_WRITE;
96 } else if (is_exec) { 99 } else if (is_exec) {
97 if (!(vma->vm_flags & VM_EXEC)) 100 if (!(vma->vm_flags & VM_EXEC))
98 goto bad_area; 101 goto bad_area;
@@ -104,7 +107,11 @@ good_area:
104 * make sure we exit gracefully rather than endlessly redo 107 * make sure we exit gracefully rather than endlessly redo
105 * the fault. 108 * the fault.
106 */ 109 */
107 fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); 110 fault = handle_mm_fault(mm, vma, address, flags);
111
112 if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
113 return;
114
108 if (unlikely(fault & VM_FAULT_ERROR)) { 115 if (unlikely(fault & VM_FAULT_ERROR)) {
109 if (fault & VM_FAULT_OOM) 116 if (fault & VM_FAULT_OOM)
110 goto out_of_memory; 117 goto out_of_memory;
@@ -112,10 +119,22 @@ good_area:
112 goto do_sigbus; 119 goto do_sigbus;
113 BUG(); 120 BUG();
114 } 121 }
115 if (fault & VM_FAULT_MAJOR) 122 if (flags & FAULT_FLAG_ALLOW_RETRY) {
116 current->maj_flt++; 123 if (fault & VM_FAULT_MAJOR)
117 else 124 current->maj_flt++;
118 current->min_flt++; 125 else
126 current->min_flt++;
127 if (fault & VM_FAULT_RETRY) {
128 flags &= ~FAULT_FLAG_ALLOW_RETRY;
129
130 /* No need to up_read(&mm->mmap_sem) as we would
131 * have already released it in __lock_page_or_retry
132 * in mm/filemap.c.
133 */
134
135 goto retry;
136 }
137 }
119 138
120 up_read(&mm->mmap_sem); 139 up_read(&mm->mmap_sem);
121 return; 140 return;