aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2010-10-25 10:10:35 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-10-25 10:10:19 -0400
commit36bf96801e3a2c4efae0bb8c1897a530fc9ca13e (patch)
treef509ae4845807edf2bf3c784ca5d26be1a12ca9b /arch/s390/mm
parent585b954e1f2fa325d425b0786e4525ac7c9ae575 (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/mm')
-rw-r--r--arch/s390/mm/fault.c14
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;