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 <[email protected]>
AuthorDate: Wed May 13 15:16:45 2020 +0800

    armv8-m: Add stack overflow by stack pointer limit register
    
    Signed-off-by: qiaowei <[email protected]>
    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

Reply via email to