#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/kdebug.h>
#include <linux/kallsyms.h>
#include <linux/reboot.h>
#include <linux/kprobes.h>
-
+#include <linux/bug.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/s390_ext.h>
#include <asm/lowcore.h>
#include <asm/debug.h>
-#include <asm/kdebug.h>
/* Called from entry.S only */
extern void handle_per_exception(struct pt_regs *regs);
static int kstack_depth_to_print = 20;
#endif /* CONFIG_64BIT */
-ATOMIC_NOTIFIER_HEAD(s390die_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_register(&s390die_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(&s390die_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
-
/*
* For show_trace we have tree different stack to consider:
* - the panic stack which is used if the kernel stack has overflown
EXPORT_SYMBOL(dump_stack);
+static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
+{
+ return (regs->psw.mask & bits) / ((~bits + 1) & bits);
+}
+
void show_registers(struct pt_regs *regs)
{
- mm_segment_t old_fs;
char *mode;
- int i;
mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl";
printk("%s PSW : %p %p",
mode, (void *) regs->psw.mask,
(void *) regs->psw.addr);
print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN);
- printk("%s GPRS: " FOURLONG, mode,
+ printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
+ "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
+ mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
+ mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY),
+ mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT),
+ mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
+ mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
+#ifdef CONFIG_64BIT
+ printk(" EA:%x", mask_bits(regs, PSW_BASE_BITS));
+#endif
+ printk("\n%s GPRS: " FOURLONG, mode,
regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
printk(" " FOURLONG,
regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
printk(" " FOURLONG,
regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
-#if 0
- /* FIXME: this isn't needed any more but it changes the ksymoops
- * input. To remove or not to remove ... */
- save_access_regs(regs->acrs);
- printk("%s ACRS: %08x %08x %08x %08x\n", mode,
- regs->acrs[0], regs->acrs[1], regs->acrs[2], regs->acrs[3]);
- printk(" %08x %08x %08x %08x\n",
- regs->acrs[4], regs->acrs[5], regs->acrs[6], regs->acrs[7]);
- printk(" %08x %08x %08x %08x\n",
- regs->acrs[8], regs->acrs[9], regs->acrs[10], regs->acrs[11]);
- printk(" %08x %08x %08x %08x\n",
- regs->acrs[12], regs->acrs[13], regs->acrs[14], regs->acrs[15]);
-#endif
-
- /*
- * Print the first 20 byte of the instruction stream at the
- * time of the fault.
- */
- old_fs = get_fs();
- if (regs->psw.mask & PSW_MASK_PSTATE)
- set_fs(USER_DS);
- else
- set_fs(KERNEL_DS);
- printk("%s Code: ", mode);
- for (i = 0; i < 20; i++) {
- unsigned char c;
- if (__get_user(c, (char __user *)(regs->psw.addr + i))) {
- printk(" Bad PSW.");
- break;
- }
- printk("%02x ", c);
- }
- set_fs(old_fs);
-
- printk("\n");
+ show_code(regs);
}
/* This is called from fs/proc/array.c */
#endif
}
+int is_valid_bugaddr(unsigned long addr)
+{
+ return 1;
+}
+
static void __kprobes inline do_trap(long interruption_code, int signr,
char *str, struct pt_regs *regs,
siginfo_t *info)
fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
if (fixup)
regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE;
- else
- die(str, regs, interruption_code);
+ else {
+ enum bug_trap_type btt;
+
+ btt = report_bug(regs->psw.addr & PSW_ADDR_INSN);
+ if (btt == BUG_TRAP_TYPE_WARN)
+ return;
+ die(str, regs, interruption_code);
+ }
}
}