arm64: Support overflow stack panic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi All

When I was trying to open a core of an overflow stack panic result, the bt command caused a segment fault, after a while I figured out the overflow stack is not supported by crash utility.

This patch is trying to initialize the overflow stack information on startup stage, and the bt command works as expected to dump the correct call trace in the overflow stack, currently  it only apply to arm64 target.

I'm not sure if any other sub command also need to be fixed for full support for the overflow stack, please advise and I'll try to improve the patch.

Thanks
Hong YANG
From 90cc414a34a8065d0d5e95a44587f7e84da5ef70 Mon Sep 17 00:00:00 2001
From: Hong YANG <hong.yang3@xxxxxxx>
Date: Mon, 15 Nov 2021 15:41:01 +0800
Subject: [PATCH] arm64: Support overflow stack panic

Overflow stack supported since kernel 4.14 in commit 872d8327ce8,
without this patch, bt command trigger a SIGSEGV fault due the SP
pointed to the overflow stack which not yet loaded by crash.

Before:

      KERNEL: ../vmlinux
    DUMPFILE: la_guestdump.gcore
        CPUS: 8
        DATE: Tue Jul 13 19:59:44 CST 2021
      UPTIME: 00:00:42
LOAD AVERAGE: 3.99, 1.13, 0.39
       TASKS: 1925
    NODENAME: localhost
     RELEASE: 4.14.156+
     VERSION: #1 SMP PREEMPT Tue Jul 13 10:37:23 UTC 2021
     MACHINE: aarch64  (unknown Mhz)
      MEMORY: 8.7 GB
       PANIC: "Kernel panic - not syncing: kernel stack overflow"
         PID: 1969
     COMMAND: "irq/139-0-0024"
        TASK: ffffffcc1a230000  [THREAD_INFO: ffffffcc1a230000]
         CPU: 0
       STATE: TASK_RUNNING (PANIC)

crash-7.3.0> bt
PID: 1969   TASK: ffffffcc1a230000  CPU: 0   COMMAND: "irq/139-0-0024"
Segmentation fault (core dumped)

After:

crash> bt
PID: 1969   TASK: ffffffcc1a230000  CPU: 0   COMMAND: "irq/139-0-0024"
  #0 [ffffffcc7fd5cf50] __delay at ffffff8008c80774
  #1 [ffffffcc7fd5cf60] __const_udelay at ffffff8008c80864
  #2 [ffffffcc7fd5cf80] msm_trigger_wdog_bite at ffffff80084e9430
  #3 [ffffffcc7fd5cfa0] do_vm_restart at ffffff80087bc974
  #4 [ffffffcc7fd5cfc0] machine_restart at ffffff80080856fc
  #5 [ffffffcc7fd5cfd0] emergency_restart at ffffff80080d49bc
  #6 [ffffffcc7fd5d140] panic at ffffff80080af4c0
  #7 [ffffffcc7fd5d150] nmi_panic at ffffff80080af150
  #8 [ffffffcc7fd5d190] handle_bad_stack at ffffff800808b0b8
  #9 [ffffffcc7fd5d2d0] __bad_stack at ffffff800808285c
--- <IRQ stack> ---
 #10 [ffffff801187bc60] el1_error_invalid at ffffff8008082e7c
 #11 [ffffff801187bcc0] cyttsp6_mt_attention at ffffff8000e8498c [cyttsp6]
 #12 [ffffff801187bd20] call_atten_cb at ffffff8000e82030 [cyttsp6]
 #13 [ffffff801187bdc0] cyttsp6_irq at ffffff8000e81e34 [cyttsp6]
 #14 [ffffff801187bdf0] irq_thread_fn at ffffff8008128dd8
 #15 [ffffff801187be50] irq_thread at ffffff8008128ca4
 #16 [ffffff801187beb0] kthread at ffffff80080d2fc4
crash>

Signed-off-by: Hong YANG <hong.yang3@xxxxxxx>
---
 arm64.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 defs.h  |  6 ++++
 2 files changed, 92 insertions(+), 6 deletions(-)

diff --git a/arm64.c b/arm64.c
index 94681d1..403fcc2 100644
--- a/arm64.c
+++ b/arm64.c
@@ -45,6 +45,7 @@ static int arm64_vtop_3level_4k(ulong, ulong, physaddr_t *, int);
 static int arm64_vtop_4level_4k(ulong, ulong, physaddr_t *, int);
 static ulong arm64_get_task_pgd(ulong);
 static void arm64_irq_stack_init(void);
+static void arm64_overflow_stack_init(void);
 static void arm64_stackframe_init(void);
 static int arm64_eframe_search(struct bt_info *);
 static int arm64_is_kernel_exception_frame(struct bt_info *, ulong);
@@ -78,8 +79,11 @@ static int arm64_get_smp_cpus(void);
 static void arm64_clear_machdep_cache(void);
 static int arm64_on_process_stack(struct bt_info *, ulong);
 static int arm64_in_alternate_stack(int, ulong);
+static int arm64_in_alternate_stackv(int cpu, ulong stkptr, ulong *stacks, ulong stack_size);
 static int arm64_on_irq_stack(int, ulong);
+static int arm64_on_overflow_stack(int, ulong);
 static void arm64_set_irq_stack(struct bt_info *);
+static void arm64_set_overflow_stack(struct bt_info *);
 static void arm64_set_process_stack(struct bt_info *);
 static int arm64_get_kvaddr_ranges(struct vaddr_range *);
 static void arm64_get_crash_notes(void);
@@ -463,6 +467,7 @@ arm64_init(int when)
 			machdep->hz = 100;
 
 		arm64_irq_stack_init();
+		arm64_overflow_stack_init();
 		arm64_stackframe_init();
 		break;
 
@@ -1715,6 +1720,49 @@ arm64_irq_stack_init(void)
 	} 
 }
 
+/*
+ *  Gather Overflow stack values.
+ *
+ *  Overflow stack supported since 4.14, in commit 872d8327c
+ */
+static void
+arm64_overflow_stack_init(void)
+{
+	int i;
+	struct syment *sp;
+	struct gnu_request request, *req;
+	struct machine_specific *ms = machdep->machspec;
+	req = &request;
+
+	if (symbol_exists("overflow_stack") &&
+	    (sp = per_cpu_symbol_search("overflow_stack")) &&
+	    get_symbol_type("overflow_stack", NULL, req)) {
+		if (CRASHDEBUG(1)) {
+			fprintf(fp, "overflow_stack: \n");
+			fprintf(fp, "  type: %x, %s\n",
+				(int)req->typecode,
+				(req->typecode == TYPE_CODE_PTR) ?
+						"TYPE_CODE_PTR" : "other");
+			fprintf(fp, "  target_typecode: %x, %s\n",
+				(int)req->target_typecode,
+				req->target_typecode == TYPE_CODE_INT ?
+						"TYPE_CODE_INT" : "other");
+			fprintf(fp, "  target_length: %ld\n",
+						req->target_length);
+			fprintf(fp, "  length: %ld\n", req->length);
+		}
+
+		if (!(ms->overflow_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
+			error(FATAL, "cannot malloc overflow_stack addresses\n");
+
+		ms->overflow_stack_size = ARM64_OVERFLOW_STACK_SIZE;
+		machdep->flags |= OVERFLOW_STACKS;
+
+		for (i = 0; i < kt->cpus; i++)
+			ms->irq_stacks[i] = kt->__per_cpu_offset[i] + sp->value;
+	}
+}
+
 /*
  *  Gather and verify all of the backtrace requirements.
  */
@@ -2673,6 +2721,12 @@ arm64_back_trace_cmd(struct bt_info *bt)
 			bt->hp->eip : GET_STACK_ULONG(bt->hp->esp);
 		stackframe.sp = bt->hp->esp + 8;
 		bt->flags &= ~BT_REGS_NOT_FOUND;
+	} else if (arm64_on_overflow_stack(bt->tc->processor, bt->frameptr)) {
+		arm64_set_overflow_stack(bt);
+		bt->flags |= BT_OVERFLOW_STACK;
+		stackframe.sp = bt->stkptr;
+		stackframe.pc = bt->instptr;
+		stackframe.fp = bt->frameptr;
 	} else {
 		if (arm64_on_irq_stack(bt->tc->processor, bt->frameptr)) {
 			arm64_set_irq_stack(bt);
@@ -3881,20 +3935,36 @@ arm64_on_irq_stack(int cpu, ulong stkptr)
 }
 
 static int
-arm64_in_alternate_stack(int cpu, ulong stkptr)
+arm64_in_alternate_stackv(int cpu, ulong stkptr, ulong *stacks, ulong stack_size)
 {
-	struct machine_specific *ms = machdep->machspec;
-
-	if (!ms->irq_stack_size || (cpu >= kt->cpus))
+	if (!stack_size || (cpu >= kt->cpus))
 		return FALSE;
 
-	if ((stkptr >= ms->irq_stacks[cpu]) &&
-	    (stkptr < (ms->irq_stacks[cpu] + ms->irq_stack_size)))
+	if ((stkptr >= stacks[cpu]) &&
+	    (stkptr < (stacks[cpu] + stack_size)))
 		return TRUE;
 
 	return FALSE;
 }
 
+static int
+arm64_in_alternate_stack(int cpu, ulong stkptr)
+{
+	struct machine_specific *ms = machdep->machspec;
+
+	return arm64_in_alternate_stackv(cpu, stkptr,
+			ms->irq_stacks, ms->irq_stack_size);
+}
+
+static int
+arm64_on_overflow_stack(int cpu, ulong stkptr)
+{
+	struct machine_specific *ms = machdep->machspec;
+
+	return arm64_in_alternate_stackv(cpu, stkptr,
+			ms->overflow_stacks, ms->overflow_stack_size);
+}
+
 static void
 arm64_set_irq_stack(struct bt_info *bt)
 {
@@ -3905,6 +3975,16 @@ arm64_set_irq_stack(struct bt_info *bt)
 	alter_stackbuf(bt);
 }
 
+static void
+arm64_set_overflow_stack(struct bt_info *bt)
+{
+	struct machine_specific *ms = machdep->machspec;
+
+	bt->stackbase = ms->overflow_stacks[bt->tc->processor];
+	bt->stacktop = bt->stackbase + ms->overflow_stack_size;
+	alter_stackbuf(bt);
+}
+
 static void
 arm64_set_process_stack(struct bt_info *bt)
 {
diff --git a/defs.h b/defs.h
index a2f3085..7e2a16e 100644
--- a/defs.h
+++ b/defs.h
@@ -3218,6 +3218,7 @@ typedef signed int s32;
 #define UNW_4_14      (0x200)
 #define FLIPPED_VM    (0x400)
 #define HAS_PHYSVIRT_OFFSET (0x800)
+#define OVERFLOW_STACKS     (0x1000)
 
 /*
  * Get kimage_voffset from /dev/crash
@@ -3260,6 +3261,7 @@ typedef signed int s32;
 
 #define ARM64_STACK_SIZE   (16384)
 #define ARM64_IRQ_STACK_SIZE   ARM64_STACK_SIZE
+#define ARM64_OVERFLOW_STACK_SIZE   (4096)
 
 #define _SECTION_SIZE_BITS           30
 #define _SECTION_SIZE_BITS_5_12      27
@@ -3332,6 +3334,9 @@ struct machine_specific {
 	char  *irq_stackbuf;
 	ulong __irqentry_text_start;
 	ulong __irqentry_text_end;
+	ulong overflow_stack_size;
+	ulong *overflow_stacks;
+	char  *overflow_stackbuf;
 	/* for exception vector code */
 	ulong exp_entry1_start;
 	ulong exp_entry1_end;
@@ -5770,6 +5775,7 @@ ulong cpu_map_addr(const char *type);
 #define BT_CPUMASK        (0x1000000000000ULL)
 #define BT_SHOW_ALL_REGS  (0x2000000000000ULL)
 #define BT_REGS_NOT_FOUND (0x4000000000000ULL)
+#define BT_OVERFLOW_STACK (0x8000000000000ULL)
 #define BT_SYMBOL_OFFSET   (BT_SYMBOLIC_ARGS)
 
 #define BT_REF_HEXVAL         (0x1)
-- 
2.25.1

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux