aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2011-05-26 03:48:29 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2011-05-26 03:48:25 -0400
commit99583181cbf2252dd0554eef6f419a6b22cd33ea (patch)
treebb8ff8673b3415318236a6efe0a8c5081ef32815 /arch/s390/mm
parentb396637841fff79e9520514e8dcbe769c20a2ea0 (diff)
[S390] mm: handle kernel caused page fault oom situations
If e.g. copy_from_user() generates a page fault and the kernel runs into an OOM situation the system might lock up. If the OOM killer sends a SIG_KILL to the current process it can't handle it since it is stuck in a copy_from_user() - page fault loop. Fix this by adding the same fix as other architectures have. E.g. the x86 variant f86268 "x86/mm: Handle mm_fault_error() in kernel space" Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/fault.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 105fa1071435..b57723aee848 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -245,9 +245,12 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code,
245 do_no_context(regs, int_code, trans_exc_code); 245 do_no_context(regs, int_code, trans_exc_code);
246 break; 246 break;
247 default: /* fault & VM_FAULT_ERROR */ 247 default: /* fault & VM_FAULT_ERROR */
248 if (fault & VM_FAULT_OOM) 248 if (fault & VM_FAULT_OOM) {
249 pagefault_out_of_memory(); 249 if (!(regs->psw.mask & PSW_MASK_PSTATE))
250 else if (fault & VM_FAULT_SIGBUS) { 250 do_no_context(regs, int_code, trans_exc_code);
251 else
252 pagefault_out_of_memory();
253 } else if (fault & VM_FAULT_SIGBUS) {
251 /* Kernel mode? Handle exceptions or die */ 254 /* Kernel mode? Handle exceptions or die */
252 if (!(regs->psw.mask & PSW_MASK_PSTATE)) 255 if (!(regs->psw.mask & PSW_MASK_PSTATE))
253 do_no_context(regs, int_code, trans_exc_code); 256 do_no_context(regs, int_code, trans_exc_code);
@@ -429,10 +432,9 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
429 access = write ? VM_WRITE : VM_READ; 432 access = write ? VM_WRITE : VM_READ;
430 fault = do_exception(&regs, access, uaddr | 2); 433 fault = do_exception(&regs, access, uaddr | 2);
431 if (unlikely(fault)) { 434 if (unlikely(fault)) {
432 if (fault & VM_FAULT_OOM) { 435 if (fault & VM_FAULT_OOM)
433 pagefault_out_of_memory(); 436 return -EFAULT;
434 fault = 0; 437 else if (fault & VM_FAULT_SIGBUS)
435 } else if (fault & VM_FAULT_SIGBUS)
436 do_sigbus(&regs, pgm_int_code, uaddr); 438 do_sigbus(&regs, pgm_int_code, uaddr);
437 } 439 }
438 return fault ? -EFAULT : 0; 440 return fault ? -EFAULT : 0;