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>
This commit is contained in:
parent
f7817968d0
commit
b01a37a749
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
152
arch/s390/kernel/pgm_check.S
Normal file
152
arch/s390/kernel/pgm_check.S
Normal file
@ -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 */
|
@ -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] = ÷_exception;
|
||||
pgm_check_table[0x0A] = &overflow_exception;
|
||||
pgm_check_table[0x0B] = ÷_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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user