aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/mm/fault_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/mm/fault_32.c')
-rw-r--r--arch/sparc/mm/fault_32.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index 7705c6731e28..df3155a17991 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -225,6 +225,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
225 unsigned long g2; 225 unsigned long g2;
226 int from_user = !(regs->psr & PSR_PS); 226 int from_user = !(regs->psr & PSR_PS);
227 int fault, code; 227 int fault, code;
228 unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
229 (write ? FAULT_FLAG_WRITE : 0));
228 230
229 if(text_fault) 231 if(text_fault)
230 address = regs->pc; 232 address = regs->pc;
@@ -251,6 +253,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
251 253
252 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); 254 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
253 255
256retry:
254 down_read(&mm->mmap_sem); 257 down_read(&mm->mmap_sem);
255 258
256 /* 259 /*
@@ -289,7 +292,11 @@ good_area:
289 * make sure we exit gracefully rather than endlessly redo 292 * make sure we exit gracefully rather than endlessly redo
290 * the fault. 293 * the fault.
291 */ 294 */
292 fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); 295 fault = handle_mm_fault(mm, vma, address, flags);
296
297 if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
298 return;
299
293 if (unlikely(fault & VM_FAULT_ERROR)) { 300 if (unlikely(fault & VM_FAULT_ERROR)) {
294 if (fault & VM_FAULT_OOM) 301 if (fault & VM_FAULT_OOM)
295 goto out_of_memory; 302 goto out_of_memory;
@@ -297,13 +304,29 @@ good_area:
297 goto do_sigbus; 304 goto do_sigbus;
298 BUG(); 305 BUG();
299 } 306 }
300 if (fault & VM_FAULT_MAJOR) { 307
301 current->maj_flt++; 308 if (flags & FAULT_FLAG_ALLOW_RETRY) {
302 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address); 309 if (fault & VM_FAULT_MAJOR) {
303 } else { 310 current->maj_flt++;
304 current->min_flt++; 311 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,
305 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address); 312 1, regs, address);
313 } else {
314 current->min_flt++;
315 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
316 1, regs, address);
317 }
318 if (fault & VM_FAULT_RETRY) {
319 flags &= ~FAULT_FLAG_ALLOW_RETRY;
320
321 /* No need to up_read(&mm->mmap_sem) as we would
322 * have already released it in __lock_page_or_retry
323 * in mm/filemap.c.
324 */
325
326 goto retry;
327 }
306 } 328 }
329
307 up_read(&mm->mmap_sem); 330 up_read(&mm->mmap_sem);
308 return; 331 return;
309 332