----- Original Message -----
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(a)linux.vnet.ibm.com>
Thanks Michael -- queued for crash-7.0.1.
Dave
---
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);
}
/*