x86/cpu.c: unhandled page fault: print pre-fault stack
Do basic manual unwinding and print raw stack addresses, with a suggested invocation of addr2line to pretty-print the result.
This commit is contained in:
@ -1205,6 +1205,10 @@ void ihk_mc_delay_us(int us)
|
||||
arch_delay(us);
|
||||
}
|
||||
|
||||
void arch_print_stack()
|
||||
{
|
||||
}
|
||||
|
||||
void arch_show_interrupt_context(const void *reg)
|
||||
{
|
||||
const struct pt_regs *regs = (struct pt_regs *)reg;
|
||||
|
||||
@ -1490,6 +1490,69 @@ void arch_show_extended_context(void)
|
||||
}
|
||||
}
|
||||
|
||||
struct stack {
|
||||
struct stack *rbp;
|
||||
unsigned long eip;
|
||||
};
|
||||
|
||||
/* KPRINTF_LOCAL_BUF_LEN is 1024, useless to go further */
|
||||
#define STACK_BUF_LEN (1024-sizeof("[ 0]: "))
|
||||
static void __print_stack(struct stack *rbp, unsigned long first) {
|
||||
char buf[STACK_BUF_LEN];
|
||||
size_t len;
|
||||
|
||||
/* Build string in buffer to output a single line */
|
||||
len = snprintf(buf, STACK_BUF_LEN,
|
||||
"addr2line -e smp-x86/kernel/mckernel.img -fpia");
|
||||
|
||||
if (first)
|
||||
len += snprintf(buf + len, STACK_BUF_LEN - len,
|
||||
" %#16lx", first);
|
||||
|
||||
while ((unsigned long)rbp > 0xffff880000000000 &&
|
||||
STACK_BUF_LEN - len > sizeof(" 0x0123456789abcdef")) {
|
||||
len += snprintf(buf + len, STACK_BUF_LEN - len,
|
||||
" %#16lx", rbp->eip);
|
||||
rbp = rbp->rbp;
|
||||
}
|
||||
__kprintf("%s\n", buf);
|
||||
}
|
||||
|
||||
void arch_print_pre_interrupt_stack(const struct x86_basic_regs *regs) {
|
||||
struct stack *rbp;
|
||||
|
||||
/* only for kernel stack */
|
||||
if (regs->error & PF_USER)
|
||||
return;
|
||||
|
||||
__kprintf("Pre-interrupt stack trace:\n");
|
||||
|
||||
/* interrupt stack heuristics:
|
||||
* - the first entry looks like it is always garbage, so skip.
|
||||
* (that is done by taking regs->rsp instead of ®s->rsp)
|
||||
* - that still looks sometimes wrong. For now, if it is not
|
||||
* within 64k of itself, look for the next entry that matches.
|
||||
*/
|
||||
|
||||
rbp = (struct stack*)regs->rsp;
|
||||
|
||||
while ((uintptr_t)rbp > (uintptr_t)rbp->rbp
|
||||
|| (uintptr_t)rbp + 0x10000 < (uintptr_t)rbp->rbp)
|
||||
rbp = (struct stack *)(((uintptr_t *)rbp) + 1);
|
||||
|
||||
__print_stack(rbp, regs->rip);
|
||||
}
|
||||
|
||||
void arch_print_stack() {
|
||||
struct stack *rbp;
|
||||
|
||||
__kprintf("Approximative stack trace:\n");
|
||||
|
||||
asm("mov %%rbp, %0" : "=r"(rbp) );
|
||||
|
||||
__print_stack(rbp, 0);
|
||||
}
|
||||
|
||||
/*@
|
||||
@ requires \valid(reg);
|
||||
@ assigns \nothing;
|
||||
@ -1521,6 +1584,8 @@ void arch_show_interrupt_context(const void *reg)
|
||||
|
||||
arch_show_extended_context();
|
||||
|
||||
arch_print_pre_interrupt_stack(regs);
|
||||
|
||||
kprintf_unlock(irqflags);
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
extern struct cpu_local_var *clv;
|
||||
extern void eventfd(int type);
|
||||
extern void arch_print_stack();
|
||||
|
||||
void panic(const char *msg)
|
||||
{
|
||||
@ -16,7 +17,9 @@ void panic(const char *msg)
|
||||
}
|
||||
cpu_disable_interrupt();
|
||||
|
||||
kprintf(msg);
|
||||
kprintf("%s\n", msg);
|
||||
|
||||
arch_print_stack();
|
||||
|
||||
while (1) {
|
||||
cpu_halt();
|
||||
|
||||
Reference in New Issue
Block a user