Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP1:Update
crash.4081
crash-x86_64-nested-nmi.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File crash-x86_64-nested-nmi.patch of Package crash.4081
From: Petr Tesarik <ptesarik@suse.cz> Subject: Fix NMI backtrace for kernels patched to handle nested NMIs References: bnc#874179 Patch-mainline: not yet Kernel commit 3f3c8b8c4b2a34776c3470142a7c8baafcda6eb0 changed the NMI stack layout, adding 12 more values on the stack. The fix has two parts: 1. Determine if this kernel has the nested NMI layout and set a machine-specific flag (NESTED_NMI) if it does. 2. When backtracing an NMI stack, use the saved values instead of those found at the top of stack. Additionally, kernel commit 28696f434fef0efa97534b59986ad33b9c4df7f8 changed the stack layout again, swapping the location of the "saved" and "copied" registers. This can be detected automatically, because the "copied" registers contain either a copy of the "saved" registers, or point to repeat_nmi. So, if restart_nmi is found as the return address, assume that this is the old layout and adjust the stack pointer again. Signed-off-by: Petr Tesarik <ptesarik@suse.cz> --- defs.h | 1 x86_64.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 57 insertions(+), 17 deletions(-) --- a/defs.h +++ b/defs.h @@ -5090,6 +5090,7 @@ struct machine_specific { #define VM_XEN_RHEL4 (0x100) #define FRAMEPOINTER (0x200) #define GART_REGION (0x400) +#define NESTED_NMI (0x800) #define VM_FLAGS (VM_ORIG|VM_2_6_11|VM_XEN|VM_XEN_RHEL4) --- a/x86_64.c +++ b/x86_64.c @@ -468,6 +468,8 @@ x86_64_init(int when) else x86_64_per_cpu_init(); x86_64_ist_init(); + if (symbol_exists("repeat_nmi")) + machdep->flags |= NESTED_NMI; machdep->in_alternate_stack = x86_64_in_alternate_stack; if ((machdep->machspec->irqstack = (char *) malloc(machdep->machspec->stkinfo.isize)) == NULL) @@ -3009,6 +3011,8 @@ in_exception_stack: } stacktop = bt->stacktop - SIZE(pt_regs); + if ((machdep->flags & NESTED_NMI) && estack_index == NMI_STACK) + stacktop -= 12*sizeof(ulong); bt->flags &= ~BT_FRAMESIZE_DISABLE; @@ -3046,21 +3050,37 @@ in_exception_stack: } cs = x86_64_exception_frame(EFRAME_PRINT|EFRAME_CS, 0, - bt->stackbuf + (bt->stacktop - bt->stackbase) - - SIZE(pt_regs), bt, ofp); + bt->stackbuf + (stacktop - bt->stackbase), + bt, ofp); if (!BT_REFERENCE_CHECK(bt)) fprintf(fp, "--- <%s exception stack> ---\n", x86_64_exception_stacks[estack_index]); - /* - * stack = (unsigned long *) estack_end[-2]; + /* + * Find the CPU-saved, or handler-saved registers */ up = (ulong *)(&bt->stackbuf[bt->stacktop - bt->stackbase]); - up -= 2; - rsp = bt->stkptr = *up; - up -= 3; - bt->instptr = *up; + up -= 5; + if ((machdep->flags & NESTED_NMI) && + estack_index == NMI_STACK && + bt->stkptr <= bt->stacktop - 17*sizeof(ulong)) { + up -= 12; + /* Copied and saved regs are swapped in pre-3.8 kernels */ + if (*up == symbol_value("repeat_nmi")) + up += 5; + } + + /* Registers (as saved by CPU): + * + * up[4] SS + * up[3] RSP + * up[2] RFLAGS + * up[1] CS + * up[0] RIP + */ + rsp = bt->stkptr = up[3]; + bt->instptr = up[0]; if (cs & 3) done = TRUE; /* user-mode exception */ else @@ -3513,27 +3533,46 @@ in_exception_stack: } stacktop = bt->stacktop - SIZE(pt_regs); - + if ((machdep->flags & NESTED_NMI) && + estack_index == NMI_STACK) + stacktop -= 12*sizeof(ulong); + if (!done) { level = dwarf_backtrace(bt, level, stacktop); done = TRUE; } cs = x86_64_exception_frame(EFRAME_PRINT|EFRAME_CS, 0, - bt->stackbuf + (bt->stacktop - bt->stackbase) - - SIZE(pt_regs), bt, ofp); + bt->stackbuf + (stacktop - bt->stackbase), + bt, ofp); if (!BT_REFERENCE_CHECK(bt)) fprintf(fp, "--- <exception stack> ---\n"); - /* - * stack = (unsigned long *) estack_end[-2]; + /* + * Find the CPU-saved, or handler-saved registers */ up = (ulong *)(&bt->stackbuf[bt->stacktop - bt->stackbase]); - up -= 2; - rsp = bt->stkptr = *up; - up -= 3; - bt->instptr = *up; + up -= 5; + if ((machdep->flags & NESTED_NMI) && + estack_index == NMI_STACK && + bt->stkptr <= bt->stacktop - 17*sizeof(ulong)) { + up -= 12; + /* Copied and saved regs are swapped in pre-3.8 kernels */ + if (*up == symbol_value("repeat_nmi")) + up += 5; + } + + /* Registers (as saved by CPU): + * + * up[4] SS + * up[3] RSP + * up[2] RFLAGS + * up[1] CS + * up[0] RIP + */ + rsp = bt->stkptr = up[3]; + bt->instptr = up[0]; if (cs & 3) done = TRUE; /* user-mode exception */ else
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor