diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/Kconfig | 7 | ||||
-rw-r--r-- | arch/s390/kernel/traps.c | 31 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 32 |
3 files changed, 30 insertions, 40 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 0d8cd9bbe101..79d0ca086820 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -444,13 +444,6 @@ config FORCE_MAX_ZONEORDER | |||
444 | int | 444 | int |
445 | default "9" | 445 | default "9" |
446 | 446 | ||
447 | config PROCESS_DEBUG | ||
448 | bool "Show crashed user process info" | ||
449 | help | ||
450 | Say Y to print all process fault locations to the console. This is | ||
451 | a debugging option; you probably do not want to set it unless you | ||
452 | are an S390 port maintainer. | ||
453 | |||
454 | config PFAULT | 447 | config PFAULT |
455 | bool "Pseudo page fault support" | 448 | bool "Pseudo page fault support" |
456 | help | 449 | help |
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index e605f070610c..5d8f0f3d0250 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -46,13 +46,7 @@ | |||
46 | 46 | ||
47 | pgm_check_handler_t *pgm_check_table[128]; | 47 | pgm_check_handler_t *pgm_check_table[128]; |
48 | 48 | ||
49 | #ifdef CONFIG_SYSCTL | 49 | int show_unhandled_signals; |
50 | #ifdef CONFIG_PROCESS_DEBUG | ||
51 | int sysctl_userprocess_debug = 1; | ||
52 | #else | ||
53 | int sysctl_userprocess_debug = 0; | ||
54 | #endif | ||
55 | #endif | ||
56 | 50 | ||
57 | extern pgm_check_handler_t do_protection_exception; | 51 | extern pgm_check_handler_t do_protection_exception; |
58 | extern pgm_check_handler_t do_dat_exception; | 52 | extern pgm_check_handler_t do_dat_exception; |
@@ -315,18 +309,19 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
315 | do_exit(SIGSEGV); | 309 | do_exit(SIGSEGV); |
316 | } | 310 | } |
317 | 311 | ||
318 | static void inline | 312 | static void inline report_user_fault(struct pt_regs *regs, long int_code, |
319 | report_user_fault(long interruption_code, struct pt_regs *regs) | 313 | int signr) |
320 | { | 314 | { |
321 | #if defined(CONFIG_SYSCTL) | 315 | if ((task_pid_nr(current) > 1) && !show_unhandled_signals) |
322 | if (!sysctl_userprocess_debug) | ||
323 | return; | 316 | return; |
324 | #endif | 317 | if (!unhandled_signal(current, signr)) |
325 | #if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG) | 318 | return; |
326 | printk("User process fault: interruption code 0x%lX\n", | 319 | if (!printk_ratelimit()) |
327 | interruption_code); | 320 | return; |
321 | printk("User process fault: interruption code 0x%lX ", int_code); | ||
322 | print_vma_addr("in ", regs->psw.addr & PSW_ADDR_INSN); | ||
323 | printk("\n"); | ||
328 | show_regs(regs); | 324 | show_regs(regs); |
329 | #endif | ||
330 | } | 325 | } |
331 | 326 | ||
332 | int is_valid_bugaddr(unsigned long addr) | 327 | int is_valid_bugaddr(unsigned long addr) |
@@ -354,7 +349,7 @@ static void __kprobes inline do_trap(long interruption_code, int signr, | |||
354 | 349 | ||
355 | tsk->thread.trap_no = interruption_code & 0xffff; | 350 | tsk->thread.trap_no = interruption_code & 0xffff; |
356 | force_sig_info(signr, info, tsk); | 351 | force_sig_info(signr, info, tsk); |
357 | report_user_fault(interruption_code, regs); | 352 | report_user_fault(regs, interruption_code, signr); |
358 | } else { | 353 | } else { |
359 | const struct exception_table_entry *fixup; | 354 | const struct exception_table_entry *fixup; |
360 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); | 355 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
@@ -390,7 +385,7 @@ static void default_trap_handler(struct pt_regs * regs, long interruption_code) | |||
390 | { | 385 | { |
391 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 386 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
392 | local_irq_enable(); | 387 | local_irq_enable(); |
393 | report_user_fault(interruption_code, regs); | 388 | report_user_fault(regs, interruption_code, SIGSEGV); |
394 | do_exit(SIGSEGV); | 389 | do_exit(SIGSEGV); |
395 | } else | 390 | } else |
396 | die("Unknown program exception", regs, interruption_code); | 391 | die("Unknown program exception", regs, interruption_code); |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 3040d7c78fe0..2505b2ea0ef1 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -48,10 +48,6 @@ | |||
48 | #define __PF_RES_FIELD 0x8000000000000000ULL | 48 | #define __PF_RES_FIELD 0x8000000000000000ULL |
49 | #endif /* CONFIG_64BIT */ | 49 | #endif /* CONFIG_64BIT */ |
50 | 50 | ||
51 | #ifdef CONFIG_SYSCTL | ||
52 | extern int sysctl_userprocess_debug; | ||
53 | #endif | ||
54 | |||
55 | #define VM_FAULT_BADCONTEXT 0x010000 | 51 | #define VM_FAULT_BADCONTEXT 0x010000 |
56 | #define VM_FAULT_BADMAP 0x020000 | 52 | #define VM_FAULT_BADMAP 0x020000 |
57 | #define VM_FAULT_BADACCESS 0x040000 | 53 | #define VM_FAULT_BADACCESS 0x040000 |
@@ -120,6 +116,22 @@ static inline int user_space_fault(unsigned long trans_exc_code) | |||
120 | return trans_exc_code != 3; | 116 | return trans_exc_code != 3; |
121 | } | 117 | } |
122 | 118 | ||
119 | static inline void report_user_fault(struct pt_regs *regs, long int_code, | ||
120 | int signr, unsigned long address) | ||
121 | { | ||
122 | if ((task_pid_nr(current) > 1) && !show_unhandled_signals) | ||
123 | return; | ||
124 | if (!unhandled_signal(current, signr)) | ||
125 | return; | ||
126 | if (!printk_ratelimit()) | ||
127 | return; | ||
128 | printk("User process fault: interruption code 0x%lX ", int_code); | ||
129 | print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN); | ||
130 | printk("\n"); | ||
131 | printk("failing address: %lX\n", address); | ||
132 | show_regs(regs); | ||
133 | } | ||
134 | |||
123 | /* | 135 | /* |
124 | * Send SIGSEGV to task. This is an external routine | 136 | * Send SIGSEGV to task. This is an external routine |
125 | * to keep the stack usage of do_page_fault small. | 137 | * to keep the stack usage of do_page_fault small. |
@@ -133,17 +145,7 @@ static noinline void do_sigsegv(struct pt_regs *regs, long int_code, | |||
133 | address = trans_exc_code & __FAIL_ADDR_MASK; | 145 | address = trans_exc_code & __FAIL_ADDR_MASK; |
134 | current->thread.prot_addr = address; | 146 | current->thread.prot_addr = address; |
135 | current->thread.trap_no = int_code; | 147 | current->thread.trap_no = int_code; |
136 | #if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG) | 148 | report_user_fault(regs, int_code, SIGSEGV, address); |
137 | #if defined(CONFIG_SYSCTL) | ||
138 | if (sysctl_userprocess_debug) | ||
139 | #endif | ||
140 | { | ||
141 | printk("User process fault: interruption code 0x%lX\n", | ||
142 | int_code); | ||
143 | printk("failing address: %lX\n", address); | ||
144 | show_regs(regs); | ||
145 | } | ||
146 | #endif | ||
147 | si.si_signo = SIGSEGV; | 149 | si.si_signo = SIGSEGV; |
148 | si.si_code = si_code; | 150 | si.si_code = si_code; |
149 | si.si_addr = (void __user *) address; | 151 | si.si_addr = (void __user *) address; |