Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP3:GA
crash.1433
crash-Fix-for-the-X86_64-bt-and-mach-commands-w...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File crash-Fix-for-the-X86_64-bt-and-mach-commands-when-running.patch of Package crash.1433
From e4cc9e7faf4517d049d2c997603015d08fe2c9e4 Mon Sep 17 00:00:00 2001 From: Dave Anderson <anderson@redhat.com> Date: Mon, 15 Dec 2014 15:23:52 -0500 Subject: [PATCH] Fix for the X86_64 "bt" and "mach" commands when running against kernels that have the following Linux 3.18 commit, which removes the special per-cpu exception stack for handling stack segment faults: commit 6f442be2fb22be02cafa606f1769fa1e6f894441 x86_64, traps: Stop using IST for #SS Without this patch, backtraces that originate on any of the other 4 per-cpu exception stacks will be mis-labeled at the transition point back to the previous stack. For example, backtraces that that originate on the NMI stack will indicate that they are coming from the "DOUBLEFAULT" stack. The patch examines all idt_table entries during initialization, looking for gate descriptors that have non-zero index values, and when found, pulls out out the handler function address; from that information, the exception stack name string array is properly initialized rather than being hard-coded. This fix also properly labels the exception stack names on x86_64 CONFIG_PREEMPT_RT realtime kernels, which only utilize 3 exception stacks instead of the traditional 5 (now 4 with this kernel commit), instead of just showing "RT". Also, without the patch, the "mach" command will mis-label the stack names when it displays the base addresses of each per-cpu exception stack. (anderson@redhat.com) --- defs.h | 5 +- x86_64.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 86 insertions(+), 32 deletions(-) --- a/defs.h +++ b/defs.h @@ -5042,14 +5042,15 @@ struct x86_64_pt_regs_offsets { }; #define MAX_EXCEPTION_STACKS 7 -#define NMI_STACK 2 /* ebase[] index to NMI exception stack */ -#define DEBUG_STACK 3 /* ebase[] index to DEBUG exception stack */ +#define NMI_STACK (machdep->machspec->stkinfo.NMI_stack_index) struct x86_64_stkinfo { ulong ebase[NR_CPUS][MAX_EXCEPTION_STACKS]; int esize[MAX_EXCEPTION_STACKS]; ulong ibase[NR_CPUS]; int isize; + int NMI_stack_index; + char *exception_stacks[MAX_EXCEPTION_STACKS]; }; struct machine_specific { --- a/x86_64.c +++ b/x86_64.c @@ -117,6 +117,7 @@ static void GART_init(void); struct machine_specific x86_64_machine_specific = { 0 }; +static void x86_64_exception_stacks_init(void); /* * Do all necessary machine-specific setup here. This is called several * times during initialization. @@ -796,6 +797,14 @@ x86_64_dump_machdep_table(ulong arg) ms->stkinfo.esize[5], ms->stkinfo.esize[6], machdep->flags & NO_TSS ? " (NO TSS) " : " "); + + fprintf(fp, " NMI_stack_index: %d\n", + ms->stkinfo.NMI_stack_index); + fprintf(fp, " exception_stacks:\n"); + for (i = 0; i < MAX_EXCEPTION_STACKS; i++) + fprintf(fp, " [%d]: %s\n", i, + ms->stkinfo.exception_stacks[i]); + fprintf(fp, " ebase[%s][%d]:", arg ? "NR_CPUS" : "cpus", MAX_EXCEPTION_STACKS); cpus = arg ? NR_CPUS : kt->cpus; @@ -1057,17 +1066,6 @@ x86_64_per_cpu_init(void) verify_spinlock(); } -static char * -x86_64_exception_stacks[MAX_EXCEPTION_STACKS] = { - "STACKFAULT", - "DOUBLEFAULT", - "NMI", - "DEBUG", - "MCE", - "(unknown)", - "(unknown)" -}; - /* * Gather the ist addresses for each CPU. */ @@ -1084,6 +1082,8 @@ x86_64_ist_init(void) tss_sp = per_cpu_symbol_search("per_cpu__init_tss"); ist_sp = per_cpu_symbol_search("per_cpu__orig_ist"); + x86_64_exception_stacks_init(); + if (!tss_sp && symbol_exists("init_tss")) { init_tss = symbol_value("init_tss"); @@ -1133,7 +1133,7 @@ x86_64_ist_init(void) if (ms->stkinfo.ebase[c][i] != estacks[i]) error(WARNING, "cpu %d %s stack: init_tss: %lx orig_ist: %lx\n", c, - x86_64_exception_stacks[i], + ms->stkinfo.exception_stacks[i], ms->stkinfo.ebase[c][i], estacks[i]); ms->stkinfo.ebase[c][i] = estacks[i]; } @@ -1163,22 +1163,12 @@ x86_64_ist_init(void) break; cnt++; if ((THIS_KERNEL_VERSION >= LINUX(2,6,18)) && - (i == DEBUG_STACK)) + STREQ(ms->stkinfo.exception_stacks[i], "DEBUG")) ms->stkinfo.esize[i] = esize*2; else ms->stkinfo.esize[i] = esize; ms->stkinfo.ebase[c][i] -= ms->stkinfo.esize[i]; } - /* - * RT kernel only uses 3 exception stacks for the 5 types. - */ - if ((c == 0) && (cnt == 3)) { - x86_64_exception_stacks[0] = "RT"; - x86_64_exception_stacks[1] = "RT"; - x86_64_exception_stacks[2] = "RT"; - x86_64_exception_stacks[3] = "(unknown)"; - x86_64_exception_stacks[4] = "(unknown)"; - } } /* @@ -2336,7 +2326,7 @@ x86_64_eframe_search(struct bt_info *bt) break; bt->hp->esp = ms->stkinfo.ebase[c][i]; fprintf(fp, "CPU %d %s EXCEPTION STACK:\n", - c, x86_64_exception_stacks[i]); + c, ms->stkinfo.exception_stacks[i]); if ((cnt = x86_64_eframe_search(bt))) fprintf(fp, "\n"); else @@ -3055,7 +3045,7 @@ in_exception_stack: if (!BT_REFERENCE_CHECK(bt)) fprintf(fp, "--- <%s exception stack> ---\n", - x86_64_exception_stacks[estack_index]); + ms->stkinfo.exception_stacks[estack_index]); /* * Find the CPU-saved, or handler-saved registers @@ -3104,7 +3094,7 @@ in_exception_stack: fprintf(ofp, " [ %s exception stack recursion: " "prior stack location overwritten ]\n", - x86_64_exception_stacks[estack_index]); + ms->stkinfo.exception_stacks[estack_index]); return; } @@ -4503,12 +4493,12 @@ skip_stage: bt->stacktop = ms->stkinfo.ebase[bt->tc->processor][estack] + ms->stkinfo.esize[estack]; console("x86_64_get_dumpfile_stack_frame: searching %s estack at %lx\n", - x86_64_exception_stacks[estack], bt->stackbase); + ms->stkinfo.exception_stacks[estack], bt->stackbase); if (!(bt->stackbase)) goto skip_stage; bt->stackbuf = ms->irqstack; alter_stackbuf(bt); - in_nmi_stack = STREQ(x86_64_exception_stacks[estack], "NMI"); + in_nmi_stack = STREQ(ms->stkinfo.exception_stacks[estack], "NMI"); goto next_stack; } @@ -4735,6 +4725,69 @@ x86_64_display_idt_table(void) FREEBUF(idt_table_buf); } +static void +x86_64_exception_stacks_init(void) +{ + char *idt_table_buf; + char buf[BUFSIZE]; + int i; + ulong *ip, ist; + long size; + struct machine_specific *ms; + + ms = machdep->machspec; + + ms->stkinfo.NMI_stack_index = -1; + for (i = 0; i < MAX_EXCEPTION_STACKS; i++) + ms->stkinfo.exception_stacks[i] = "(unknown)"; + + if (!kernel_symbol_exists("idt_table")) + return; + + if (INVALID_SIZE(gate_struct)) + size = 16; + else + size = SIZE(gate_struct); + + idt_table_buf = GETBUF(size * 256); + readmem(symbol_value("idt_table"), KVADDR, idt_table_buf, + size * 256, "idt_table", FAULT_ON_ERROR); + ip = (ulong *)idt_table_buf; + + if (CRASHDEBUG(1)) + fprintf(fp, "exception IST:\n"); + + for (i = 0; i < 256; i++, ip += 2) { + ist = ((*ip) >> 32) & 0x7; + if (ist) { + x86_64_extract_idt_function(ip, buf, NULL); + if (CRASHDEBUG(1)) + fprintf(fp, " %ld: %s\n", ist, buf); + if (strstr(buf, "nmi")) { + ms->stkinfo.NMI_stack_index = ist-1; + ms->stkinfo.exception_stacks[ist-1] = "NMI"; + } + if (strstr(buf, "debug")) + ms->stkinfo.exception_stacks[ist-1] = "DEBUG"; + if (strstr(buf, "stack")) + ms->stkinfo.exception_stacks[ist-1] = "STACKFAULT"; + if (strstr(buf, "double")) + ms->stkinfo.exception_stacks[ist-1] = "DOUBLEFAULT"; + if (strstr(buf, "machine")) + ms->stkinfo.exception_stacks[ist-1] = "MCE"; + } + } + + if (CRASHDEBUG(1)) { + fprintf(fp, "exception stacks:\n"); + for (i = 0; i < MAX_EXCEPTION_STACKS; i++) + fprintf(fp, " [%d]: %s\n", i, ms->stkinfo.exception_stacks[i]); + } + + FREEBUF(idt_table_buf); +} + + /* * Extract the function name out of the IDT entry. */ @@ -5048,9 +5101,9 @@ x86_64_display_machine_stats(void) if (machdep->machspec->stkinfo.ebase[0][i] == 0) break; fprintf(fp, "%11s STACK SIZE: %d\n", - x86_64_exception_stacks[i], + machdep->machspec->stkinfo.exception_stacks[i], machdep->machspec->stkinfo.esize[i]); - sprintf(buf, "%s STACKS:\n", x86_64_exception_stacks[i]); + sprintf(buf, "%s STACKS:\n", machdep->machspec->stkinfo.exception_stacks[i]); fprintf(fp, "%24s", buf); for (c = 0; c < kt->cpus; c++) { if (machdep->machspec->stkinfo.ebase[c][i] == 0)
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