mirror of
https://github.com/apache/nuttx.git
synced 2026-08-20 04:58:28 +00:00
armv8-m: Add stack overflow by stack pointer limit register
Signed-off-by: qiaowei <qiaowei@xiaomi.com> Change-Id: I0f0ae0fb8edb8e1690b3c5e3e8b3189d51a318b0
This commit is contained in:
parent
57bc329aac
commit
cddd64fd30
6 changed files with 118 additions and 15 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue