According to ARMv7-M and ARMv8-M reference manuals, exception stack frame is formed on currently active stack (MSP or PSP, depending on what was interrupted by the exception).
This decision looks unlogical to me: every process stack has to have a space for exception stack frame; it could be huge, especially when FPU and security extensions are used. But more importantly, it leaves at least one unanswered question: how to isolate process stack overflows from the rest of a system?
Suppose you have ARMv8-M platform (i.e. Cortex-M33) that runs unprivileged process with MPU restrictions enforced. Process has just a single MPU region for stack, and also PSPLIM register is set. Process runs near it's stack limit and the stack space is insufficient to hold exception frame.
Now some peripheral interrupt arrives. Most likely you will get an UsageFault with STKOF flag set. This is where problems start. First, you missed the exception. Most likely it is still pending and you will get it again. But how to recover?
UsageFault handling will be subject to same stack limits. There is still no space for exception frame. HardFault can ignore stack limits, but this does not make situation any better. Ignored stack limit means that memory beyond the stack is now corrupted. You could probably reserve some space after PSPLIM exactly for the HardFault, and at least you won't get corrupted memory.
Is there a safe way to deal with such situation? System should remain consistent and operational regardless of bugs (or malicious behavior) of unprivileged process.
TL;DR
Stack frame is not written. You lose the context of currently executing task. Inaccessible memory is not corrupted. UsageFault (for stack limit) or MemManage (for MPU violations) is taken instead of original exception. This behavior is well-documented in ARM reference manual. Invalid stack frame is signalled with
MMFSR.MSTKERR
orUFSR.STKOF
bits depending on the exception.Test program
Implemented test cases:
SPLIM is mostly redundant when MPU is active, but it may be useful when another MPU region is directly adjacent to stack region and MemManage is not generated.
Both thread ("regular") stack overflow and context stacking failure set
UFSR.STKOF
. From handler point of view, exact stack overflow reason is not important: task context is lost anyway.References
Observed behavior is documented in the following parts of ARMv8 architecture reference manual:
B3.18 Exception handling
This implies that context stacking happens while PE is still in Thread mode with all security restrictions still active.
B3.19 Exception entry, context stacking
B3.21 Stack limit checks
B3.24 Exceptions during exception entry