[arch][arm-m] add additional comments and asserts to exception/context switch code

This commit is contained in:
Travis Geiselbrecht
2024-02-26 00:49:04 -08:00
parent be19e2a960
commit 770d475224
3 changed files with 40 additions and 22 deletions

View File

@@ -116,51 +116,51 @@ void _nmi(void) {
*/
#if (__CORTEX_M >= 0X03) || (__CORTEX_SC >= 300)
#define PUSH_REGS \
"push {r4-r11, lr};"
"push {r4-r11, lr};" /* 9 words on the stack */
#else
#define PUSH_REGS \
"push {r4-r7, lr};" \
"mov r4, r8;" \
"mov r5, r9;" \
"mov r6, r10;" \
"mov r7, r11;" \
"push {r4-r7};"
"push {r4-r7, lr};" /* 5 words */ \
"mov r4, r8;" \
"mov r5, r9;" \
"mov r6, r10;" \
"mov r7, r11;" \
"push {r4-r7};" /* 4 more words */
#endif
__NAKED void _hardfault(void) {
__asm__ volatile(
PUSH_REGS
"mov r0, sp;"
"b hardfault;"
"mov r0, sp;"
"sub sp, #4;" /* adjust the stack to be 8 byte aligned */
"b hardfault;"
);
__UNREACHABLE;
}
__NAKED void _memmanage(void) {
__asm__ volatile(
PUSH_REGS
"mov r0, sp;"
"b memmanage;"
"mov r0, sp;"
"sub sp, #4;" /* adjust the stack to be 8 byte aligned */
"b memmanage;"
);
__UNREACHABLE;
}
__NAKED void _busfault(void) {
__asm__ volatile(
PUSH_REGS
"mov r0, sp;"
"b busfault;"
"mov r0, sp;"
"sub sp, #4;" /* adjust the stack to be 8 byte aligned */
"b busfault;"
);
__UNREACHABLE;
}
__NAKED void _usagefault(void) {
__asm__ volatile(
PUSH_REGS
"mov r0, sp;"
"b usagefault;"
"mov r0, sp;"
"sub sp, #4;" /* adjust the stack to be 8 byte aligned */
"b usagefault;"
);
__UNREACHABLE;
}
#undef PUSH_REGS

View File

@@ -10,6 +10,7 @@
/* support header for all cortex-m class cpus */
#include <assert.h>
#include <lk/compiler.h>
#include <stdint.h>
#include <stdbool.h>
@@ -59,6 +60,8 @@ struct arm_cm_exception_frame {
uint32_t r7;
#endif
uint32_t exc_return;
/* hardware pushes this */
uint32_t r0;
uint32_t r1;
uint32_t r2;
@@ -69,6 +72,8 @@ struct arm_cm_exception_frame {
uint32_t psr;
};
static_assert(sizeof(struct arm_cm_exception_frame) == 17 * 4, "");
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
/* exception frame when fpu context save is enabled */
@@ -85,6 +90,7 @@ struct arm_cm_exception_frame_fpu {
float s16_31[16];
/* hardware pushes this */
uint32_t r0;
uint32_t r1;
uint32_t r2;
@@ -94,9 +100,14 @@ struct arm_cm_exception_frame_fpu {
uint32_t pc;
uint32_t psr;
/* additional state the cpu pushes when using an extended frame */
float s0_15[16];
uint32_t fpscr;
uint32_t reserved;
};
static_assert(sizeof(struct arm_cm_exception_frame_fpu) == (9 + 16 + 8 + 16 + 2) * 4, "");
#endif
#if ARM_CM_DYNAMIC_PRIORITY_SIZE
@@ -158,12 +169,13 @@ static inline void arm_cm_trigger_interrupt(int vector) {
}
#endif
static inline void arm_cm_trigger_preempt(void) {
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
static inline bool arm_cm_is_preempt_triggered(void) {
return SCB->ICSR & SCB_ICSR_PENDSVSET_Msk;
}
/* systick */
void arm_cm_systick_init(uint32_t mhz);

View File

@@ -106,7 +106,7 @@ static vaddr_t pendsv_swap_sp(vaddr_t old_frame) {
DEBUG_ASSERT(((uintptr_t)__GET_FRAME() & 0x7) == 0);
DEBUG_ASSERT_MSG(!spin_lock_held(&thread_lock),
"PENDSV: thread lock was held when preempted! pc %#x\n", ((struct arm_cm_exception_frame *)old_frame)->pc);
"PENDSV: thread lock was held when preempted! pc %#x\n", ((struct arm_cm_exception_frame *)old_frame)->pc);
DEBUG_ASSERT(_prev_running_thread != NULL);
DEBUG_ASSERT(_current_thread != NULL);
@@ -181,6 +181,12 @@ void arch_context_switch(struct thread *oldthread, struct thread *newthread) {
arm_cm_trigger_preempt();
}
/*
* Make sure either pendsv is queued up either via the previous if statement
* or via a nested preemption.
*/
DEBUG_ASSERT(arm_cm_is_preempt_triggered());
if (!in_interrupt_context) {
/* we're in thread context, so jump to PendSV immediately */