Hi Dave, The following upstream kernel git commit introduced a crash regression in v3.10-rc1 for s390x: commit dc7ee00d4771b3218b10e09e1071ee6eb176d381 Date: Wed Apr 24 10:20:43 2013 +0200 s390: lowcore stack pointer offsets Store the stack pointers in the lowcore for the kernel stack, the async stack and the panic stack with the offset required for the first user. This avoids an unnecessary add instruction on the system call path. - lc->async_stack = pcpu->async_stack + ASYNC_SIZE; - lc->panic_stack = pcpu->panic_stack + PAGE_SIZE; + lc->async_stack = pcpu->async_stack + ASYNC_SIZE + - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); + lc->panic_stack = pcpu->panic_stack + PAGE_SIZE + - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); The s390x crash code uses lowcore->panic/async_stack to find out the location of the per-cpu stacks. With the above kernel change this is no longer correct. For newer kernels with the "pcpu_devices" array there is a second location where the stacks are stored. With this patch we use the new location if available. Signed-off-by: Michael Holzheu <holzheu@xxxxxxxxxxxxxxxxxx> --- s390x.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) --- a/s390x.c +++ b/s390x.c @@ -913,10 +913,34 @@ s390x_get_lowcore(struct bt_info *bt, ch } /* + * Get stack address for interrupt stack using the pcpu array + */ +static unsigned long get_int_stack_pcpu(char *stack_name, int cpu) +{ + unsigned long addr; + + if (!MEMBER_EXISTS("pcpu", stack_name)) + return 0; + addr = symbol_value("pcpu_devices") + + cpu * STRUCT_SIZE("pcpu") + MEMBER_OFFSET("pcpu", stack_name); + return readmem_ul(addr) + INT_STACK_SIZE; +} + +/* + * Get stack address for interrupt stack using the lowcore + */ +static unsigned long get_int_stack_lc(char *stack_name, char *lc) +{ + if (!MEMBER_EXISTS(lc_struct, stack_name)) + return 0; + return ULONG(lc + MEMBER_OFFSET(lc_struct, stack_name)); +} + +/* * Read interrupt stack (either "async_stack" or "panic_stack"); */ -static void get_int_stack(char *stack_name, char *lc, unsigned long *start, - unsigned long *end) +static void get_int_stack(char *stack_name, int cpu, char *lc, + unsigned long *start, unsigned long *end) { unsigned long stack_addr; @@ -925,9 +949,10 @@ static void get_int_stack(char *stack_na stack_addr = symbol_value("restart_stack"); stack_addr = readmem_ul(stack_addr); } else { - if (!MEMBER_EXISTS(lc_struct, stack_name)) - return; - stack_addr = ULONG(lc + MEMBER_OFFSET(lc_struct, stack_name)); + if (symbol_exists("pcpu_devices")) + stack_addr = get_int_stack_pcpu(stack_name, cpu); + else + stack_addr = get_int_stack_lc(stack_name, lc); } if (stack_addr == 0) return; @@ -1157,12 +1182,13 @@ static void s390x_back_trace_cmd(struct s390x_print_lowcore(lowcore,bt,1); fprintf(fp,"\n"); if (symbol_exists("restart_stack")) { - get_int_stack("restart_stack", lowcore, &low, &high); + get_int_stack("restart_stack", + cpu, lowcore, &low, &high); sp = show_trace(bt, cnt, sp, low, high); } - get_int_stack("panic_stack", lowcore, &low, &high); + get_int_stack("panic_stack", cpu, lowcore, &low, &high); sp = show_trace(bt, cnt, sp, low, high); - get_int_stack("async_stack", lowcore, &low, &high); + get_int_stack("async_stack", cpu, lowcore, &low, &high); sp = show_trace(bt, cnt, sp, low, high); } /*
[PATCH] s390x: Fix linux-3.10 backtrace for interrupt stacks The following upstream kernel git commit introduced a crash regression in v3.10-rc1 for s390x: commit dc7ee00d4771b3218b10e09e1071ee6eb176d381 Date: Wed Apr 24 10:20:43 2013 +0200 s390: lowcore stack pointer offsets Store the stack pointers in the lowcore for the kernel stack, the async stack and the panic stack with the offset required for the first user. This avoids an unnecessary add instruction on the system call path. - lc->async_stack = pcpu->async_stack + ASYNC_SIZE; - lc->panic_stack = pcpu->panic_stack + PAGE_SIZE; + lc->async_stack = pcpu->async_stack + ASYNC_SIZE + - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); + lc->panic_stack = pcpu->panic_stack + PAGE_SIZE + - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); The s390x crash code uses lowcore->panic/async_stack to find out the location of the per-cpu stacks. With the above kernel change this is no longer correct. For newer kernels with the "pcpu_devices" array there is a second location where the stacks are stored. With this patch we use the new location if available. Signed-off-by: Michael Holzheu <holzheu@xxxxxxxxxxxxxxxxxx> --- s390x.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) --- a/s390x.c +++ b/s390x.c @@ -913,10 +913,34 @@ s390x_get_lowcore(struct bt_info *bt, ch } /* + * Get stack address for interrupt stack using the pcpu array + */ +static unsigned long get_int_stack_pcpu(char *stack_name, int cpu) +{ + unsigned long addr; + + if (!MEMBER_EXISTS("pcpu", stack_name)) + return 0; + addr = symbol_value("pcpu_devices") + + cpu * STRUCT_SIZE("pcpu") + MEMBER_OFFSET("pcpu", stack_name); + return readmem_ul(addr) + INT_STACK_SIZE; +} + +/* + * Get stack address for interrupt stack using the lowcore + */ +static unsigned long get_int_stack_lc(char *stack_name, char *lc) +{ + if (!MEMBER_EXISTS(lc_struct, stack_name)) + return 0; + return ULONG(lc + MEMBER_OFFSET(lc_struct, stack_name)); +} + +/* * Read interrupt stack (either "async_stack" or "panic_stack"); */ -static void get_int_stack(char *stack_name, char *lc, unsigned long *start, - unsigned long *end) +static void get_int_stack(char *stack_name, int cpu, char *lc, + unsigned long *start, unsigned long *end) { unsigned long stack_addr; @@ -925,9 +949,10 @@ static void get_int_stack(char *stack_na stack_addr = symbol_value("restart_stack"); stack_addr = readmem_ul(stack_addr); } else { - if (!MEMBER_EXISTS(lc_struct, stack_name)) - return; - stack_addr = ULONG(lc + MEMBER_OFFSET(lc_struct, stack_name)); + if (symbol_exists("pcpu_devices")) + stack_addr = get_int_stack_pcpu(stack_name, cpu); + else + stack_addr = get_int_stack_lc(stack_name, lc); } if (stack_addr == 0) return; @@ -1157,12 +1182,13 @@ static void s390x_back_trace_cmd(struct s390x_print_lowcore(lowcore,bt,1); fprintf(fp,"\n"); if (symbol_exists("restart_stack")) { - get_int_stack("restart_stack", lowcore, &low, &high); + get_int_stack("restart_stack", + cpu, lowcore, &low, &high); sp = show_trace(bt, cnt, sp, low, high); } - get_int_stack("panic_stack", lowcore, &low, &high); + get_int_stack("panic_stack", cpu, lowcore, &low, &high); sp = show_trace(bt, cnt, sp, low, high); - get_int_stack("async_stack", lowcore, &low, &high); + get_int_stack("async_stack", cpu, lowcore, &low, &high); sp = show_trace(bt, cnt, sp, low, high); } /*
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility