You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/05/18 13:21:15 UTC
[incubator-nuttx] branch master updated: armv8-m: Add stack
overflow by stack pointer limit register
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new cddd64f armv8-m: Add stack overflow by stack pointer limit register
cddd64f is described below
commit cddd64fd30987a1dde018d0e80ec8af137d9e27e
Author: qiaowei <qi...@xiaomi.com>
AuthorDate: Wed May 13 15:16:45 2020 +0800
armv8-m: Add stack overflow by stack pointer limit register
Signed-off-by: qiaowei <qi...@xiaomi.com>
Change-Id: I0f0ae0fb8edb8e1690b3c5e3e8b3189d51a318b0
---
arch/arm/include/armv8-m/irq_cmnvector.h | 8 +++++-
arch/arm/include/armv8-m/irq_lazyfpu.h | 8 +++++-
arch/arm/src/armv8-m/Kconfig | 28 +++++++++++++++++----
arch/arm/src/armv8-m/arm_exception.S | 42 +++++++++++++++++++++++++++++---
arch/arm/src/armv8-m/arm_initialstate.c | 6 +++++
arch/arm/src/armv8-m/arm_lazyexception.S | 41 ++++++++++++++++++++++++++++---
6 files changed, 118 insertions(+), 15 deletions(-)
diff --git a/arch/arm/include/armv8-m/irq_cmnvector.h b/arch/arm/include/armv8-m/irq_cmnvector.h
index 24b02b3..4c784e7 100644
--- a/arch/arm/include/armv8-m/irq_cmnvector.h
+++ b/arch/arm/include/armv8-m/irq_cmnvector.h
@@ -82,7 +82,13 @@
/* The total number of registers saved by software */
-#define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS)
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+# define REG_SPLIM (SW_INT_REGS + SW_FPU_REGS + 0) /* REG_SPLIM */
+# define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS + 1)
+#else
+# define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS)
+#endif
+
#define SW_XCPT_SIZE (4 * SW_XCPT_REGS)
/* On entry into an IRQ, the hardware automatically saves the following
diff --git a/arch/arm/include/armv8-m/irq_lazyfpu.h b/arch/arm/include/armv8-m/irq_lazyfpu.h
index 88c5e03..33af6d8 100644
--- a/arch/arm/include/armv8-m/irq_lazyfpu.h
+++ b/arch/arm/include/armv8-m/irq_lazyfpu.h
@@ -129,7 +129,13 @@
/* The total number of registers saved by software */
-#define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS)
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+# define REG_SPLIM (SW_INT_REGS + SW_FPU_REGS + 0) /* REG_SPLIM */
+# define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS + 1)
+#else
+# define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS)
+#endif
+
#define SW_XCPT_SIZE (4 * SW_XCPT_REGS)
/* On entry into an IRQ, the hardware automatically saves the following
diff --git a/arch/arm/src/armv8-m/Kconfig b/arch/arm/src/armv8-m/Kconfig
index 991f740..016d8d4 100644
--- a/arch/arm/src/armv8-m/Kconfig
+++ b/arch/arm/src/armv8-m/Kconfig
@@ -155,14 +155,15 @@ config ARMV8M_TARGET2_PREL
---help---
Perform a PC relative relocation for relocation type R_ARM_TARGET2
-config ARMV8M_HAVE_STACKCHECK
- bool
- default n
+choice
+ prompt "Select the stack protection Schema"
+ default ARMV8M_STACKCHECK_NONE
+
+config ARMV8M_STACKCHECK_NONE
+ bool "Do not check for stack overflow"
config ARMV8M_STACKCHECK
bool "Check for stack overflow on each function call"
- default n
- depends on ARMV8M_HAVE_STACKCHECK
---help---
This check uses R10 to check for a stack overflow within each
function call. This has performances and code size impacts, but it
@@ -177,6 +178,23 @@ config ARMV8M_STACKCHECK
compile. This addition to your CFLAGS should probably be added
to the definition of the CFFLAGS in your board Make.defs file.
+config ARMV8M_STACKCHECK_HARDWARE
+ bool "Check for stack overflow by stack pointer limit register"
+ ---help---
+ This option signifies the CPU has the MSPLIM, PSPLIM registers.
+
+ The stack pointer limit registers, MSPLIM, PSPLIM, limit the
+ extend to which the Main and Process Stack Pointers, respectively,
+ can descend. MSPLIM, PSPLIM are always present in ARMv8-M
+ MCUs that implement the ARMv8-M Main Extension (Mainline).
+
+ In an ARMv8-M Mainline implementation with the Security Extension
+ the MSPLIM, PSPLIM registers have additional Secure instances.
+ In an ARMv8-M Baseline implementation with the Security Extension
+ the MSPLIM, PSPLIM registers have only Secure instances.
+
+endchoice
+
config ARMV8M_ITMSYSLOG
bool "ITM SYSLOG support"
default n
diff --git a/arch/arm/src/armv8-m/arm_exception.S b/arch/arm/src/armv8-m/arm_exception.S
index 85951b5..c7dc5af 100644
--- a/arch/arm/src/armv8-m/arm_exception.S
+++ b/arch/arm/src/armv8-m/arm_exception.S
@@ -105,6 +105,10 @@
#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 7
.macro setintstack, tmp1, tmp2
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ ldr \tmp1, =g_intstackalloc
+ msr msplim, \tmp1
+#endif
ldr sp, =g_intstackbase
.endm
#endif
@@ -148,12 +152,23 @@ exception_common:
tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
beq 1f /* Branch if context already on the MSP */
mrs r1, psp /* R1=The process stack pointer (PSP) */
- mov sp, r1 /* Set the MSP to the PSP */
-
+ mov sp, r1 /* Set the MSP to the PSP */
1:
mov r2, sp /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
/* (ignoring the xPSR[9] alignment bit) */
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ mov r3, #0x0
+
+ ittee eq
+ mrseq r1, msplim
+ msreq msplim, r3
+ mrsne r1, psplim
+ msrne psplim, r3
+
+ stmdb sp!, {r1}
+#endif
+
#ifdef CONFIG_ARMV8M_USEBASEPRI
mrs r3, basepri /* R3=Current BASEPRI setting */
#else
@@ -249,7 +264,11 @@ exception_common:
stmdb r1!, {r4-r11} /* Store eight registers on the return stack */
ldmia r0!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */
#ifdef CONFIG_ARCH_FPU
- vldmia r0, {s16-s31} /* Recover S16-S31 */
+ vldmia r0!, {s16-s31} /* Recover S16-S31 */
+#endif
+
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ ldmia r0, {r0} /* Get psplim/msplim*/
#endif
b 3f /* Re-join common logic */
@@ -261,7 +280,11 @@ exception_common:
ldmia r1!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */
#ifdef CONFIG_ARCH_FPU
- vldmia r1!, {s16-s31} /* Recover S16-S31 */
+ vldmia r1!, {s16-s31} /* Recover S16-S31 */
+#endif
+
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ ldmia r1!, {r0} /* Get psplim/msplim */
#endif
3:
@@ -279,15 +302,26 @@ exception_common:
beq 4f /* Branch if privileged */
orr r2, r2, #1 /* Unprivileged mode */
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ msr psplim, r0
+#endif
msr psp, r1 /* R1=The process stack pointer */
b 5f
4:
bic r2, r2, #1 /* Privileged mode */
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ msr msplim, r0
+#endif
msr msp, r1 /* R1=The main stack pointer */
5:
msr control, r2 /* Save the updated control register */
#else
tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ ite eq
+ msreq msplim, r0
+ msrne psplim, r0
+#endif
ite eq /* next two instructions conditional */
msreq msp, r1 /* R1=The main stack pointer */
msrne psp, r1 /* R1=The process stack pointer */
diff --git a/arch/arm/src/armv8-m/arm_initialstate.c b/arch/arm/src/armv8-m/arm_initialstate.c
index ad6751f..969c9be 100644
--- a/arch/arm/src/armv8-m/arm_initialstate.c
+++ b/arch/arm/src/armv8-m/arm_initialstate.c
@@ -73,6 +73,12 @@ void up_initial_state(struct tcb_s *tcb)
xcp->regs[REG_R10] = (uint32_t)tcb->stack_alloc_ptr + 64;
#endif
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ /* Save the stack limit value, will be used in context switch. */
+
+ xcp->regs[REG_SPLIM] = (uint32_t)tcb->stack_alloc_ptr;
+#endif
+
/* Save the task entry point (stripping off the thumb bit) */
xcp->regs[REG_PC] = (uint32_t)tcb->start & ~1;
diff --git a/arch/arm/src/armv8-m/arm_lazyexception.S b/arch/arm/src/armv8-m/arm_lazyexception.S
index 2bb1093..ade51c1 100644
--- a/arch/arm/src/armv8-m/arm_lazyexception.S
+++ b/arch/arm/src/armv8-m/arm_lazyexception.S
@@ -88,6 +88,10 @@
#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 7
.macro setintstack, tmp1, tmp2
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ ldr \tmp1, =g_intstackalloc
+ msr msplim, \tmp1
+#endif
ldr sp, =g_intstackbase
.endm
#endif
@@ -125,16 +129,17 @@ exception_common:
/* Complete the context save */
+ tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
+
#ifdef CONFIG_BUILD_PROTECTED
/* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1
* (handler mode) if the stack is on the MSP. It can only be on the PSP if
* EXC_RETURN is 0xfffffffd (unprivileged thread)
*/
- tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
beq 1f /* Branch if context already on the MSP */
mrs r1, psp /* R1=The process stack pointer (PSP) */
- mov sp, r1 /* Set the MSP to the PSP */
+ mov sp, r1 /* Set the MSP to the PSP */
1:
#endif
@@ -147,6 +152,18 @@ exception_common:
mov r2, sp /* R2=Copy of the main/process stack pointer */
add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ mov r3, #0x0
+
+ ittee eq
+ mrseq r1, msplim
+ msreq msplim, r3
+ mrsne r1, psplim
+ msrne psplim, r3
+
+ stmdb sp!, {r1}
+#endif
+
#ifdef CONFIG_ARMV8M_USEBASEPRI
mrs r3, basepri /* R3=Current BASEPRI setting */
#else
@@ -246,9 +263,12 @@ exception_common:
ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */
stmdb r1!, {r4-r11} /* Store eight registers in HW save area */
#ifdef CONFIG_BUILD_PROTECTED
- ldmia r0, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */
+ ldmia r0!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */
#else
- ldmia r0, {r2-r11} /* Recover R4-R11 + 2 temp values */
+ ldmia r0!, {r2-r11} /* Recover R4-R11 + 2 temp values */
+#endif
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ ldmia r0, {r0} /* Get psplim/msplim*/
#endif
b 3f /* Re-join common logic */
@@ -274,6 +294,10 @@ exception_common:
add r1, #(4*SW_FPU_REGS)
#endif
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ ldmia r1!, {r0} /* Get psplim/msplim */
+#endif
+
/* Set up to return from the exception
*
* Here:
@@ -296,14 +320,23 @@ exception_common:
beq 4f /* Branch if privileged */
orr r2, r2, #1 /* Unprivileged mode */
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ msr psplim, r0
+#endif
msr psp, r1 /* R1=The process stack pointer */
b 5f
4:
bic r2, r2, #1 /* Privileged mode */
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ msr msplim, r0
+#endif
msr msp, r1 /* R1=The main stack pointer */
5:
msr control, r2 /* Save the updated control register */
#else
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+ msr msplim, r0
+#endif
msr msp, r1 /* Recover the return MSP value */
/* Preload r14 with the special return value first (so that the return