[PATCH v2 3/4] arm: Fix stack alignment during interrupt handling
Sebastian Huber
sebastian.huber at embedded-brains.de
Fri Jan 14 13:17:35 UTC 2022
On a public interface, the stack pointer must be aligned on an 8-byte
boundary. However, it may temporarily be only aligned on a 4-byte
boundary. The interrupt handling code must ensure that the stack
pointer is properly aligned before it calls a function. See also:
https://developer.arm.com/documentation/den0013/d/Interrupt-Handling/External-interrupt-requests/Nested-interrupt-handling
Close #4579.
---
cpukit/score/cpu/arm/arm_exc_interrupt.S | 39 +++++++++++++++---------
1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/cpukit/score/cpu/arm/arm_exc_interrupt.S b/cpukit/score/cpu/arm/arm_exc_interrupt.S
index 77e57ff5e7..a239d3a7cd 100644
--- a/cpukit/score/cpu/arm/arm_exc_interrupt.S
+++ b/cpukit/score/cpu/arm/arm_exc_interrupt.S
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2009, 2016 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2009, 2022 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -34,6 +34,9 @@
#ifdef ARM_MULTILIB_ARCH_V4
+#define STACK_POINTER_ADJUST r7
+#define NON_VOLATILE_SCRATCH r9
+
#define EXCHANGE_LR r4
#define EXCHANGE_SPSR r5
#define EXCHANGE_CPSR r6
@@ -42,9 +45,7 @@
#define EXCHANGE_LIST {EXCHANGE_LR, EXCHANGE_SPSR, EXCHANGE_CPSR, EXCHANGE_INT_SP}
#define EXCHANGE_SIZE 16
-#define NON_VOLATILE_SCRATCH r9
-
-#define CONTEXT_LIST {r0, r1, r2, r3, EXCHANGE_LR, EXCHANGE_SPSR, r7, r12}
+#define CONTEXT_LIST {r0, r1, r2, r3, EXCHANGE_LR, EXCHANGE_SPSR, NON_VOLATILE_SCRATCH, r12}
#define CONTEXT_SIZE 32
.arm
@@ -67,12 +68,20 @@ _ARMV4_Exception_interrupt:
/*
* Save context. We save the link register separately because it has
* to be restored in SVC mode. The other registers can be restored in
- * INT mode. Ensure that stack remains 8 byte aligned. Use register
- * necessary for the stack alignment for the stack pointer of the
- * interrupted context.
+ * INT mode. Provide a non-volatile scratch register which may be used
+ * accross function calls.
*/
push CONTEXT_LIST
- push {NON_VOLATILE_SCRATCH, lr}
+ push {STACK_POINTER_ADJUST, lr}
+
+ /*
+ * On a public interface, the stack pointer must be aligned on an
+ * 8-byte boundary. However, it may temporarily be only aligned on a
+ * 4-byte boundary. Make sure the stack pointer is aligned on an
+ * 8-byte boundary.
+ */
+ and STACK_POINTER_ADJUST, sp, #0x4
+ sub sp, sp, STACK_POINTER_ADJUST
/* Get per-CPU control of current processor */
GET_SELF_CPU_CONTROL r0
@@ -138,9 +147,6 @@ _ARMV4_Exception_interrupt:
/* Restore stack pointer */
mov sp, NON_VOLATILE_SCRATCH
- /* Save CPSR in non-volatile register */
- mrs NON_VOLATILE_SCRATCH, CPSR
-
/* Decrement levels and determine thread dispatch state */
eor r1, r1, r12
sub r12, r12, #1
@@ -159,9 +165,11 @@ _ARMV4_Exception_interrupt:
cmp r1, #0
bne .Lthread_dispatch_done
- /* Thread dispatch */
+ /* Save CPSR in non-volatile register */
mrs NON_VOLATILE_SCRATCH, CPSR
+ /* Thread dispatch */
+
.Ldo_thread_dispatch:
/* Set ISR dispatch disable and thread dispatch disable level to one */
@@ -203,8 +211,11 @@ _ARMV4_Exception_interrupt:
vmsr FPSCR, r2
#endif /* ARM_MULTILIB_VFP */
- /* Restore NON_VOLATILE_SCRATCH register and link register */
- pop {NON_VOLATILE_SCRATCH, lr}
+ /* Undo stack pointer adjustment */
+ add sp, sp, STACK_POINTER_ADJUST
+
+ /* Restore STACK_POINTER_ADJUST register and link register */
+ pop {STACK_POINTER_ADJUST, lr}
/*
* XXX: Remember and restore stack pointer. The data on the stack is
--
2.31.1
More information about the devel
mailing list