aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/traps.c')
-rw-r--r--arch/s390/kernel/traps.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 01775c04a90e..3d2b0fa37db0 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -57,6 +57,23 @@ static int kstack_depth_to_print = 12;
57static int kstack_depth_to_print = 20; 57static int kstack_depth_to_print = 20;
58#endif /* CONFIG_64BIT */ 58#endif /* CONFIG_64BIT */
59 59
60static inline void __user *get_trap_ip(struct pt_regs *regs)
61{
62#ifdef CONFIG_64BIT
63 unsigned long address;
64
65 if (regs->int_code & 0x200)
66 address = *(unsigned long *)(current->thread.trap_tdb + 24);
67 else
68 address = regs->psw.addr;
69 return (void __user *)
70 ((address - (regs->int_code >> 16)) & PSW_ADDR_INSN);
71#else
72 return (void __user *)
73 ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN);
74#endif
75}
76
60/* 77/*
61 * For show_trace we have tree different stack to consider: 78 * For show_trace we have tree different stack to consider:
62 * - the panic stack which is used if the kernel stack has overflown 79 * - the panic stack which is used if the kernel stack has overflown
@@ -214,7 +231,6 @@ void show_registers(struct pt_regs *regs)
214 231
215void show_regs(struct pt_regs *regs) 232void show_regs(struct pt_regs *regs)
216{ 233{
217 print_modules();
218 printk("CPU: %d %s %s %.*s\n", 234 printk("CPU: %d %s %s %.*s\n",
219 task_thread_info(current)->cpu, print_tainted(), 235 task_thread_info(current)->cpu, print_tainted(),
220 init_utsname()->release, 236 init_utsname()->release,
@@ -254,6 +270,7 @@ void die(struct pt_regs *regs, const char *str)
254#endif 270#endif
255 printk("\n"); 271 printk("\n");
256 notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV); 272 notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
273 print_modules();
257 show_regs(regs); 274 show_regs(regs);
258 bust_spinlocks(0); 275 bust_spinlocks(0);
259 add_taint(TAINT_DIE); 276 add_taint(TAINT_DIE);
@@ -285,12 +302,6 @@ int is_valid_bugaddr(unsigned long addr)
285 return 1; 302 return 1;
286} 303}
287 304
288static inline void __user *get_psw_address(struct pt_regs *regs)
289{
290 return (void __user *)
291 ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN);
292}
293
294static void __kprobes do_trap(struct pt_regs *regs, 305static void __kprobes do_trap(struct pt_regs *regs,
295 int si_signo, int si_code, char *str) 306 int si_signo, int si_code, char *str)
296{ 307{
@@ -304,14 +315,14 @@ static void __kprobes do_trap(struct pt_regs *regs,
304 info.si_signo = si_signo; 315 info.si_signo = si_signo;
305 info.si_errno = 0; 316 info.si_errno = 0;
306 info.si_code = si_code; 317 info.si_code = si_code;
307 info.si_addr = get_psw_address(regs); 318 info.si_addr = get_trap_ip(regs);
308 force_sig_info(si_signo, &info, current); 319 force_sig_info(si_signo, &info, current);
309 report_user_fault(regs, si_signo); 320 report_user_fault(regs, si_signo);
310 } else { 321 } else {
311 const struct exception_table_entry *fixup; 322 const struct exception_table_entry *fixup;
312 fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); 323 fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
313 if (fixup) 324 if (fixup)
314 regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; 325 regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE;
315 else { 326 else {
316 enum bug_trap_type btt; 327 enum bug_trap_type btt;
317 328
@@ -381,6 +392,11 @@ DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN,
381DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, 392DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN,
382 "translation exception") 393 "translation exception")
383 394
395#ifdef CONFIG_64BIT
396DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN,
397 "transaction constraint exception")
398#endif
399
384static inline void do_fp_trap(struct pt_regs *regs, int fpc) 400static inline void do_fp_trap(struct pt_regs *regs, int fpc)
385{ 401{
386 int si_code = 0; 402 int si_code = 0;
@@ -408,7 +424,7 @@ static void __kprobes illegal_op(struct pt_regs *regs)
408 __u16 __user *location; 424 __u16 __user *location;
409 int signal = 0; 425 int signal = 0;
410 426
411 location = get_psw_address(regs); 427 location = get_trap_ip(regs);
412 428
413 if (user_mode(regs)) { 429 if (user_mode(regs)) {
414 if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) 430 if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
@@ -476,7 +492,7 @@ void specification_exception(struct pt_regs *regs)
476 __u16 __user *location = NULL; 492 __u16 __user *location = NULL;
477 int signal = 0; 493 int signal = 0;
478 494
479 location = (__u16 __user *) get_psw_address(regs); 495 location = (__u16 __user *) get_trap_ip(regs);
480 496
481 if (user_mode(regs)) { 497 if (user_mode(regs)) {
482 get_user(*((__u16 *) opcode), location); 498 get_user(*((__u16 *) opcode), location);
@@ -525,7 +541,7 @@ static void data_exception(struct pt_regs *regs)
525 __u16 __user *location; 541 __u16 __user *location;
526 int signal = 0; 542 int signal = 0;
527 543
528 location = get_psw_address(regs); 544 location = get_trap_ip(regs);
529 545
530 if (MACHINE_HAS_IEEE) 546 if (MACHINE_HAS_IEEE)
531 asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); 547 asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
@@ -641,6 +657,7 @@ void __init trap_init(void)
641 pgm_check_table[0x12] = &translation_exception; 657 pgm_check_table[0x12] = &translation_exception;
642 pgm_check_table[0x13] = &special_op_exception; 658 pgm_check_table[0x13] = &special_op_exception;
643#ifdef CONFIG_64BIT 659#ifdef CONFIG_64BIT
660 pgm_check_table[0x18] = &transaction_exception;
644 pgm_check_table[0x38] = &do_asce_exception; 661 pgm_check_table[0x38] = &do_asce_exception;
645 pgm_check_table[0x39] = &do_dat_exception; 662 pgm_check_table[0x39] = &do_dat_exception;
646 pgm_check_table[0x3A] = &do_dat_exception; 663 pgm_check_table[0x3A] = &do_dat_exception;