Skip to content

Commit

Permalink
[arch][arm-m] simplify context switch
Browse files Browse the repository at this point in the history
The context switch is now always performed inside the PendSV handler,
which greatly simplifies the code by reducing all switches to a single
path. This should also eliminate any race conditions during the switch.

Because we always enter PendSV for a switch, there is a slight
performance penalty in the case of switching from a non-preempted thread
to another non-preempted thread (~40 cycles longer on an M4, compared to
the previous implementation)
  • Loading branch information
fdischner committed Jun 21, 2023
1 parent 9cc95f1 commit f56c3d5
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 426 deletions.
2 changes: 1 addition & 1 deletion arch/arm/arm-m/arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void arm_cm_irq_exit(bool reschedule) {
target_set_debug_led(1, false);

if (reschedule)
arm_cm_trigger_preempt();
thread_preempt();

KEVLOG_IRQ_EXIT(__get_IPSR());

Expand Down
9 changes: 7 additions & 2 deletions arch/arm/arm-m/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ void _nmi(void) {
*/
#if (__CORTEX_M >= 0X03) || (__CORTEX_SC >= 300)
#define PUSH_REGS \
"push {r4-r11};"
"push {r4-r11, lr};"
#else
#define PUSH_REGS \
"push {r4-r7};" \
"push {r4-r7, lr};" \
"mov r4, r8;" \
"mov r5, r9;" \
"mov r6, r10;" \
Expand Down Expand Up @@ -177,3 +177,8 @@ void __WEAK _debugmonitor(void) {
printf("debugmonitor\n");
platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
}

void __WEAK _svc(void) {
printf("svc\n");
platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
}
9 changes: 0 additions & 9 deletions arch/arm/arm-m/include/arch/arch_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@

struct arch_thread {
vaddr_t sp;
bool was_preempted;

#if ARM_WITH_VFP
/* has this thread ever used the floating point state? */
bool fpused;

/* s16-s31 saved here. s0-s15, fpscr saved on exception frame */
float fpregs[16];
#endif
};

#endif
Expand Down
40 changes: 23 additions & 17 deletions arch/arm/arm-m/include/arch/arm/cm.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#define SCB_DEMCR (0xE000EDFC)

struct arm_cm_exception_frame {
#if (__CORTEX_M >= 0x03)
uint32_t r4;
uint32_t r5;
uint32_t r6;
Expand All @@ -46,6 +47,18 @@ struct arm_cm_exception_frame {
uint32_t r9;
uint32_t r10;
uint32_t r11;
#else
/* frame format is slightly different due to ordering of push/pops */
uint32_t r8;
uint32_t r9;
uint32_t r10;
uint32_t r11;
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t r7;
#endif
uint32_t exc_return;
uint32_t r0;
uint32_t r1;
uint32_t r2;
Expand All @@ -56,18 +69,10 @@ struct arm_cm_exception_frame {
uint32_t psr;
};

struct arm_cm_exception_frame_short {
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t lr;
uint32_t pc;
uint32_t psr;
};
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)

struct arm_cm_exception_frame_long {
/* exception frame when fpu context save is enabled */
struct arm_cm_exception_frame_fpu {
uint32_t r4;
uint32_t r5;
uint32_t r6;
Expand All @@ -76,22 +81,23 @@ struct arm_cm_exception_frame_long {
uint32_t r9;
uint32_t r10;
uint32_t r11;
uint32_t lr;
uint32_t exc_return;

float s16_31[16];

uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t exc_lr;
uint32_t lr;
uint32_t pc;
uint32_t psr;
};

/* when fpu context save is enabled, this goes just above psr in the previous structs */
struct arm_cm_exception_frame_fpu {
float s[16];
float s0_15[16];
uint32_t fpscr;
};
#endif

#if ARM_CM_DYNAMIC_PRIORITY_SIZE
extern unsigned int arm_cm_num_irq_pri_bits;
Expand Down
Loading

0 comments on commit f56c3d5

Please sign in to comment.