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