aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/traps.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2012-10-18 12:10:06 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-11-23 05:14:25 -0500
commitb01a37a749916ef1765e4d65dee8b43fde8407b8 (patch)
tree421be52e05d061fa356a64b9cbabbfee7ebc68c7 /arch/s390/kernel/traps.c
parentf7817968d03df390d77d3af1b13298efa4f31047 (diff)
s390/traps: preinitialize program check table
Preinitialize the program check table, so we can put it into the read-only data section. Also use only four byte entries for the table, since each program check handler resides within the first 2GB. Therefore this reduces the size of the table by 50% on 64 bit builds. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/traps.c')
-rw-r--r--arch/s390/kernel/traps.c52
1 files changed, 7 insertions, 45 deletions
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 3d2b0fa37db0..70ecfc5fe8f0 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -41,8 +41,6 @@
41#include <asm/ipl.h> 41#include <asm/ipl.h>
42#include "entry.h" 42#include "entry.h"
43 43
44void (*pgm_check_table[128])(struct pt_regs *regs);
45
46int show_unhandled_signals = 1; 44int show_unhandled_signals = 1;
47 45
48#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) 46#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
@@ -350,7 +348,7 @@ void __kprobes do_per_trap(struct pt_regs *regs)
350 force_sig_info(SIGTRAP, &info, current); 348 force_sig_info(SIGTRAP, &info, current);
351} 349}
352 350
353static void default_trap_handler(struct pt_regs *regs) 351void default_trap_handler(struct pt_regs *regs)
354{ 352{
355 if (user_mode(regs)) { 353 if (user_mode(regs)) {
356 report_user_fault(regs, SIGSEGV); 354 report_user_fault(regs, SIGSEGV);
@@ -360,9 +358,9 @@ static void default_trap_handler(struct pt_regs *regs)
360} 358}
361 359
362#define DO_ERROR_INFO(name, signr, sicode, str) \ 360#define DO_ERROR_INFO(name, signr, sicode, str) \
363static void name(struct pt_regs *regs) \ 361void name(struct pt_regs *regs) \
364{ \ 362{ \
365 do_trap(regs, signr, sicode, str); \ 363 do_trap(regs, signr, sicode, str); \
366} 364}
367 365
368DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR, 366DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR,
@@ -417,7 +415,7 @@ static inline void do_fp_trap(struct pt_regs *regs, int fpc)
417 do_trap(regs, SIGFPE, si_code, "floating point exception"); 415 do_trap(regs, SIGFPE, si_code, "floating point exception");
418} 416}
419 417
420static void __kprobes illegal_op(struct pt_regs *regs) 418void __kprobes illegal_op(struct pt_regs *regs)
421{ 419{
422 siginfo_t info; 420 siginfo_t info;
423 __u8 opcode[6]; 421 __u8 opcode[6];
@@ -536,7 +534,7 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
536 "specification exception"); 534 "specification exception");
537#endif 535#endif
538 536
539static void data_exception(struct pt_regs *regs) 537void data_exception(struct pt_regs *regs)
540{ 538{
541 __u16 __user *location; 539 __u16 __user *location;
542 int signal = 0; 540 int signal = 0;
@@ -611,7 +609,7 @@ static void data_exception(struct pt_regs *regs)
611 do_trap(regs, signal, ILL_ILLOPN, "data exception"); 609 do_trap(regs, signal, ILL_ILLOPN, "data exception");
612} 610}
613 611
614static void space_switch_exception(struct pt_regs *regs) 612void space_switch_exception(struct pt_regs *regs)
615{ 613{
616 /* Set user psw back to home space mode. */ 614 /* Set user psw back to home space mode. */
617 if (user_mode(regs)) 615 if (user_mode(regs))
@@ -629,43 +627,7 @@ void __kprobes kernel_stack_overflow(struct pt_regs * regs)
629 panic("Corrupt kernel stack, can't continue."); 627 panic("Corrupt kernel stack, can't continue.");
630} 628}
631 629
632/* init is done in lowcore.S and head.S */
633
634void __init trap_init(void) 630void __init trap_init(void)
635{ 631{
636 int i;
637
638 for (i = 0; i < 128; i++)
639 pgm_check_table[i] = &default_trap_handler;
640 pgm_check_table[1] = &illegal_op;
641 pgm_check_table[2] = &privileged_op;
642 pgm_check_table[3] = &execute_exception;
643 pgm_check_table[4] = &do_protection_exception;
644 pgm_check_table[5] = &addressing_exception;
645 pgm_check_table[6] = &specification_exception;
646 pgm_check_table[7] = &data_exception;
647 pgm_check_table[8] = &overflow_exception;
648 pgm_check_table[9] = &divide_exception;
649 pgm_check_table[0x0A] = &overflow_exception;
650 pgm_check_table[0x0B] = &divide_exception;
651 pgm_check_table[0x0C] = &hfp_overflow_exception;
652 pgm_check_table[0x0D] = &hfp_underflow_exception;
653 pgm_check_table[0x0E] = &hfp_significance_exception;
654 pgm_check_table[0x0F] = &hfp_divide_exception;
655 pgm_check_table[0x10] = &do_dat_exception;
656 pgm_check_table[0x11] = &do_dat_exception;
657 pgm_check_table[0x12] = &translation_exception;
658 pgm_check_table[0x13] = &special_op_exception;
659#ifdef CONFIG_64BIT
660 pgm_check_table[0x18] = &transaction_exception;
661 pgm_check_table[0x38] = &do_asce_exception;
662 pgm_check_table[0x39] = &do_dat_exception;
663 pgm_check_table[0x3A] = &do_dat_exception;
664 pgm_check_table[0x3B] = &do_dat_exception;
665#endif /* CONFIG_64BIT */
666 pgm_check_table[0x15] = &operand_exception;
667 pgm_check_table[0x1C] = &space_switch_exception;
668 pgm_check_table[0x1D] = &hfp_sqrt_exception;
669 /* Enable machine checks early. */
670 local_mcck_enable(); 632 local_mcck_enable();
671} 633}