[9/9] core: interrupt markers for stack traces
diff mbox series

Message ID 20200226183408.1626737-10-npiggin@gmail.com
State New
Headers show
Series
  • assorted fixes and preparation
Related show

Checks

Context Check Description
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot-dco success Signed-off-by present
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot fail Test snowpatch/job/snowpatch-skiboot on branch master
snowpatch_ozlabs/apply_patch success Successfully applied on branch master (f123417068e51842004bdc047c8c5107b70442ef)

Commit Message

Nicholas Piggin Feb. 26, 2020, 6:34 p.m. UTC
Use magic marker in the exception stack frame that is used by the
unwinder to decode the interrupt type and NIA. The below example trace
comes from a modified skiboot that uses virtual memory, but any
interrupt type will appear similarly.

 CPU 0000 Backtrace:
  S: 0000000031c13580 R: 0000000030028210   .vm_dsi+0x360
  S: 0000000031c13630 R: 000000003003b0dc   .exception_entry+0x4fc
  S: 0000000031c13830 R: 0000000030001f4c   exception_entry_foo+0x4
  --- Interrupt 0x300 at 000000003002431c ---
  S: 0000000031c13b40 R: 000000003002430c   .make_free.isra.0+0x110
  S: 0000000031c13bd0 R: 0000000030025198   .mem_alloc+0x4a0
  S: 0000000031c13c80 R: 0000000030028bac   .__memalign+0x48
  S: 0000000031c13d10 R: 0000000030028da4   .__zalloc+0x18
  S: 0000000031c13d90 R: 000000003002fb34   .opal_init_msg+0x34
  S: 0000000031c13e20 R: 00000000300234b4   .main_cpu_entry+0x61c
  S: 0000000031c13f00 R: 00000000300031b8   boot_entry+0x1b0
  --- OPAL boot ---

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 asm/asm-offsets.c |  1 +
 asm/head.S        |  5 +++++
 core/exceptions.c |  2 ++
 core/stack.c      | 11 +++++++++++
 include/mem-map.h |  2 +-
 include/stack.h   |  6 ++++++
 6 files changed, 26 insertions(+), 1 deletion(-)

Patch
diff mbox series

diff --git a/asm/asm-offsets.c b/asm/asm-offsets.c
index 61a25cab3..b51939b9f 100644
--- a/asm/asm-offsets.c
+++ b/asm/asm-offsets.c
@@ -38,6 +38,7 @@  int main(void)
 	OFFSET(CPUTHREAD_STACK_BOT_TOK, cpu_thread, stack_bot_tok);
 #endif
 	OFFSET(STACK_TYPE,	stack_frame, type);
+	OFFSET(STACK_MAGIC,	stack_frame, magic);
 	OFFSET(STACK_LOCALS,	stack_frame, locals);
 	OFFSET(STACK_GPR0,	stack_frame, gpr[0]);
 	OFFSET(STACK_GPR1,	stack_frame, gpr[1]);
diff --git a/asm/head.S b/asm/head.S
index 5ada79971..a76d723db 100644
--- a/asm/head.S
+++ b/asm/head.S
@@ -176,6 +176,7 @@  _exception:
 	mfspr	%r3,SPR_SRR0
 	mfspr	%r4,SPR_SRR1
 	std	%r3,STACK_SRR0(%r1)
+	std	%r3,16(%r1)
 	std	%r4,STACK_SRR1(%r1)
 	mfspr	%r3,SPR_DSISR
 	mfspr	%r4,SPR_DAR
@@ -231,6 +232,8 @@  _exception:
 	stw	%r4,STACK_XER(%r1)
 	std	%r5,STACK_CTR(%r1)
 	std	%r6,STACK_LR(%r1)
+	LOAD_IMM64(%r3,STACK_INT_MAGIC)
+	std	%r3,STACK_MAGIC(%r1)
 	LOAD_IMM64(%r4, SKIBOOT_BASE)
 	LOAD_IMM32(%r5,__toc_start - __head)
 	LOAD_IMM32(%r6, exception_entry_foo - __head)
@@ -928,6 +931,8 @@  opal_entry:
 	/* Store token in CPU thread */
 	std	%r0,CPUTHREAD_CUR_TOKEN(%r16)
 
+	LOAD_IMM64(%r12,STACK_INT_MAGIC)
+	std	%r12,STACK_MAGIC(%r1)
 	/* Mark the stack frame */
 	li	%r12,STACK_ENTRY_OPAL_API
 	std	%r12,STACK_TYPE(%r1)
diff --git a/core/exceptions.c b/core/exceptions.c
index 4ff7a9e4b..7cb30c18c 100644
--- a/core/exceptions.c
+++ b/core/exceptions.c
@@ -65,6 +65,8 @@  void exception_entry(struct stack_frame *stack)
 		nip = stack->srr0;
 		msr = stack->srr1;
 	}
+	stack->msr = msr;
+	stack->pc = nip;
 
 	if (!(msr & MSR_RI))
 		fatal = true;
diff --git a/core/stack.c b/core/stack.c
index b94d11518..c8c6b15b1 100644
--- a/core/stack.c
+++ b/core/stack.c
@@ -35,6 +35,12 @@  static void __nomcount __backtrace_create(struct bt_entry *entries,
 		if (!fp || (unsigned long)fp > top_adj)
 			break;
 		eframe = (struct stack_frame *)fp;
+		if (eframe->magic == STACK_INT_MAGIC) {
+			entries->exception_type = eframe->type;
+			entries->exception_pc = eframe->pc;
+		} else {
+			entries->exception_type = 0;
+		}
 		entries->sp = (unsigned long)fp;
 		entries->pc = fp[2];
 		entries++;
@@ -99,6 +105,11 @@  void backtrace_print(struct bt_entry *entries, struct bt_metadata *metadata,
 		if (symbols)
 			l += snprintf_symbol(buf + l, max - l, entries->pc);
 		l += snprintf(buf + l, max - l, "\n");
+		if (entries->exception_type) {
+			l += snprintf(buf + l, max - l,
+				      " --- Interrupt 0x%lx at %016lx ---\n",
+				      entries->exception_type, entries->exception_pc);
+		}
 		entries++;
 	}
 	if (metadata->token <= OPAL_LAST)
diff --git a/include/mem-map.h b/include/mem-map.h
index 8ac11e916..69b2a1b93 100644
--- a/include/mem-map.h
+++ b/include/mem-map.h
@@ -19,7 +19,7 @@ 
 /* End of the exception region we copy from 0x0. 0x0-0x100 will have
  * IPL data and is not actually for exception vectors.
  */
-#define EXCEPTION_VECTORS_END	0x2000
+#define EXCEPTION_VECTORS_END	0x3000
 
 #define NACA_OFF		0x4000
 
diff --git a/include/stack.h b/include/stack.h
index b0d6df17d..86db5839d 100644
--- a/include/stack.h
+++ b/include/stack.h
@@ -45,6 +45,7 @@ 
 #define STACK_WARNING_GAP	2048
 
 #define STACK_CHECK_GUARD_BASE	0xdeadf00dbaad300
+#define STACK_INT_MAGIC		0xb1ab1af00ba1234ULL
 
 #ifndef __ASSEMBLY__
 
@@ -72,6 +73,9 @@  struct stack_frame {
 	 * one doubleword. */
 	uint64_t	locals[1];
 
+	/* Interrupt entry magic value */
+	uint64_t	magic;
+
 	/* Entry type */
 	uint64_t	type;
 
@@ -104,6 +108,8 @@  struct stack_frame {
 struct bt_entry {
 	unsigned long	sp;
 	unsigned long	pc;
+	unsigned long	exception_type;
+	unsigned long	exception_pc;
 };
 
 /* Backtrace metadata */