Add basic 'bt -e' support for s390x printing only interrupt frame and
related pt_regs, e.g:
crash> bt -e
PID: 604 TASK: 7052a00 CPU: 1 COMMAND: "systemd-journal"
USER-MODE INTERRUPT FRAME at 38000003e98
pt_regs at 38000003f38:
PSW: 0705000180000000 000003ff8db0fa36 (user space)
GPRS: 00000000002f9112 000003ff00000000 ffffffffffffffda 000002aa2b4db520
000000000000003e ffffffffffffffff 00063ea900000007 0000000000000020
0000000000000140 000002aa2b4b5290 000003ff8e2e6b40 000000000000003e
000003ff8e17bcd0 000003ff8e2af018 000003ff8e089a02 000003ffe02f98f0
Suggested-by: Heiko Carstens <hca(a)linux.ibm.com>
Signed-off-by: Mikhail Zaslonko <zaslonko(a)linux.ibm.com>
---
s390x.c | 46 ++++++++++++++++++++++++++++++++--------------
1 file changed, 32 insertions(+), 14 deletions(-)
diff --git a/s390x.c b/s390x.c
index 84362e9..13b0208 100644
--- a/s390x.c
+++ b/s390x.c
@@ -1376,12 +1376,17 @@ s390x_translate_pte(ulong pte, void *physaddr, ulonglong unused)
static int
s390x_eframe_search(struct bt_info *bt)
{
- if(bt->flags & BT_EFRAME_SEARCH2)
+ ulong esp;
+
+ if (bt->flags & BT_EFRAME_SEARCH2) {
return (error(FATAL,
"Option '-E' is not implemented for this architecture\n"));
- else
- return (error(FATAL,
- "Option '-e' is not implemented for this architecture\n"));
+ } else {
+ /* For 'bt -e' print only interrupt frames and related pt_regs */
+ s390x_get_stack_frame(bt, NULL, &esp);
+ bt->stkptr = esp;
+ s390x_back_trace_cmd(bt);
+ }
}
#ifdef DEPRECATED
@@ -1699,17 +1704,19 @@ static void print_ptregs(struct bt_info *bt, unsigned long sp)
static unsigned long show_trace(struct bt_info *bt, int cnt, unsigned long sp,
unsigned long low, unsigned long high)
{
- unsigned long reg;
+ unsigned long reg, iframe_addr;
unsigned long psw_addr ATTRIBUTE_UNUSED;
while (1) {
if (sp < low || sp > high - SIZE(s390_stack_frame))
return sp;
reg = readmem_ul(sp + OFFSET(s390_stack_frame_r14));
- if (!s390x_has_cpu(bt))
- print_frame(bt, cnt++, sp, reg);
- if (bt->flags & BT_FULL)
- print_frame_data(sp, high);
+ if (!(bt->flags & BT_EFRAME_SEARCH)) {
+ if (!s390x_has_cpu(bt))
+ print_frame(bt, cnt++, sp, reg);
+ if (bt->flags & BT_FULL)
+ print_frame_data(sp, high);
+ }
/* Follow the backchain. */
while (1) {
low = sp;
@@ -1722,18 +1729,25 @@ static unsigned long show_trace(struct bt_info *bt, int cnt,
unsigned long sp,
if (sp <= low || sp > high - SIZE(s390_stack_frame))
return sp;
reg = readmem_ul(sp + OFFSET(s390_stack_frame_r14));
- print_frame(bt, cnt++, sp, reg);
- if (bt->flags & BT_FULL)
- print_frame_data(sp, high);
+ if (!(bt->flags & BT_EFRAME_SEARCH)) {
+ print_frame(bt, cnt++, sp, reg);
+ if (bt->flags & BT_FULL)
+ print_frame_data(sp, high);
+ }
}
/* Zero backchain detected, check for interrupt frame. */
+ iframe_addr = sp;
sp += SIZE(s390_stack_frame);
if (sp <= low || sp > high - STRUCT_SIZE("pt_regs"))
return sp;
/* Check for user PSW */
reg = readmem_ul(sp + MEMBER_OFFSET("pt_regs", "psw"));
if (reg & S390X_PSW_MASK_PSTATE) {
- fprintf(fp, " USER-MODE INTERRUPT FRAME; pt_regs at %llx:\n", sp);
+ if (bt->flags & BT_EFRAME_SEARCH)
+ fprintf(fp, " USER-MODE INTERRUPT FRAME at %llx\n", iframe_addr);
+ else
+ fprintf(fp, " USER-MODE INTERRUPT FRAME;", sp);
+ fprintf(fp, " pt_regs at %llx:\n", sp);
print_ptregs(bt, sp);
return sp;
}
@@ -1746,7 +1760,11 @@ static unsigned long show_trace(struct bt_info *bt, int cnt,
unsigned long sp,
/* Check for loop (kernel_thread_starter) of second zero bc */
if (low == reg || reg == 0)
return reg;
- fprintf(fp, " KERNEL-MODE INTERRUPT FRAME; pt_regs at %llx:\n", sp);
+ if (bt->flags & BT_EFRAME_SEARCH)
+ fprintf(fp, " KERNEL-MODE INTERRUPT FRAME at %llx\n", iframe_addr);
+ else
+ fprintf(fp, " KERNEL-MODE INTERRUPT FRAME;", sp);
+ fprintf(fp, " pt_regs at %llx:\n", sp);
print_ptregs(bt, sp);
low = sp;
sp = reg;
--
2.49.0