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:
Dominique Martinet
2017-09-25 11:35:58 +09:00
parent b894619d1b
commit d4cd756a91
3 changed files with 73 additions and 1 deletions

View File

@ -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;

View File

@ -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 &regs->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);
}

View File

@ -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();