diff options
Diffstat (limited to 'arch/mips/mm')
| -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 937cf3368164..69ebd586d7ff 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 | |||
| 42 | const int field = sizeof(unsigned long) * 2; | 42 | const int field = sizeof(unsigned long) * 2; |
| 43 | siginfo_t info; | 43 | siginfo_t info; |
| 44 | int fault; | 44 | int fault; |
| 45 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | | ||
| 46 | (write ? FAULT_FLAG_WRITE : 0); | ||
| 45 | 47 | ||
| 46 | #if 0 | 48 | #if 0 |
| 47 | printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(), | 49 | 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 | |||
| 91 | if (in_atomic() || !mm) | 93 | if (in_atomic() || !mm) |
| 92 | goto bad_area_nosemaphore; | 94 | goto bad_area_nosemaphore; |
| 93 | 95 | ||
| 96 | retry: | ||
| 94 | down_read(&mm->mmap_sem); | 97 | down_read(&mm->mmap_sem); |
| 95 | vma = find_vma(mm, address); | 98 | vma = find_vma(mm, address); |
| 96 | if (!vma) | 99 | if (!vma) |
| @@ -144,7 +147,11 @@ good_area: | |||
| 144 | * make sure we exit gracefully rather than endlessly redo | 147 | * make sure we exit gracefully rather than endlessly redo |
| 145 | * the fault. | 148 | * the fault. |
| 146 | */ | 149 | */ |
| 147 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); | 150 | fault = handle_mm_fault(mm, vma, address, flags); |
| 151 | |||
| 152 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
| 153 | return; | ||
| 154 | |||
| 148 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | 155 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); |
| 149 | if (unlikely(fault & VM_FAULT_ERROR)) { | 156 | if (unlikely(fault & VM_FAULT_ERROR)) { |
| 150 | if (fault & VM_FAULT_OOM) | 157 | if (fault & VM_FAULT_OOM) |
| @@ -153,12 +160,27 @@ good_area: | |||
| 153 | goto do_sigbus; | 160 | goto do_sigbus; |
| 154 | BUG(); | 161 | BUG(); |
| 155 | } | 162 | } |
| 156 | if (fault & VM_FAULT_MAJOR) { | 163 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
| 157 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address); | 164 | if (fault & VM_FAULT_MAJOR) { |
| 158 | tsk->maj_flt++; | 165 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, |
| 159 | } else { | 166 | regs, address); |
| 160 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address); | 167 | tsk->maj_flt++; |
| 161 | tsk->min_flt++; | 168 | } else { |
| 169 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, | ||
| 170 | regs, address); | ||
| 171 | tsk->min_flt++; | ||
| 172 | } | ||
| 173 | if (fault & VM_FAULT_RETRY) { | ||
| 174 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
| 175 | |||
| 176 | /* | ||
| 177 | * No need to up_read(&mm->mmap_sem) as we would | ||
| 178 | * have already released it in __lock_page_or_retry | ||
| 179 | * in mm/filemap.c. | ||
| 180 | */ | ||
| 181 | |||
| 182 | goto retry; | ||
| 183 | } | ||
| 162 | } | 184 | } |
| 163 | 185 | ||
| 164 | up_read(&mm->mmap_sem); | 186 | up_read(&mm->mmap_sem); |
