aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm/fault.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm/fault.c')
-rw-r--r--arch/s390/mm/fault.c107
1 files changed, 48 insertions, 59 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index a9a301866b3c..354dd39073ef 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -125,8 +125,7 @@ static inline int user_space_fault(unsigned long trans_exc_code)
125 return trans_exc_code != 3; 125 return trans_exc_code != 3;
126} 126}
127 127
128static inline void report_user_fault(struct pt_regs *regs, long int_code, 128static inline void report_user_fault(struct pt_regs *regs, long signr)
129 int signr, unsigned long address)
130{ 129{
131 if ((task_pid_nr(current) > 1) && !show_unhandled_signals) 130 if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
132 return; 131 return;
@@ -134,10 +133,12 @@ static inline void report_user_fault(struct pt_regs *regs, long int_code,
134 return; 133 return;
135 if (!printk_ratelimit()) 134 if (!printk_ratelimit())
136 return; 135 return;
137 printk("User process fault: interruption code 0x%lX ", int_code); 136 printk(KERN_ALERT "User process fault: interruption code 0x%X ",
137 regs->int_code);
138 print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN); 138 print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN);
139 printk("\n"); 139 printk(KERN_CONT "\n");
140 printk("failing address: %lX\n", address); 140 printk(KERN_ALERT "failing address: %lX\n",
141 regs->int_parm_long & __FAIL_ADDR_MASK);
141 show_regs(regs); 142 show_regs(regs);
142} 143}
143 144
@@ -145,24 +146,18 @@ static inline void report_user_fault(struct pt_regs *regs, long int_code,
145 * Send SIGSEGV to task. This is an external routine 146 * Send SIGSEGV to task. This is an external routine
146 * to keep the stack usage of do_page_fault small. 147 * to keep the stack usage of do_page_fault small.
147 */ 148 */
148static noinline void do_sigsegv(struct pt_regs *regs, long int_code, 149static noinline void do_sigsegv(struct pt_regs *regs, int si_code)
149 int si_code, unsigned long trans_exc_code)
150{ 150{
151 struct siginfo si; 151 struct siginfo si;
152 unsigned long address;
153 152
154 address = trans_exc_code & __FAIL_ADDR_MASK; 153 report_user_fault(regs, SIGSEGV);
155 current->thread.prot_addr = address;
156 current->thread.trap_no = int_code;
157 report_user_fault(regs, int_code, SIGSEGV, address);
158 si.si_signo = SIGSEGV; 154 si.si_signo = SIGSEGV;
159 si.si_code = si_code; 155 si.si_code = si_code;
160 si.si_addr = (void __user *) address; 156 si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK);
161 force_sig_info(SIGSEGV, &si, current); 157 force_sig_info(SIGSEGV, &si, current);
162} 158}
163 159
164static noinline void do_no_context(struct pt_regs *regs, long int_code, 160static noinline void do_no_context(struct pt_regs *regs)
165 unsigned long trans_exc_code)
166{ 161{
167 const struct exception_table_entry *fixup; 162 const struct exception_table_entry *fixup;
168 unsigned long address; 163 unsigned long address;
@@ -178,55 +173,48 @@ static noinline void do_no_context(struct pt_regs *regs, long int_code,
178 * Oops. The kernel tried to access some bad page. We'll have to 173 * Oops. The kernel tried to access some bad page. We'll have to
179 * terminate things with extreme prejudice. 174 * terminate things with extreme prejudice.
180 */ 175 */
181 address = trans_exc_code & __FAIL_ADDR_MASK; 176 address = regs->int_parm_long & __FAIL_ADDR_MASK;
182 if (!user_space_fault(trans_exc_code)) 177 if (!user_space_fault(regs->int_parm_long))
183 printk(KERN_ALERT "Unable to handle kernel pointer dereference" 178 printk(KERN_ALERT "Unable to handle kernel pointer dereference"
184 " at virtual kernel address %p\n", (void *)address); 179 " at virtual kernel address %p\n", (void *)address);
185 else 180 else
186 printk(KERN_ALERT "Unable to handle kernel paging request" 181 printk(KERN_ALERT "Unable to handle kernel paging request"
187 " at virtual user address %p\n", (void *)address); 182 " at virtual user address %p\n", (void *)address);
188 183
189 die("Oops", regs, int_code); 184 die(regs, "Oops");
190 do_exit(SIGKILL); 185 do_exit(SIGKILL);
191} 186}
192 187
193static noinline void do_low_address(struct pt_regs *regs, long int_code, 188static noinline void do_low_address(struct pt_regs *regs)
194 unsigned long trans_exc_code)
195{ 189{
196 /* Low-address protection hit in kernel mode means 190 /* Low-address protection hit in kernel mode means
197 NULL pointer write access in kernel mode. */ 191 NULL pointer write access in kernel mode. */
198 if (regs->psw.mask & PSW_MASK_PSTATE) { 192 if (regs->psw.mask & PSW_MASK_PSTATE) {
199 /* Low-address protection hit in user mode 'cannot happen'. */ 193 /* Low-address protection hit in user mode 'cannot happen'. */
200 die ("Low-address protection", regs, int_code); 194 die (regs, "Low-address protection");
201 do_exit(SIGKILL); 195 do_exit(SIGKILL);
202 } 196 }
203 197
204 do_no_context(regs, int_code, trans_exc_code); 198 do_no_context(regs);
205} 199}
206 200
207static noinline void do_sigbus(struct pt_regs *regs, long int_code, 201static noinline void do_sigbus(struct pt_regs *regs)
208 unsigned long trans_exc_code)
209{ 202{
210 struct task_struct *tsk = current; 203 struct task_struct *tsk = current;
211 unsigned long address;
212 struct siginfo si; 204 struct siginfo si;
213 205
214 /* 206 /*
215 * Send a sigbus, regardless of whether we were in kernel 207 * Send a sigbus, regardless of whether we were in kernel
216 * or user mode. 208 * or user mode.
217 */ 209 */
218 address = trans_exc_code & __FAIL_ADDR_MASK;
219 tsk->thread.prot_addr = address;
220 tsk->thread.trap_no = int_code;
221 si.si_signo = SIGBUS; 210 si.si_signo = SIGBUS;
222 si.si_errno = 0; 211 si.si_errno = 0;
223 si.si_code = BUS_ADRERR; 212 si.si_code = BUS_ADRERR;
224 si.si_addr = (void __user *) address; 213 si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK);
225 force_sig_info(SIGBUS, &si, tsk); 214 force_sig_info(SIGBUS, &si, tsk);
226} 215}
227 216
228static noinline void do_fault_error(struct pt_regs *regs, long int_code, 217static noinline void do_fault_error(struct pt_regs *regs, int fault)
229 unsigned long trans_exc_code, int fault)
230{ 218{
231 int si_code; 219 int si_code;
232 220
@@ -238,24 +226,24 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code,
238 /* User mode accesses just cause a SIGSEGV */ 226 /* User mode accesses just cause a SIGSEGV */
239 si_code = (fault == VM_FAULT_BADMAP) ? 227 si_code = (fault == VM_FAULT_BADMAP) ?
240 SEGV_MAPERR : SEGV_ACCERR; 228 SEGV_MAPERR : SEGV_ACCERR;
241 do_sigsegv(regs, int_code, si_code, trans_exc_code); 229 do_sigsegv(regs, si_code);
242 return; 230 return;
243 } 231 }
244 case VM_FAULT_BADCONTEXT: 232 case VM_FAULT_BADCONTEXT:
245 do_no_context(regs, int_code, trans_exc_code); 233 do_no_context(regs);
246 break; 234 break;
247 default: /* fault & VM_FAULT_ERROR */ 235 default: /* fault & VM_FAULT_ERROR */
248 if (fault & VM_FAULT_OOM) { 236 if (fault & VM_FAULT_OOM) {
249 if (!(regs->psw.mask & PSW_MASK_PSTATE)) 237 if (!(regs->psw.mask & PSW_MASK_PSTATE))
250 do_no_context(regs, int_code, trans_exc_code); 238 do_no_context(regs);
251 else 239 else
252 pagefault_out_of_memory(); 240 pagefault_out_of_memory();
253 } else if (fault & VM_FAULT_SIGBUS) { 241 } else if (fault & VM_FAULT_SIGBUS) {
254 /* Kernel mode? Handle exceptions or die */ 242 /* Kernel mode? Handle exceptions or die */
255 if (!(regs->psw.mask & PSW_MASK_PSTATE)) 243 if (!(regs->psw.mask & PSW_MASK_PSTATE))
256 do_no_context(regs, int_code, trans_exc_code); 244 do_no_context(regs);
257 else 245 else
258 do_sigbus(regs, int_code, trans_exc_code); 246 do_sigbus(regs);
259 } else 247 } else
260 BUG(); 248 BUG();
261 break; 249 break;
@@ -273,12 +261,12 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code,
273 * 11 Page translation -> Not present (nullification) 261 * 11 Page translation -> Not present (nullification)
274 * 3b Region third trans. -> Not present (nullification) 262 * 3b Region third trans. -> Not present (nullification)
275 */ 263 */
276static inline int do_exception(struct pt_regs *regs, int access, 264static inline int do_exception(struct pt_regs *regs, int access)
277 unsigned long trans_exc_code)
278{ 265{
279 struct task_struct *tsk; 266 struct task_struct *tsk;
280 struct mm_struct *mm; 267 struct mm_struct *mm;
281 struct vm_area_struct *vma; 268 struct vm_area_struct *vma;
269 unsigned long trans_exc_code;
282 unsigned long address; 270 unsigned long address;
283 unsigned int flags; 271 unsigned int flags;
284 int fault; 272 int fault;
@@ -288,6 +276,7 @@ static inline int do_exception(struct pt_regs *regs, int access,
288 276
289 tsk = current; 277 tsk = current;
290 mm = tsk->mm; 278 mm = tsk->mm;
279 trans_exc_code = regs->int_parm_long;
291 280
292 /* 281 /*
293 * Verify that the fault happened in user space, that 282 * Verify that the fault happened in user space, that
@@ -387,45 +376,46 @@ out:
387 return fault; 376 return fault;
388} 377}
389 378
390void __kprobes do_protection_exception(struct pt_regs *regs, long pgm_int_code, 379void __kprobes do_protection_exception(struct pt_regs *regs)
391 unsigned long trans_exc_code)
392{ 380{
381 unsigned long trans_exc_code;
393 int fault; 382 int fault;
394 383
384 trans_exc_code = regs->int_parm_long;
395 /* Protection exception is suppressing, decrement psw address. */ 385 /* Protection exception is suppressing, decrement psw address. */
396 regs->psw.addr = __rewind_psw(regs->psw, pgm_int_code >> 16); 386 regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
397 /* 387 /*
398 * Check for low-address protection. This needs to be treated 388 * Check for low-address protection. This needs to be treated
399 * as a special case because the translation exception code 389 * as a special case because the translation exception code
400 * field is not guaranteed to contain valid data in this case. 390 * field is not guaranteed to contain valid data in this case.
401 */ 391 */
402 if (unlikely(!(trans_exc_code & 4))) { 392 if (unlikely(!(trans_exc_code & 4))) {
403 do_low_address(regs, pgm_int_code, trans_exc_code); 393 do_low_address(regs);
404 return; 394 return;
405 } 395 }
406 fault = do_exception(regs, VM_WRITE, trans_exc_code); 396 fault = do_exception(regs, VM_WRITE);
407 if (unlikely(fault)) 397 if (unlikely(fault))
408 do_fault_error(regs, 4, trans_exc_code, fault); 398 do_fault_error(regs, fault);
409} 399}
410 400
411void __kprobes do_dat_exception(struct pt_regs *regs, long pgm_int_code, 401void __kprobes do_dat_exception(struct pt_regs *regs)
412 unsigned long trans_exc_code)
413{ 402{
414 int access, fault; 403 int access, fault;
415 404
416 access = VM_READ | VM_EXEC | VM_WRITE; 405 access = VM_READ | VM_EXEC | VM_WRITE;
417 fault = do_exception(regs, access, trans_exc_code); 406 fault = do_exception(regs, access);
418 if (unlikely(fault)) 407 if (unlikely(fault))
419 do_fault_error(regs, pgm_int_code & 255, trans_exc_code, fault); 408 do_fault_error(regs, fault);
420} 409}
421 410
422#ifdef CONFIG_64BIT 411#ifdef CONFIG_64BIT
423void __kprobes do_asce_exception(struct pt_regs *regs, long pgm_int_code, 412void __kprobes do_asce_exception(struct pt_regs *regs)
424 unsigned long trans_exc_code)
425{ 413{
426 struct mm_struct *mm = current->mm; 414 struct mm_struct *mm = current->mm;
427 struct vm_area_struct *vma; 415 struct vm_area_struct *vma;
416 unsigned long trans_exc_code;
428 417
418 trans_exc_code = regs->int_parm_long;
429 if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm)) 419 if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm))
430 goto no_context; 420 goto no_context;
431 421
@@ -440,12 +430,12 @@ void __kprobes do_asce_exception(struct pt_regs *regs, long pgm_int_code,
440 430
441 /* User mode accesses just cause a SIGSEGV */ 431 /* User mode accesses just cause a SIGSEGV */
442 if (regs->psw.mask & PSW_MASK_PSTATE) { 432 if (regs->psw.mask & PSW_MASK_PSTATE) {
443 do_sigsegv(regs, pgm_int_code, SEGV_MAPERR, trans_exc_code); 433 do_sigsegv(regs, SEGV_MAPERR);
444 return; 434 return;
445 } 435 }
446 436
447no_context: 437no_context:
448 do_no_context(regs, pgm_int_code, trans_exc_code); 438 do_no_context(regs);
449} 439}
450#endif 440#endif
451 441
@@ -459,14 +449,15 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
459 regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT; 449 regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
460 regs.psw.addr = (unsigned long) __builtin_return_address(0); 450 regs.psw.addr = (unsigned long) __builtin_return_address(0);
461 regs.psw.addr |= PSW_ADDR_AMODE; 451 regs.psw.addr |= PSW_ADDR_AMODE;
462 uaddr &= PAGE_MASK; 452 regs.int_code = pgm_int_code;
453 regs.int_parm_long = (uaddr & PAGE_MASK) | 2;
463 access = write ? VM_WRITE : VM_READ; 454 access = write ? VM_WRITE : VM_READ;
464 fault = do_exception(&regs, access, uaddr | 2); 455 fault = do_exception(&regs, access);
465 if (unlikely(fault)) { 456 if (unlikely(fault)) {
466 if (fault & VM_FAULT_OOM) 457 if (fault & VM_FAULT_OOM)
467 return -EFAULT; 458 return -EFAULT;
468 else if (fault & VM_FAULT_SIGBUS) 459 else if (fault & VM_FAULT_SIGBUS)
469 do_sigbus(&regs, pgm_int_code, uaddr); 460 do_sigbus(&regs);
470 } 461 }
471 return fault ? -EFAULT : 0; 462 return fault ? -EFAULT : 0;
472} 463}
@@ -509,7 +500,7 @@ int pfault_init(void)
509 .reserved = __PF_RES_FIELD }; 500 .reserved = __PF_RES_FIELD };
510 int rc; 501 int rc;
511 502
512 if (!MACHINE_IS_VM || pfault_disable) 503 if (pfault_disable)
513 return -1; 504 return -1;
514 asm volatile( 505 asm volatile(
515 " diag %1,%0,0x258\n" 506 " diag %1,%0,0x258\n"
@@ -530,7 +521,7 @@ void pfault_fini(void)
530 .refversn = 2, 521 .refversn = 2,
531 }; 522 };
532 523
533 if (!MACHINE_IS_VM || pfault_disable) 524 if (pfault_disable)
534 return; 525 return;
535 asm volatile( 526 asm volatile(
536 " diag %0,0,0x258\n" 527 " diag %0,0,0x258\n"
@@ -643,8 +634,6 @@ static int __init pfault_irq_init(void)
643{ 634{
644 int rc; 635 int rc;
645 636
646 if (!MACHINE_IS_VM)
647 return 0;
648 rc = register_external_interrupt(0x2603, pfault_interrupt); 637 rc = register_external_interrupt(0x2603, pfault_interrupt);
649 if (rc) 638 if (rc)
650 goto out_extint; 639 goto out_extint;