diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2010-10-25 10:10:35 -0400 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-10-25 10:10:19 -0400 |
commit | 36bf96801e3a2c4efae0bb8c1897a530fc9ca13e (patch) | |
tree | f509ae4845807edf2bf3c784ca5d26be1a12ca9b /arch/s390 | |
parent | 585b954e1f2fa325d425b0786e4525ac7c9ae575 (diff) |
[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, | |||
212 | unsigned long trans_exc_code) | 212 | unsigned long trans_exc_code) |
213 | { | 213 | { |
214 | struct task_struct *tsk = current; | 214 | struct task_struct *tsk = current; |
215 | unsigned long address; | ||
216 | struct siginfo si; | ||
215 | 217 | ||
216 | /* | 218 | /* |
217 | * Send a sigbus, regardless of whether we were in kernel | 219 | * Send a sigbus, regardless of whether we were in kernel |
218 | * or user mode. | 220 | * or user mode. |
219 | */ | 221 | */ |
220 | tsk->thread.prot_addr = trans_exc_code & __FAIL_ADDR_MASK; | 222 | address = trans_exc_code & __FAIL_ADDR_MASK; |
223 | tsk->thread.prot_addr = address; | ||
221 | tsk->thread.trap_no = int_code; | 224 | tsk->thread.trap_no = int_code; |
222 | force_sig(SIGBUS, tsk); | 225 | si.si_signo = SIGBUS; |
226 | si.si_errno = 0; | ||
227 | si.si_code = BUS_ADRERR; | ||
228 | si.si_addr = (void __user *) address; | ||
229 | force_sig_info(SIGBUS, &si, tsk); | ||
223 | } | 230 | } |
224 | 231 | ||
225 | #ifdef CONFIG_S390_EXEC_PROTECT | 232 | #ifdef CONFIG_S390_EXEC_PROTECT |
@@ -279,10 +286,11 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code, | |||
279 | if (fault & VM_FAULT_OOM) | 286 | if (fault & VM_FAULT_OOM) |
280 | pagefault_out_of_memory(); | 287 | pagefault_out_of_memory(); |
281 | else if (fault & VM_FAULT_SIGBUS) { | 288 | else if (fault & VM_FAULT_SIGBUS) { |
282 | do_sigbus(regs, int_code, trans_exc_code); | ||
283 | /* Kernel mode? Handle exceptions or die */ | 289 | /* Kernel mode? Handle exceptions or die */ |
284 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) | 290 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) |
285 | do_no_context(regs, int_code, trans_exc_code); | 291 | do_no_context(regs, int_code, trans_exc_code); |
292 | else | ||
293 | do_sigbus(regs, int_code, trans_exc_code); | ||
286 | } else | 294 | } else |
287 | BUG(); | 295 | BUG(); |
288 | break; | 296 | break; |