diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2010-10-25 16:10:35 +0200 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-10-25 16:10:19 +0200 |
commit | 36bf96801e3a2c4efae0bb8c1897a530fc9ca13e (patch) | |
tree | f509ae4845807edf2bf3c784ca5d26be1a12ca9b /arch/s390 | |
parent | [S390] cio: notify drivers of channel path events (diff) | |
download | linux-36bf96801e3a2c4efae0bb8c1897a530fc9ca13e.tar.xz linux-36bf96801e3a2c4efae0bb8c1897a530fc9ca13e.zip |
[S390] fix SIGBUS handling
Raise SIGBUS with a siginfo structure. Deliver BUS_ADRERR as si_code and
the address of the fault in the si_addr field.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/mm/fault.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index b49d12073f10..bae2c282221c 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -212,14 +212,21 @@ static noinline void do_sigbus(struct pt_regs *regs, long int_code, unsigned long trans_exc_code) { struct task_struct *tsk = current; + unsigned long address; + struct siginfo si; /* * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - tsk->thread.prot_addr = trans_exc_code & __FAIL_ADDR_MASK; + address = trans_exc_code & __FAIL_ADDR_MASK; + tsk->thread.prot_addr = address; tsk->thread.trap_no = int_code; - force_sig(SIGBUS, tsk); + si.si_signo = SIGBUS; + si.si_errno = 0; + si.si_code = BUS_ADRERR; + si.si_addr = (void __user *) address; + force_sig_info(SIGBUS, &si, tsk); } #ifdef CONFIG_S390_EXEC_PROTECT @@ -279,10 +286,11 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code, if (fault & VM_FAULT_OOM) pagefault_out_of_memory(); else if (fault & VM_FAULT_SIGBUS) { - do_sigbus(regs, int_code, trans_exc_code); /* Kernel mode? Handle exceptions or die */ if (!(regs->psw.mask & PSW_MASK_PSTATE)) do_no_context(regs, int_code, trans_exc_code); + else + do_sigbus(regs, int_code, trans_exc_code); } else BUG(); break; |