From b3fe647eaf6b13d741ead85bb9548548dd45a7ca Mon Sep 17 00:00:00 2001 From: Sudan Landge Date: Fri, 12 Jul 2024 17:26:32 +0100 Subject: [PATCH] arch: arm: cortex_a_r: Fix restore of registers while exiting exception This commit fixes potential unpredictable behavior, caused by using the ^ form of ldmia instruction, while exiting an exception in SMP mode on Cortex-A/R. Change: Use "pop" instead of "ldmia" to restore user mode registers while exiting from an exception via `z_arm_cortex_ar_exit_exc`. Reason for change: Processor mode is always set to system (MODE_SYS) before calling `z_arm_cortex_ar_exit_exc` and hence, the user mode register can be accessed directly without the ^ form of the instruction. Also, LDMIA instruction is UNPREDICTABLE in SYStem mode. Signed-off-by: Sudan Landge --- arch/arm/core/cortex_a_r/isr_wrapper.S | 9 +++++++++ arch/arm/core/cortex_a_r/vector_table.S | 8 ++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/arm/core/cortex_a_r/isr_wrapper.S b/arch/arm/core/cortex_a_r/isr_wrapper.S index 2e2256ffbfd752..3dd678c4030f04 100644 --- a/arch/arm/core/cortex_a_r/isr_wrapper.S +++ b/arch/arm/core/cortex_a_r/isr_wrapper.S @@ -339,6 +339,15 @@ z_arm_cortex_ar_irq_done: str r0, [r2, #___cpu_t_nested_OFFSET] /* Do not context switch if exiting a nested interrupt */ cmp r0, #0 + /* Note that this function is only called from `z_arm_svc`, + * while handling irq_offload, with below modes set: + * ``` + * if (cpu interrupts are nested) + * mode=MODE_SYS + * else + * mode=MODE_IRQ + * ``` + */ bhi __EXIT_INT /* retrieve pointer to the current thread */ diff --git a/arch/arm/core/cortex_a_r/vector_table.S b/arch/arm/core/cortex_a_r/vector_table.S index 8c1060e61220cc..e74b6a41c8d6b7 100644 --- a/arch/arm/core/cortex_a_r/vector_table.S +++ b/arch/arm/core/cortex_a_r/vector_table.S @@ -41,6 +41,11 @@ SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table) GTEXT(z_arm_cortex_ar_exit_exc) SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_cortex_ar_exit_exc) + /* Note: + * This function is expected to be *always* called with + * processor mode set to MODE_SYS. + */ + /* decrement exception depth */ get_cpu r2 ldrb r1, [r2, #_cpu_offset_to_exc_depth] @@ -51,7 +56,6 @@ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_cortex_ar_exit_exc) * Restore r0-r3, r12, lr, lr_und and spsr_und from the exception stack * and return to the current thread. */ - ldmia sp, {r0-r3, r12, lr}^ - add sp, #24 + pop {r0-r3, r12, lr} rfeia sp! #endif