diff mbox series

[11/16] asm/head: provide asm support for interrupts to be returned from

Message ID 20190107140428.16388-12-npiggin@gmail.com
State Accepted
Headers show
Series assorted MCE and SRESET handling and reporting | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success master/apply_patch Successfully applied
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot success Test snowpatch/job/snowpatch-skiboot on branch master

Commit Message

Nicholas Piggin Jan. 7, 2019, 2:04 p.m. UTC
This adds the redzone to the interrupt stack, and code to restore
registers.

This can be used for a number of things. Initially it will be used
to recover from system reset interrupts, it could later be used to
handle recoverable machine checks, use the decrementer to implement
a watchdog, handle HMI interrupts at boot, and to implement virtual
memory.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 asm/asm-offsets.c |  6 ++++
 asm/head.S        | 89 +++++++++++++++++++++++++++++++++++++----------
 core/exceptions.c |  4 +--
 3 files changed, 79 insertions(+), 20 deletions(-)
diff mbox series

Patch

diff --git a/asm/asm-offsets.c b/asm/asm-offsets.c
index 45f424361..0aea93d21 100644
--- a/asm/asm-offsets.c
+++ b/asm/asm-offsets.c
@@ -28,6 +28,11 @@ 
 #define OFFSET(sym, str, mem) \
 	DEFINE(sym, offsetof(struct str, mem))
 
+/*
+ * 64-bit ELF ABI specifies 288 byte redzone size.
+ */
+#define REDZONE_SIZE 288
+
 int main(void);
 
 int main(void)
@@ -95,6 +100,7 @@  int main(void)
 	OFFSET(STACK_HSRR1,	stack_frame, hsrr1);
 	OFFSET(STACK_DAR,	stack_frame, dar);
 	DEFINE(STACK_FRAMESIZE,	sizeof(struct stack_frame));
+	DEFINE(INT_FRAMESIZE,	(sizeof(struct stack_frame) + REDZONE_SIZE));
 
 	return 0;
 }
diff --git a/asm/head.S b/asm/head.S
index f918a404a..f6475bcab 100644
--- a/asm/head.S
+++ b/asm/head.S
@@ -162,9 +162,23 @@  hdat_entry:
 
 	.= 0x1e00
 _exception:
-	stdu	%r1,-STACK_FRAMESIZE(%r1)
+	stdu	%r1,-INT_FRAMESIZE(%r1)
 	std	%r3,STACK_CFAR(%r1)
 	std	%r4,STACK_TYPE(%r1)
+	mfspr	%r3,SPR_SRR0
+	mfspr	%r4,SPR_SRR1
+	std	%r3,STACK_SRR0(%r1)
+	std	%r4,STACK_SRR1(%r1)
+	mfspr	%r3,SPR_DSISR
+	mfspr	%r4,SPR_DAR
+	stw	%r3,STACK_DSISR(%r1)
+	std	%r4,STACK_DAR(%r1)
+	mfmsr	%r3
+	std	%r3,STACK_MSR(%r1)
+	mfspr	%r3,SPR_HSRR0
+	mfspr	%r4,SPR_HSRR1
+	std	%r3,STACK_HSRR0(%r1)
+	std	%r4,STACK_HSRR1(%r1)
 	mfsprg0	%r3
 	mfsprg1 %r4
 	SAVE_GPR(0,%r1)
@@ -207,29 +221,68 @@  _exception:
 	stw	%r4,STACK_XER(%r1)
 	std	%r5,STACK_CTR(%r1)
 	std	%r6,STACK_LR(%r1)
-	mfspr	%r3,SPR_SRR0
-	mfspr	%r4,SPR_SRR1
-	mfspr	%r5,SPR_HSRR0
-	mfspr	%r6,SPR_HSRR1
-	std	%r3,STACK_SRR0(%r1)
-	std	%r4,STACK_SRR1(%r1)
-	std	%r5,STACK_HSRR0(%r1)
-	std	%r6,STACK_HSRR1(%r1)
-	mfspr	%r3,SPR_DSISR
-	mfspr	%r4,SPR_DAR
-	mfmsr	%r5
-	stw	%r3,STACK_DSISR(%r1)
-	std	%r4,STACK_DAR(%r1)
-	std	%r5,STACK_MSR(%r1)
 	mr	%r3,%r1
 	LOAD_IMM64(%r4, SKIBOOT_BASE)
 	LOAD_IMM32(%r5, exception_entry_foo - __head)
 	add	%r4,%r4,%r5
 	mtctr	%r4
-	bctrl
-	b	.
+	bctr
 exception_entry_foo:
-	b	exception_entry
+	bl	exception_entry
+	/* Restore HSRRs in case a NMI interrupted an HSRR-live section
+	 * and the NMI uses HSRRs for something. Possibly does not happen
+	 * in current skiboot code, but good to be careful.
+	 */
+	ld	%r3,STACK_HSRR0(%r1)
+	ld	%r4,STACK_HSRR1(%r1)
+	mtspr	SPR_HSRR0,%r3
+	mtspr	SPR_HSRR1,%r4
+	lwz	%r3,STACK_CR(%r1)
+	lwz	%r4,STACK_XER(%r1)
+	ld	%r5,STACK_CTR(%r1)
+	ld	%r6,STACK_LR(%r1)
+	mtcr	%r3
+	mtxer	%r4
+	mtctr	%r5
+	mtlr	%r6
+	REST_GPR(0,%r1)
+	REST_GPR(2,%r1)
+	REST_GPR(4,%r1)
+	REST_GPR(5,%r1)
+	REST_GPR(6,%r1)
+	REST_GPR(7,%r1)
+	REST_GPR(8,%r1)
+	REST_GPR(9,%r1)
+	REST_GPR(10,%r1)
+	REST_GPR(11,%r1)
+	REST_GPR(12,%r1)
+	REST_GPR(13,%r1)
+	REST_GPR(14,%r1)
+	REST_GPR(15,%r1)
+	REST_GPR(16,%r1)
+	REST_GPR(17,%r1)
+	REST_GPR(18,%r1)
+	REST_GPR(19,%r1)
+	REST_GPR(20,%r1)
+	REST_GPR(21,%r1)
+	REST_GPR(22,%r1)
+	REST_GPR(23,%r1)
+	REST_GPR(24,%r1)
+	REST_GPR(25,%r1)
+	REST_GPR(26,%r1)
+	REST_GPR(27,%r1)
+	REST_GPR(28,%r1)
+	REST_GPR(29,%r1)
+	REST_GPR(30,%r1)
+	REST_GPR(31,%r1)
+	ld	%r3,STACK_SRR0(%r1)
+	mtspr	SPR_SRR0,%r3
+	ld	%r3,STACK_SRR1(%r1)
+	mtspr	SPR_SRR1,%r3
+	REST_GPR(3,%r1)
+	addi	%r1,%r1,INT_FRAMESIZE
+	rfid
+	b	.
 
 	.= EXCEPTION_VECTORS_END
 	/* This is the OPAL branch table. It's populated at boot time
diff --git a/core/exceptions.c b/core/exceptions.c
index ed92edfbc..f05bcfb9e 100644
--- a/core/exceptions.c
+++ b/core/exceptions.c
@@ -40,9 +40,9 @@  static void dump_regs(struct stack_frame *stack)
 }
 
 /* Called from head.S, thus no prototype */
-void exception_entry(struct stack_frame *stack) __noreturn;
+void __noreturn exception_entry(struct stack_frame *stack);
 
-void exception_entry(struct stack_frame *stack)
+void __noreturn exception_entry(struct stack_frame *stack)
 {
 	uint64_t nip;
 	uint64_t msr;