Commit 99583181 authored by Heiko Carstens's avatar Heiko Carstens

[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: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
parent b3966378
...@@ -245,9 +245,12 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code, ...@@ -245,9 +245,12 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code,
do_no_context(regs, int_code, trans_exc_code); do_no_context(regs, int_code, trans_exc_code);
break; break;
default: /* fault & VM_FAULT_ERROR */ default: /* fault & VM_FAULT_ERROR */
if (fault & VM_FAULT_OOM) if (fault & VM_FAULT_OOM) {
pagefault_out_of_memory(); if (!(regs->psw.mask & PSW_MASK_PSTATE))
else if (fault & VM_FAULT_SIGBUS) { do_no_context(regs, int_code, trans_exc_code);
else
pagefault_out_of_memory();
} else if (fault & VM_FAULT_SIGBUS) {
/* Kernel mode? Handle exceptions or die */ /* Kernel mode? Handle exceptions or die */
if (!(regs->psw.mask & PSW_MASK_PSTATE)) if (!(regs->psw.mask & PSW_MASK_PSTATE))
do_no_context(regs, int_code, trans_exc_code); 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,10 +432,9 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
access = write ? VM_WRITE : VM_READ; access = write ? VM_WRITE : VM_READ;
fault = do_exception(&regs, access, uaddr | 2); fault = do_exception(&regs, access, uaddr | 2);
if (unlikely(fault)) { if (unlikely(fault)) {
if (fault & VM_FAULT_OOM) { if (fault & VM_FAULT_OOM)
pagefault_out_of_memory(); return -EFAULT;
fault = 0; else if (fault & VM_FAULT_SIGBUS)
} else if (fault & VM_FAULT_SIGBUS)
do_sigbus(&regs, pgm_int_code, uaddr); do_sigbus(&regs, pgm_int_code, uaddr);
} }
return fault ? -EFAULT : 0; return fault ? -EFAULT : 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment