diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2012-07-27 02:54:20 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-07-30 05:03:08 -0400 |
commit | f2c76e3b6f72c3fda290998109594dc490b8b087 (patch) | |
tree | c82f073d8c61ff212e34c90e8f3090abbb7ac967 /arch/s390/mm | |
parent | 216550e4fd5ade3f255bd5460db6b59e57f5f8c2 (diff) |
s390/mm: make page faults killable
This is the s390 variant of 37b23e05 "x86,mm: make pagefault killable".
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r-- | arch/s390/mm/fault.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 6a12d1bb6e09..2a34a1c35a7c 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #define VM_FAULT_BADCONTEXT 0x010000 | 49 | #define VM_FAULT_BADCONTEXT 0x010000 |
50 | #define VM_FAULT_BADMAP 0x020000 | 50 | #define VM_FAULT_BADMAP 0x020000 |
51 | #define VM_FAULT_BADACCESS 0x040000 | 51 | #define VM_FAULT_BADACCESS 0x040000 |
52 | #define VM_FAULT_SIGNAL 0x080000 | ||
52 | 53 | ||
53 | static unsigned long store_indication; | 54 | static unsigned long store_indication; |
54 | 55 | ||
@@ -229,6 +230,10 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault) | |||
229 | case VM_FAULT_BADCONTEXT: | 230 | case VM_FAULT_BADCONTEXT: |
230 | do_no_context(regs); | 231 | do_no_context(regs); |
231 | break; | 232 | break; |
233 | case VM_FAULT_SIGNAL: | ||
234 | if (!user_mode(regs)) | ||
235 | do_no_context(regs); | ||
236 | break; | ||
232 | default: /* fault & VM_FAULT_ERROR */ | 237 | default: /* fault & VM_FAULT_ERROR */ |
233 | if (fault & VM_FAULT_OOM) { | 238 | if (fault & VM_FAULT_OOM) { |
234 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) | 239 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) |
@@ -286,7 +291,7 @@ static inline int do_exception(struct pt_regs *regs, int access) | |||
286 | 291 | ||
287 | address = trans_exc_code & __FAIL_ADDR_MASK; | 292 | address = trans_exc_code & __FAIL_ADDR_MASK; |
288 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | 293 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); |
289 | flags = FAULT_FLAG_ALLOW_RETRY; | 294 | flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; |
290 | if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400) | 295 | if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400) |
291 | flags |= FAULT_FLAG_WRITE; | 296 | flags |= FAULT_FLAG_WRITE; |
292 | down_read(&mm->mmap_sem); | 297 | down_read(&mm->mmap_sem); |
@@ -335,6 +340,11 @@ retry: | |||
335 | * the fault. | 340 | * the fault. |
336 | */ | 341 | */ |
337 | fault = handle_mm_fault(mm, vma, address, flags); | 342 | fault = handle_mm_fault(mm, vma, address, flags); |
343 | /* No reason to continue if interrupted by SIGKILL. */ | ||
344 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) { | ||
345 | fault = VM_FAULT_SIGNAL; | ||
346 | goto out; | ||
347 | } | ||
338 | if (unlikely(fault & VM_FAULT_ERROR)) | 348 | if (unlikely(fault & VM_FAULT_ERROR)) |
339 | goto out_up; | 349 | goto out_up; |
340 | 350 | ||