summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/kernel/dumpstack.c1
-rw-r--r--arch/s390/lib/test_unwind.c12
2 files changed, 11 insertions, 2 deletions
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
index fc442aec0d96..d74e21a23703 100644
--- a/arch/s390/kernel/dumpstack.c
+++ b/arch/s390/kernel/dumpstack.c
@@ -38,6 +38,7 @@ const char *stack_type_name(enum stack_type type)
return "unknown";
}
}
+EXPORT_SYMBOL_GPL(stack_type_name);
static inline bool in_stack(unsigned long sp, struct stack_info *info,
enum stack_type type, unsigned long low,
diff --git a/arch/s390/lib/test_unwind.c b/arch/s390/lib/test_unwind.c
index 687a6922beda..db94e657c056 100644
--- a/arch/s390/lib/test_unwind.c
+++ b/arch/s390/lib/test_unwind.c
@@ -56,11 +56,19 @@ static noinline int test_unwind(struct task_struct *task, struct pt_regs *regs,
unsigned long addr = unwind_get_return_address(&state);
char sym[KSYM_SYMBOL_LEN];
- if (!addr || frame_count == max_frames)
+ if (frame_count++ == max_frames)
break;
+ if (state.reliable && !addr) {
+ pr_err("unwind state reliable but addr is 0\n");
+ return -EINVAL;
+ }
sprint_symbol(sym, addr);
if (bt_pos < BT_BUF_SIZE) {
- bt_pos += snprintf(bt + bt_pos, BT_BUF_SIZE - bt_pos, "%s\n", sym);
+ bt_pos += snprintf(bt + bt_pos, BT_BUF_SIZE - bt_pos,
+ state.reliable ? " [%-7s%px] %pSR\n" :
+ "([%-7s%px] %pSR)\n",
+ stack_type_name(state.stack_info.type),
+ (void *)state.sp, (void *)state.ip);
if (bt_pos >= BT_BUF_SIZE)
pr_err("backtrace buffer is too small\n");
}