Hi Dave,
This patch fixes several bugs in the s390 stack backtrace code
* Add panic stack as second interrupt stack
* Fix printing of access registers (4 bytes instead of 8 bytes)
* Use u64 for s390x register 14
* Fix interrupt stack handling for s390x (use 160 byte overhead
instead of 96)
The patch looks OK upon first glance -- can you verify that it's
absolutely backwards-compatible to earlier kernel versions?
Thanks,
Dave
---
s390.c | 46 ++++++++++++++++++-------------
s390x.c | 94
+++++++++++++++++++++++++++++++++++-----------------------------
2 files changed, 79 insertions(+), 61 deletions(-)
--- a/s390.c
+++ b/s390.c
@@ -37,7 +37,7 @@
#define S390_PTE_INVALID_MASK 0x80000900
#define S390_PTE_INVALID(x) ((x) & S390_PTE_INVALID_MASK)
-#define ASYNC_STACK_SIZE STACKSIZE() // can be 4096 or 8192
+#define INT_STACK_SIZE STACKSIZE() // can be 4096 or 8192
#define KERNEL_STACK_SIZE STACKSIZE() // can be 4096 or 8192
#define LOWCORE_SIZE 4096
@@ -570,20 +570,21 @@ s390_get_lowcore(int cpu, char* lowcore)
FAULT_ON_ERROR);
}
-/*
- * read in the async stack
+/*
+ * Read interrupt stack (either "async_stack" or "panic_stack");
*/
-static void
-s390_get_async_stack(char* lowcore, char* async_stack, unsigned long*
start, unsigned long* end)
+static void s390_get_int_stack(char *stack_name, char* lc, char*
int_stack,
+ unsigned long* start, unsigned long* end)
{
- unsigned long async_stack_ptr;
+ unsigned long stack_addr;
- async_stack_ptr = ULONG(lowcore +
- MEMBER_OFFSET("_lowcore","async_stack"));
- readmem(async_stack_ptr-ASYNC_STACK_SIZE,KVADDR, async_stack,
- ASYNC_STACK_SIZE, "async_stack", FAULT_ON_ERROR);
- *start=async_stack_ptr-ASYNC_STACK_SIZE;
- *end=async_stack_ptr;
+ if (!MEMBER_EXISTS("_lowcore", stack_name))
+ return;
+ stack_addr = ULONG(lc + MEMBER_OFFSET("_lowcore", stack_name));
+ readmem(stack_addr - INT_STACK_SIZE, KVADDR, int_stack,
+ INT_STACK_SIZE, stack_name, FAULT_ON_ERROR);
+ *start = stack_addr - INT_STACK_SIZE;
+ *end = stack_addr;
}
/*
@@ -593,16 +594,18 @@ static void
s390_back_trace_cmd(struct bt_info *bt)
{
char* stack;
- char async_stack[ASYNC_STACK_SIZE];
+ char async_stack[INT_STACK_SIZE];
+ char panic_stack[INT_STACK_SIZE];
long ksp,backchain,old_backchain;
int i=0, r14_offset,bc_offset,r14, skip_first_frame=0;
- unsigned long async_start,async_end, stack_end, stack_start,
stack_base;
+ unsigned long async_start = 0, async_end = 0;
+ unsigned long panic_start = 0, panic_end = 0;
+ unsigned long stack_end, stack_start, stack_base;
if (bt->hp && bt->hp->eip) {
error(WARNING,
"instruction pointer argument ignored on this architecture!\n");
}
- async_end = async_start = 0;
ksp = bt->stkptr;
/* print lowcore and get async stack when task has cpu */
@@ -622,9 +625,10 @@ s390_back_trace_cmd(struct bt_info *bt)
s390_print_lowcore(lowcore,bt,0);
return;
}
-
- s390_get_async_stack(lowcore,async_stack,&async_start,
- &async_end);
+ s390_get_int_stack("async_stack", lowcore, async_stack,
+ &async_start, &async_end);
+ s390_get_int_stack("panic_stack", lowcore, panic_stack,
+ &panic_start, &panic_end);
s390_print_lowcore(lowcore,bt,1);
fprintf(fp,"\n");
skip_first_frame=1;
@@ -653,7 +657,7 @@ s390_back_trace_cmd(struct bt_info *bt)
unsigned long r14_stack_off;
int j;
- /* Find stack: Either async stack or task stack */
+ /* Find stack: Either async, panic stack or task stack */
if((backchain > stack_start) && (backchain < stack_end)){
stack = bt->stackbuf;
stack_base = stack_start;
@@ -661,6 +665,10 @@ s390_back_trace_cmd(struct bt_info *bt)
&& s390_has_cpu(bt)){
stack = async_stack;
stack_base = async_start;
+ } else if((backchain > panic_start) && (backchain < panic_end)
+ && s390_has_cpu(bt)){
+ stack = panic_stack;
+ stack_base = panic_start;
} else {
/* invalid stackframe */
break;
--- a/s390x.c
+++ b/s390x.c
@@ -36,7 +36,7 @@
#define S390X_PTE_INVALID_MASK 0x900ULL
#define S390X_PTE_INVALID(x) ((x) & S390X_PTE_INVALID_MASK)
-#define ASYNC_STACK_SIZE STACKSIZE() // can be 8192 or 16384
+#define INT_STACK_SIZE STACKSIZE() // can be 8192 or 16384
#define KERNEL_STACK_SIZE STACKSIZE() // can be 8192 or 16384
#define LOWCORE_SIZE 8192
@@ -803,19 +803,20 @@ s390x_get_lowcore(struct bt_info *bt, ch
}
/*
- * read in the async stack
+ * Read interrupt stack (either "async_stack" or "panic_stack");
*/
-static void
-s390x_get_async_stack(char* lowcore, char* async_stack, unsigned
long* start, unsigned long* end)
+static void s390x_get_int_stack(char *stack_name, char* lc, char*
int_stack,
+ unsigned long* start, unsigned long* end)
{
- unsigned long async_stack_ptr;
+ unsigned long stack_addr;
- async_stack_ptr = ULONG(lowcore +
- MEMBER_OFFSET("_lowcore","async_stack"));
- readmem(async_stack_ptr-ASYNC_STACK_SIZE,KVADDR, async_stack,
- ASYNC_STACK_SIZE, "async_stack", FAULT_ON_ERROR);
- *start=async_stack_ptr-ASYNC_STACK_SIZE;
- *end=async_stack_ptr;
+ if (!MEMBER_EXISTS("_lowcore", stack_name))
+ return;
+ stack_addr = ULONG(lc + MEMBER_OFFSET("_lowcore", stack_name));
+ readmem(stack_addr - INT_STACK_SIZE, KVADDR, int_stack,
+ INT_STACK_SIZE, stack_name, FAULT_ON_ERROR);
+ *start = stack_addr - INT_STACK_SIZE;
+ *end = stack_addr;
}
/*
@@ -825,11 +826,14 @@ static void
s390x_back_trace_cmd(struct bt_info *bt)
{
char* stack;
- char async_stack[ASYNC_STACK_SIZE];
+ char async_stack[INT_STACK_SIZE];
+ char panic_stack[INT_STACK_SIZE];
long ksp,backchain,old_backchain;
- int i=0, r14_offset,bc_offset,r14, skip_first_frame=0;
+ int i=0, r14_offset,bc_offset, skip_first_frame=0;
unsigned long async_start = 0, async_end = 0;
+ unsigned long panic_start = 0, panic_end = 0;
unsigned long stack_end, stack_start, stack_base;
+ unsigned long r14;
if (bt->hp && bt->hp->eip) {
error(WARNING,
@@ -854,9 +858,10 @@ s390x_back_trace_cmd(struct bt_info *bt)
s390x_print_lowcore(lowcore,bt,0);
return;
}
-
- s390x_get_async_stack(lowcore,async_stack,&async_start,
- &async_end);
+ s390x_get_int_stack("async_stack", lowcore, async_stack,
+ &async_start, &async_end);
+ s390x_get_int_stack("panic_stack", lowcore, panic_stack,
+ &panic_start, &panic_end);
s390x_print_lowcore(lowcore,bt,1);
fprintf(fp,"\n");
skip_first_frame=1;
@@ -885,7 +890,7 @@ s390x_back_trace_cmd(struct bt_info *bt)
unsigned long r14_stack_off;
int j;
- /* Find stack: Either async stack or task stack */
+ /* Find stack: Either async, panic stack or task stack */
if((backchain > stack_start) && (backchain < stack_end)){
stack = bt->stackbuf;
stack_base = stack_start;
@@ -893,6 +898,10 @@ s390x_back_trace_cmd(struct bt_info *bt)
&& s390x_has_cpu(bt)){
stack = async_stack;
stack_base = async_start;
+ } else if((backchain > panic_start) && (backchain < panic_end)
+ && s390x_has_cpu(bt)){
+ stack = panic_stack;
+ stack_base = panic_start;
} else {
/* invalid stackframe */
break;
@@ -913,7 +922,7 @@ s390x_back_trace_cmd(struct bt_info *bt)
skip_first_frame=0;
} else {
fprintf(fp," #%i [%08lx] ",i,backchain);
- fprintf(fp,"%s at %x\n", closest_symbol(r14), r14);
+ fprintf(fp,"%s at %lx\n", closest_symbol(r14), r14);
if (bt->flags & BT_LINE_NUMBERS)
s390x_dump_line_number(r14);
i++;
@@ -944,19 +953,20 @@ s390x_back_trace_cmd(struct bt_info *bt)
}
/* Check for interrupt stackframe */
- if((backchain == 0) && (stack == async_stack)){
- unsigned long psw_flags,r15;
+ if((backchain == 0) &&
+ (stack == async_stack || stack == panic_stack)) {
+ int pt_regs_off = old_backchain - stack_base + 160;
+ unsigned long psw_flags;
- psw_flags = ULONG(&stack[old_backchain - stack_base
- +96 +MEMBER_OFFSET("pt_regs","psw")]);
+ psw_flags = ULONG(&stack[pt_regs_off +
+ MEMBER_OFFSET("pt_regs", "psw")]);
if(psw_flags & 0x1000000000000ULL){
/* User psw: should not happen */
break;
}
- r15 = ULONG(&stack[old_backchain - stack_base +
- 96 + MEMBER_OFFSET("pt_regs",
- "gprs") + 15 * S390X_WORD_SIZE]);
- backchain=r15;
+ backchain = ULONG(&stack[pt_regs_off +
+ MEMBER_OFFSET("pt_regs", "gprs") +
+ 15 * S390X_WORD_SIZE]);
fprintf(fp," - Interrupt -\n");
}
} while(backchain != 0);
@@ -1036,28 +1046,28 @@ s390x_print_lowcore(char* lc, struct bt_
fprintf(fp," -access registers:\n");
ptr = lc + MEMBER_OFFSET("_lowcore","access_regs_save_area");
- tmp[0]=ULONG(ptr);
- tmp[1]=ULONG(ptr + 4);
- tmp[2]=ULONG(ptr + 2 * 4);
- tmp[3]=ULONG(ptr + 3 * 4);
+ tmp[0]=UINT(ptr);
+ tmp[1]=UINT(ptr + 4);
+ tmp[2]=UINT(ptr + 2 * 4);
+ tmp[3]=UINT(ptr + 3 * 4);
fprintf(fp," %#010lx %#010lx %#010lx %#010lx\n",
tmp[0], tmp[1], tmp[2], tmp[3]);
- tmp[0]=ULONG(ptr + 4 * 4);
- tmp[1]=ULONG(ptr + 5 * 4);
- tmp[2]=ULONG(ptr + 6 * 4);
- tmp[3]=ULONG(ptr + 7 * 4);
+ tmp[0]=UINT(ptr + 4 * 4);
+ tmp[1]=UINT(ptr + 5 * 4);
+ tmp[2]=UINT(ptr + 6 * 4);
+ tmp[3]=UINT(ptr + 7 * 4);
fprintf(fp," %#010lx %#010lx %#010lx %#010lx\n",
tmp[0], tmp[1], tmp[2], tmp[3]);
- tmp[0]=ULONG(ptr + 8 * 4);
- tmp[1]=ULONG(ptr + 9 * 4);
- tmp[2]=ULONG(ptr + 10* 4);
- tmp[3]=ULONG(ptr + 11* 4);
+ tmp[0]=UINT(ptr + 8 * 4);
+ tmp[1]=UINT(ptr + 9 * 4);
+ tmp[2]=UINT(ptr + 10 * 4);
+ tmp[3]=UINT(ptr + 11 * 4);
fprintf(fp," %#010lx %#010lx %#010lx %#010lx\n",
tmp[0], tmp[1], tmp[2], tmp[3]);
- tmp[0]=ULONG(ptr + 12* 4);
- tmp[1]=ULONG(ptr + 13* 4);
- tmp[2]=ULONG(ptr + 14* 4);
- tmp[3]=ULONG(ptr + 15* 4);
+ tmp[0]=UINT(ptr + 12 * 4);
+ tmp[1]=UINT(ptr + 13 * 4);
+ tmp[2]=UINT(ptr + 14 * 4);
+ tmp[3]=UINT(ptr + 15 * 4);
fprintf(fp," %#010lx %#010lx %#010lx %#010lx\n",
tmp[0], tmp[1], tmp[2], tmp[3]);
--
Crash-utility mailing list
Crash-utility(a)redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility