forked from Minki/linux
[S390] Improved oops output.
This patch adds two improvements to the oops output. First it adds an additional line after the PSW which decodes the different fields of it. Second a disassembler is added that decodes the instructions surrounding the faulting PSW. The output of a test oops now looks like this: kernel BUG at init/main.c:419 illegal operation: 0001 [#1] CPU: 0 Not tainted Process swapper (pid: 0, task: 0000000000464968, ksp: 00000000004be000) Krnl PSW : 0700000180000000 00000000000120b6 (rest_init+0x36/0x38) R:0 T:1 IO:1 EX:1 Key:0 M:0 W:0 P:0 AS:0 CC:0 PM:0 EA:3 Krnl GPRS: 0000000000000003 00000000004ba017 0000000000000022 0000000000000001 000000000003a5f6 0000000000000000 00000000004be6a8 0000000000000000 0000000000000000 00000000004b8200 0000000000003a50 0000000000008000 0000000000516368 000000000033d008 00000000000120b2 00000000004bdee0 Krnl Code: 00000000000120a6: e3e0f0980024 stg %r14,152(%r15) 00000000000120ac: c0e500014296 brasl %r14,3a5d8 00000000000120b2: a7f40001 brc 15,120b4 >00000000000120b6: 0707 bcr 0,%r7 00000000000120b8: eb7ff0500024 stmg %r7,%r15,80(%r15) 00000000000120be: c0d000195825 larl %r13,33d108 00000000000120c4: a7f13f00 tmll %r15,16128 00000000000120c8: a7840001 brc 8,120ca Call Trace: ([<00000000000120b2>] rest_init+0x32/0x38) [<00000000004be614>] start_kernel+0x37c/0x410 [<0000000000012020>] _ehead+0x20/0x80 Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
This commit is contained in:
parent
03ff9a235a
commit
bb11e3bdba
@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional
|
||||
|
||||
obj-y := bitmap.o traps.o time.o process.o base.o early.o \
|
||||
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
|
||||
semaphore.o s390_ext.o debug.o irq.o ipl.o
|
||||
semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o
|
||||
|
||||
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
|
||||
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
|
||||
|
1278
arch/s390/kernel/dis.c
Normal file
1278
arch/s390/kernel/dis.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -188,18 +188,31 @@ void dump_stack(void)
|
||||
|
||||
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]);
|
||||
@ -208,41 +221,7 @@ void show_registers(struct pt_regs *regs)
|
||||
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 */
|
||||
|
@ -196,6 +196,7 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
|
||||
extern char *task_show_regs(struct task_struct *task, char *buffer);
|
||||
|
||||
extern void show_registers(struct pt_regs *regs);
|
||||
extern void show_code(struct pt_regs *regs);
|
||||
extern void show_trace(struct task_struct *task, unsigned long *sp);
|
||||
|
||||
unsigned long get_wchan(struct task_struct *p);
|
||||
|
Loading…
Reference in New Issue
Block a user