diff options
author | Arnd Bergmann <arnd@arndb.de> | 2012-03-19 20:46:32 +0000 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2012-03-20 09:41:43 +0000 |
commit | b2f1df8d2fc14bf7e6d9d967043d4b60c2efd8dc (patch) | |
tree | 065282434bde6ef9b4357c042705c5fcef3782ea /arch/mips/mm/fault.c | |
parent | c0206e228e34d8b414fcc63db45b831843adea06 (diff) | |
parent | 5cd9eb2736a572a9ef2689829f47ffd4262adc00 (diff) | |
download | op-kernel-dev-b2f1df8d2fc14bf7e6d9d967043d4b60c2efd8dc.zip op-kernel-dev-b2f1df8d2fc14bf7e6d9d967043d4b60c2efd8dc.tar.gz |
Merge branch 'renesas/timer' into next/timer
Conflicts:
arch/arm/mach-shmobile/timer.c
This resolves a nonobvious merge conflict between renesas
timer changes in the global timer changes with those
from the renesas soc branch and last minute bug fixes that
went into v3.3.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/mips/mm/fault.c')
-rw-r--r-- | arch/mips/mm/fault.c | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 937cf33..69ebd58 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -42,6 +42,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ const int field = sizeof(unsigned long) * 2; siginfo_t info; int fault; + unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | + (write ? FAULT_FLAG_WRITE : 0); #if 0 printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(), @@ -91,6 +93,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ if (in_atomic() || !mm) goto bad_area_nosemaphore; +retry: down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) @@ -144,7 +147,11 @@ good_area: * make sure we exit gracefully rather than endlessly redo * the fault. */ - fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); + fault = handle_mm_fault(mm, vma, address, flags); + + if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) + return; + perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) @@ -153,12 +160,27 @@ good_area: goto do_sigbus; BUG(); } - if (fault & VM_FAULT_MAJOR) { - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address); - tsk->maj_flt++; - } else { - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address); - tsk->min_flt++; + if (flags & FAULT_FLAG_ALLOW_RETRY) { + if (fault & VM_FAULT_MAJOR) { + perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, + regs, address); + tsk->maj_flt++; + } else { + perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, + regs, address); + tsk->min_flt++; + } + if (fault & VM_FAULT_RETRY) { + flags &= ~FAULT_FLAG_ALLOW_RETRY; + + /* + * No need to up_read(&mm->mmap_sem) as we would + * have already released it in __lock_page_or_retry + * in mm/filemap.c. + */ + + goto retry; + } } up_read(&mm->mmap_sem); |