diff options
| -rw-r--r-- | arch/s390/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/entry.h | 21 | ||||
| -rw-r--r-- | arch/s390/kernel/entry64.S | 4 | ||||
| -rw-r--r-- | arch/s390/kernel/pgm_check.S | 152 | ||||
| -rw-r--r-- | arch/s390/kernel/traps.c | 52 | 
5 files changed, 182 insertions, 49 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 4da52fe31743..2ac311ef5c9b 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -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) diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index d0d3f69a7346..80ebb985f3b9 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h @@ -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); diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 07d8de353984..e42842a3072b 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -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 index 000000000000..14bdecb61923 --- /dev/null +++ b/arch/s390/kernel/pgm_check.S @@ -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 */ 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 @@  #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();  }  | 
