]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
s390/traps: preinitialize program check table
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Thu, 18 Oct 2012 16:10:06 +0000 (18:10 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 24 Oct 2012 10:47:28 +0000 (12:47 +0200)
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>
arch/s390/kernel/Makefile
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/pgm_check.S [new file with mode: 0644]
arch/s390/kernel/traps.c

index 4da52fe317437e312e509b05d28a5d92ed681d5d..2ac311ef5c9b11a3b37aa4f5586a240aa14679a6 100644 (file)
@@ -23,7 +23,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 obj-y  :=  bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
            processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
            debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
-           sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o
+           sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
 
 obj-y  += $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y  += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
index d0d3f69a73463744edc3d3ec53fdd37dddd0adca..80ebb985f3b9b49335f58d7ca6609edca759b3e9 100644 (file)
@@ -6,7 +6,6 @@
 #include <asm/ptrace.h>
 #include <asm/cputime.h>
 
-extern void (*pgm_check_table[128])(struct pt_regs *);
 extern void *restart_stack;
 
 void system_call(void);
@@ -25,6 +24,26 @@ void do_protection_exception(struct pt_regs *regs);
 void do_dat_exception(struct pt_regs *regs);
 void do_asce_exception(struct pt_regs *regs);
 
+void addressing_exception(struct pt_regs *regs);
+void data_exception(struct pt_regs *regs);
+void default_trap_handler(struct pt_regs *regs);
+void divide_exception(struct pt_regs *regs);
+void execute_exception(struct pt_regs *regs);
+void hfp_divide_exception(struct pt_regs *regs);
+void hfp_overflow_exception(struct pt_regs *regs);
+void hfp_significance_exception(struct pt_regs *regs);
+void hfp_sqrt_exception(struct pt_regs *regs);
+void hfp_underflow_exception(struct pt_regs *regs);
+void illegal_op(struct pt_regs *regs);
+void operand_exception(struct pt_regs *regs);
+void overflow_exception(struct pt_regs *regs);
+void privileged_op(struct pt_regs *regs);
+void space_switch_exception(struct pt_regs *regs);
+void special_op_exception(struct pt_regs *regs);
+void specification_exception(struct pt_regs *regs);
+void transaction_exception(struct pt_regs *regs);
+void translation_exception(struct pt_regs *regs);
+
 void do_per_trap(struct pt_regs *regs);
 void syscall_trace(struct pt_regs *regs, int entryexit);
 void kernel_stack_overflow(struct pt_regs * regs);
index 07d8de353984da0fd8c8792348cebba214391c0c..e42842a3072b37b80ca09cb0a96cdd999c016ba3 100644 (file)
@@ -429,9 +429,9 @@ ENTRY(pgm_check_handler)
        larl    %r1,pgm_check_table
        llgh    %r10,__PT_INT_CODE+2(%r11)
        nill    %r10,0x007f
-       sll     %r10,3
+       sll     %r10,2
        je      sysc_return
-       lg      %r1,0(%r10,%r1)         # load address of handler routine
+       lgf     %r1,0(%r10,%r1)         # load address of handler routine
        lgr     %r2,%r11                # pass pointer to pt_regs
        basr    %r14,%r1                # branch to interrupt-handler
        j       sysc_return
diff --git a/arch/s390/kernel/pgm_check.S b/arch/s390/kernel/pgm_check.S
new file mode 100644 (file)
index 0000000..14bdecb
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ *    Program check table.
+ *
+ *    Copyright IBM Corp. 2012
+ */
+
+#include <linux/linkage.h>
+
+#ifdef CONFIG_32BIT
+#define PGM_CHECK_64BIT(handler) .long default_trap_handler
+#else
+#define PGM_CHECK_64BIT(handler) .long handler
+#endif
+
+#define PGM_CHECK(handler)     .long handler
+#define PGM_CHECK_DEFAULT      PGM_CHECK(default_trap_handler)
+
+/*
+ * The program check table contains exactly 128 (0x00-0x7f) entries. Each
+ * line defines the 31 and/or 64 bit function to be called corresponding
+ * to the program check interruption code.
+ */
+.section .rodata, "a"
+ENTRY(pgm_check_table)
+PGM_CHECK_DEFAULT                      /* 00 */
+PGM_CHECK(illegal_op)                  /* 01 */
+PGM_CHECK(privileged_op)               /* 02 */
+PGM_CHECK(execute_exception)           /* 03 */
+PGM_CHECK(do_protection_exception)     /* 04 */
+PGM_CHECK(addressing_exception)                /* 05 */
+PGM_CHECK(specification_exception)     /* 06 */
+PGM_CHECK(data_exception)              /* 07 */
+PGM_CHECK(overflow_exception)          /* 08 */
+PGM_CHECK(divide_exception)            /* 09 */
+PGM_CHECK(overflow_exception)          /* 0a */
+PGM_CHECK(divide_exception)            /* 0b */
+PGM_CHECK(hfp_overflow_exception)      /* 0c */
+PGM_CHECK(hfp_underflow_exception)     /* 0d */
+PGM_CHECK(hfp_significance_exception)  /* 0e */
+PGM_CHECK(hfp_divide_exception)                /* 0f */
+PGM_CHECK(do_dat_exception)            /* 10 */
+PGM_CHECK(do_dat_exception)            /* 11 */
+PGM_CHECK(translation_exception)       /* 12 */
+PGM_CHECK(special_op_exception)                /* 13 */
+PGM_CHECK_DEFAULT                      /* 14 */
+PGM_CHECK(operand_exception)           /* 15 */
+PGM_CHECK_DEFAULT                      /* 16 */
+PGM_CHECK_DEFAULT                      /* 17 */
+PGM_CHECK_64BIT(transaction_exception) /* 18 */
+PGM_CHECK_DEFAULT                      /* 19 */
+PGM_CHECK_DEFAULT                      /* 1a */
+PGM_CHECK_DEFAULT                      /* 1b */
+PGM_CHECK(space_switch_exception)      /* 1c */
+PGM_CHECK(hfp_sqrt_exception)          /* 1d */
+PGM_CHECK_DEFAULT                      /* 1e */
+PGM_CHECK_DEFAULT                      /* 1f */
+PGM_CHECK_DEFAULT                      /* 20 */
+PGM_CHECK_DEFAULT                      /* 21 */
+PGM_CHECK_DEFAULT                      /* 22 */
+PGM_CHECK_DEFAULT                      /* 23 */
+PGM_CHECK_DEFAULT                      /* 24 */
+PGM_CHECK_DEFAULT                      /* 25 */
+PGM_CHECK_DEFAULT                      /* 26 */
+PGM_CHECK_DEFAULT                      /* 27 */
+PGM_CHECK_DEFAULT                      /* 28 */
+PGM_CHECK_DEFAULT                      /* 29 */
+PGM_CHECK_DEFAULT                      /* 2a */
+PGM_CHECK_DEFAULT                      /* 2b */
+PGM_CHECK_DEFAULT                      /* 2c */
+PGM_CHECK_DEFAULT                      /* 2d */
+PGM_CHECK_DEFAULT                      /* 2e */
+PGM_CHECK_DEFAULT                      /* 2f */
+PGM_CHECK_DEFAULT                      /* 30 */
+PGM_CHECK_DEFAULT                      /* 31 */
+PGM_CHECK_DEFAULT                      /* 32 */
+PGM_CHECK_DEFAULT                      /* 33 */
+PGM_CHECK_DEFAULT                      /* 34 */
+PGM_CHECK_DEFAULT                      /* 35 */
+PGM_CHECK_DEFAULT                      /* 36 */
+PGM_CHECK_DEFAULT                      /* 37 */
+PGM_CHECK_64BIT(do_asce_exception)     /* 38 */
+PGM_CHECK_64BIT(do_dat_exception)      /* 39 */
+PGM_CHECK_64BIT(do_dat_exception)      /* 3a */
+PGM_CHECK_64BIT(do_dat_exception)      /* 3b */
+PGM_CHECK_DEFAULT                      /* 3c */
+PGM_CHECK_DEFAULT                      /* 3d */
+PGM_CHECK_DEFAULT                      /* 3e */
+PGM_CHECK_DEFAULT                      /* 3f */
+PGM_CHECK_DEFAULT                      /* 40 */
+PGM_CHECK_DEFAULT                      /* 41 */
+PGM_CHECK_DEFAULT                      /* 42 */
+PGM_CHECK_DEFAULT                      /* 43 */
+PGM_CHECK_DEFAULT                      /* 44 */
+PGM_CHECK_DEFAULT                      /* 45 */
+PGM_CHECK_DEFAULT                      /* 46 */
+PGM_CHECK_DEFAULT                      /* 47 */
+PGM_CHECK_DEFAULT                      /* 48 */
+PGM_CHECK_DEFAULT                      /* 49 */
+PGM_CHECK_DEFAULT                      /* 4a */
+PGM_CHECK_DEFAULT                      /* 4b */
+PGM_CHECK_DEFAULT                      /* 4c */
+PGM_CHECK_DEFAULT                      /* 4d */
+PGM_CHECK_DEFAULT                      /* 4e */
+PGM_CHECK_DEFAULT                      /* 4f */
+PGM_CHECK_DEFAULT                      /* 50 */
+PGM_CHECK_DEFAULT                      /* 51 */
+PGM_CHECK_DEFAULT                      /* 52 */
+PGM_CHECK_DEFAULT                      /* 53 */
+PGM_CHECK_DEFAULT                      /* 54 */
+PGM_CHECK_DEFAULT                      /* 55 */
+PGM_CHECK_DEFAULT                      /* 56 */
+PGM_CHECK_DEFAULT                      /* 57 */
+PGM_CHECK_DEFAULT                      /* 58 */
+PGM_CHECK_DEFAULT                      /* 59 */
+PGM_CHECK_DEFAULT                      /* 5a */
+PGM_CHECK_DEFAULT                      /* 5b */
+PGM_CHECK_DEFAULT                      /* 5c */
+PGM_CHECK_DEFAULT                      /* 5d */
+PGM_CHECK_DEFAULT                      /* 5e */
+PGM_CHECK_DEFAULT                      /* 5f */
+PGM_CHECK_DEFAULT                      /* 60 */
+PGM_CHECK_DEFAULT                      /* 61 */
+PGM_CHECK_DEFAULT                      /* 62 */
+PGM_CHECK_DEFAULT                      /* 63 */
+PGM_CHECK_DEFAULT                      /* 64 */
+PGM_CHECK_DEFAULT                      /* 65 */
+PGM_CHECK_DEFAULT                      /* 66 */
+PGM_CHECK_DEFAULT                      /* 67 */
+PGM_CHECK_DEFAULT                      /* 68 */
+PGM_CHECK_DEFAULT                      /* 69 */
+PGM_CHECK_DEFAULT                      /* 6a */
+PGM_CHECK_DEFAULT                      /* 6b */
+PGM_CHECK_DEFAULT                      /* 6c */
+PGM_CHECK_DEFAULT                      /* 6d */
+PGM_CHECK_DEFAULT                      /* 6e */
+PGM_CHECK_DEFAULT                      /* 6f */
+PGM_CHECK_DEFAULT                      /* 70 */
+PGM_CHECK_DEFAULT                      /* 71 */
+PGM_CHECK_DEFAULT                      /* 72 */
+PGM_CHECK_DEFAULT                      /* 73 */
+PGM_CHECK_DEFAULT                      /* 74 */
+PGM_CHECK_DEFAULT                      /* 75 */
+PGM_CHECK_DEFAULT                      /* 76 */
+PGM_CHECK_DEFAULT                      /* 77 */
+PGM_CHECK_DEFAULT                      /* 78 */
+PGM_CHECK_DEFAULT                      /* 79 */
+PGM_CHECK_DEFAULT                      /* 7a */
+PGM_CHECK_DEFAULT                      /* 7b */
+PGM_CHECK_DEFAULT                      /* 7c */
+PGM_CHECK_DEFAULT                      /* 7d */
+PGM_CHECK_DEFAULT                      /* 7e */
+PGM_CHECK_DEFAULT                      /* 7f */
index 3d2b0fa37db09649f6bcf0861de452144c22b0da..70ecfc5fe8f0acc87b7fe0036df511f283b22dbe 100644 (file)
@@ -41,8 +41,6 @@
 #include <asm/ipl.h>
 #include "entry.h"
 
-void (*pgm_check_table[128])(struct pt_regs *regs);
-
 int show_unhandled_signals = 1;
 
 #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)
        force_sig_info(SIGTRAP, &info, current);
 }
 
-static void default_trap_handler(struct pt_regs *regs)
+void default_trap_handler(struct pt_regs *regs)
 {
        if (user_mode(regs)) {
                report_user_fault(regs, SIGSEGV);
@@ -360,9 +358,9 @@ static void default_trap_handler(struct pt_regs *regs)
 }
 
 #define DO_ERROR_INFO(name, signr, sicode, str) \
-static void name(struct pt_regs *regs) \
-{ \
-       do_trap(regs, signr, sicode, str); \
+void name(struct pt_regs *regs)                        \
+{                                              \
+       do_trap(regs, signr, sicode, str);      \
 }
 
 DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR,
@@ -417,7 +415,7 @@ static inline void do_fp_trap(struct pt_regs *regs, int fpc)
        do_trap(regs, SIGFPE, si_code, "floating point exception");
 }
 
-static void __kprobes illegal_op(struct pt_regs *regs)
+void __kprobes illegal_op(struct pt_regs *regs)
 {
        siginfo_t info;
         __u8 opcode[6];
@@ -536,7 +534,7 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
              "specification exception");
 #endif
 
-static void data_exception(struct pt_regs *regs)
+void data_exception(struct pt_regs *regs)
 {
        __u16 __user *location;
        int signal = 0;
@@ -611,7 +609,7 @@ static void data_exception(struct pt_regs *regs)
                do_trap(regs, signal, ILL_ILLOPN, "data exception");
 }
 
-static void space_switch_exception(struct pt_regs *regs)
+void space_switch_exception(struct pt_regs *regs)
 {
        /* Set user psw back to home space mode. */
        if (user_mode(regs))
@@ -629,43 +627,7 @@ void __kprobes kernel_stack_overflow(struct pt_regs * regs)
        panic("Corrupt kernel stack, can't continue.");
 }
 
-/* init is done in lowcore.S and head.S */
-
 void __init trap_init(void)
 {
-        int i;
-
-        for (i = 0; i < 128; i++)
-          pgm_check_table[i] = &default_trap_handler;
-        pgm_check_table[1] = &illegal_op;
-        pgm_check_table[2] = &privileged_op;
-        pgm_check_table[3] = &execute_exception;
-        pgm_check_table[4] = &do_protection_exception;
-        pgm_check_table[5] = &addressing_exception;
-        pgm_check_table[6] = &specification_exception;
-        pgm_check_table[7] = &data_exception;
-        pgm_check_table[8] = &overflow_exception;
-        pgm_check_table[9] = &divide_exception;
-        pgm_check_table[0x0A] = &overflow_exception;
-        pgm_check_table[0x0B] = &divide_exception;
-        pgm_check_table[0x0C] = &hfp_overflow_exception;
-        pgm_check_table[0x0D] = &hfp_underflow_exception;
-        pgm_check_table[0x0E] = &hfp_significance_exception;
-        pgm_check_table[0x0F] = &hfp_divide_exception;
-        pgm_check_table[0x10] = &do_dat_exception;
-        pgm_check_table[0x11] = &do_dat_exception;
-        pgm_check_table[0x12] = &translation_exception;
-        pgm_check_table[0x13] = &special_op_exception;
-#ifdef CONFIG_64BIT
-       pgm_check_table[0x18] = &transaction_exception;
-       pgm_check_table[0x38] = &do_asce_exception;
-       pgm_check_table[0x39] = &do_dat_exception;
-       pgm_check_table[0x3A] = &do_dat_exception;
-        pgm_check_table[0x3B] = &do_dat_exception;
-#endif /* CONFIG_64BIT */
-        pgm_check_table[0x15] = &operand_exception;
-        pgm_check_table[0x1C] = &space_switch_exception;
-        pgm_check_table[0x1D] = &hfp_sqrt_exception;
-       /* Enable machine checks early. */
        local_mcck_enable();
 }