diff options
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; |