Skip to content

Commit

Permalink
arch: cortex-m3: catch stack overflow
Browse files Browse the repository at this point in the history
  • Loading branch information
bradjc committed Jul 16, 2020
1 parent 1ec0b41 commit 6b32c45
Showing 1 changed file with 82 additions and 38 deletions.
120 changes: 82 additions & 38 deletions arch/cortex-m3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,52 +373,96 @@ pub unsafe extern "C" fn hard_fault_handler() {
let faulting_stack: *mut u32;
let kernel_stack: bool;

// First need to determine if this a kernel fault or a userspace fault.
llvm_asm!(
"mov r1, 0 \n\
tst lr, #4 \n\
itte eq \n\
mrseq r0, msp \n\
addeq r1, 1 \n\
mrsne r0, psp "
"
mov r1, 0 /* r1 = 0 */
tst lr, #4 /* bitwise AND link register to 0b100 */
itte eq /* if lr==4, run next two instructions, else, run 3rd instruction. */
mrseq r0, msp /* r0 = kernel stack pointer */
addeq r1, 1 /* r1 = 1, kernel was executing */
mrsne r0, psp /* r0 = userland stack pointer */"
: "={r0}"(faulting_stack), "={r1}"(kernel_stack)
:
: "r0", "r1"
: "volatile"
);
: "volatile" );

if kernel_stack {
kernel_hardfault(faulting_stack);
// Need to determine if we had a stack overflow before we push anything
// on to the stack. We check this by looking at the BusFault Status
// Register's (BFSR) `LSPERR` and `STKERR` bits to see if the hardware
// had any trouble stacking important registers to the stack during the
// fault. If so, then we cannot use this stack while handling this fault
// or we will trigger another fault.
let stack_overflow: bool;
llvm_asm!(
"
ldr r2, =0xE000ED29 /* SCB BFSR register address */
ldrb r2, [r2] /* r2 = BFSR */
tst r2, #0x30 /* r2 = BFSR & 0b00110000; LSPERR & STKERR bits */
ite ne /* check if the result of that bitwise AND was not 0 */
movne r3, #1 /* BFSR & 0b00110000 != 0; r3 = 1 */
moveq r3, #0 /* BFSR & 0b00110000 == 0; r3 = 0 */"
: "={r3}"(stack_overflow)
:
: "r3"
: "volatile" );

if stack_overflow {
// The hardware couldn't use the stack, so we have no saved data and
// we cannot use the kernel stack as is. We just want to report that
// the kernel's stack overflowed, since that is essential for
// debugging.
//
// To make room for a panic!() handler stack, we just re-use the
// kernel's original stack. This should in theory leave the bottom
// of the stack where the problem occurred untouched should one want
// to further debug.
llvm_asm!(
"
mov sp, r0 /* Set the stack pointer to _estack */"
:
: "{r0}"((_estack as *const ()) as u32)
: "volatile" );

// Panic to show the correct error.
panic!("kernel stack overflow");
} else {
// Show the normal kernel hardfault message.
kernel_hardfault(faulting_stack);
}
} else {
// hard fault occurred in an app, not the kernel. The app should be
// marked as in an error state and handled by the kernel
// Hard fault occurred in an app, not the kernel. The app should be
// marked as in an error state and handled by the kernel.
llvm_asm!(
"ldr r0, =APP_HARD_FAULT
mov r1, #1 /* Fault */
str r1, [r0, #0]
/* Read the SCB registers. */
ldr r0, =SCB_REGISTERS
ldr r1, =0xE000ED14
ldr r2, [r1, #0] /* CCR */
str r2, [r0, #0]
ldr r2, [r1, #20] /* CFSR */
str r2, [r0, #4]
ldr r2, [r1, #24] /* HFSR */
str r2, [r0, #8]
ldr r2, [r1, #32] /* MMFAR */
str r2, [r0, #12]
ldr r2, [r1, #36] /* BFAR */
str r2, [r0, #16]
/* Set thread mode to privileged */
mov r0, #0
msr CONTROL, r0
/* CONTROL writes must be followed by ISB */
/* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHFJCAC.html */
isb
movw LR, #0xFFF9
movt LR, #0xFFFF"
"
/* Read the relevant SCB registers. */
ldr r0, =SCB_REGISTERS /* Global variable address */
ldr r1, =0xE000ED14 /* SCB CCR register address */
ldr r2, [r1, #0] /* CCR */
str r2, [r0, #0]
ldr r2, [r1, #20] /* CFSR */
str r2, [r0, #4]
ldr r2, [r1, #24] /* HFSR */
str r2, [r0, #8]
ldr r2, [r1, #32] /* MMFAR */
str r2, [r0, #12]
ldr r2, [r1, #36] /* BFAR */
str r2, [r0, #16]
ldr r0, =APP_HARD_FAULT /* Global variable address */
mov r1, #1 /* r1 = 1 */
str r1, [r0, #0] /* APP_HARD_FAULT = 1 */
/* Set thread mode to privileged */
mov r0, #0
msr CONTROL, r0
/* CONTROL writes must be followed by ISB */
/* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHFJCAC.html */
isb
movw LR, #0xFFF9
movt LR, #0xFFFF"
: : : : "volatile" );
}
}
Expand Down

0 comments on commit 6b32c45

Please sign in to comment.