From b7b170a0017c5824357b147cc7ddd7d3f006e332 Mon Sep 17 00:00:00 2001 From: Brad Campbell Date: Fri, 22 Nov 2024 14:23:13 -0500 Subject: [PATCH 1/3] arch: cortex-m: v7m: check SPSEL in EXC_RETURN In the exception handling assembly for the cortex-m platform we have been using the full value of `EXC_RETURN` for checking if we are coming from userspace and for directing where we should go to after the exception handler returns. This has been effective, but has two drawbacks: 1. It will not work for full floating point-enabled hardware/software that uses the larger exception frame. 2. It will not work for the v8m architecture which uses more of the bits that are reserved on v7m. As we look to support more cortex-m architectures, this change will make that easier. This should have no effect on our current v7m no fp platforms. --- arch/cortex-v7m/src/lib.rs | 49 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/arch/cortex-v7m/src/lib.rs b/arch/cortex-v7m/src/lib.rs index 06d63ab6b4..6194eb858a 100644 --- a/arch/cortex-v7m/src/lib.rs +++ b/arch/cortex-v7m/src/lib.rs @@ -45,9 +45,10 @@ core::arch::global_asm!( // (ISB). https://developer.arm.com/documentation/dai0321/latest isb // synchronization barrier - // Set the link register to the special EXC_RETURN value of 0xFFFFFFF9 which - // instructs the CPU to run in thread mode with the main (kernel) stack. - ldr lr, =0xFFFFFFF9 // LR = 0xFFFFFFF9 + // The link register is set to the `EXC_RETURN` value on exception entry. To + // ensure we continue executing in the kernel we ensure the SPSEL bit is set + // to 0 to use the main (kernel) stack. + bfc lr, #2, #1 // LR = LR & !(0x1<<2) // This will resume in the switch_to_user function where application state // is saved and the scheduler can choose what to do next. @@ -72,10 +73,12 @@ core::arch::global_asm!( .thumb_func svc_handler_arm_v7m: // First check to see which direction we are going in. If the link register - // is something other than 0xFFFFFFF9, then we are coming from an app which - // has called a syscall. - cmp lr, #0xFFFFFFF9 // LR ≟ 0xFFFFFFF9 - bne 100f // to_kernel // if LR != 0xFFFFFFF9, jump to to_kernel + // (containing EXC_RETURN) has a 1 in the SPSEL bit (meaning the + // alternative/process stack was in use) then we are coming from an app + // which has called a syscall. + ubfx r0, lr, #2, #1 // r0 = (LR & (0x1<<2)) >> 2 + cmp r0, #0 // LR ≟ 0 + bne 100f // to_kernel // if LR != 1, jump to to_kernel // If we get here, then this is a context switch from the kernel to the // application. Use the CONTROL register to set the thread mode to @@ -93,9 +96,11 @@ core::arch::global_asm!( // (ISB). https://developer.arm.com/documentation/dai0321/latest isb - // Set the link register to the special EXC_RETURN value of 0xFFFFFFFD which - // instructs the CPU to run in thread mode with the process stack. - ldr lr, =0xFFFFFFFD // LR = 0xFFFFFFFD + // The link register is set to the `EXC_RETURN` value on exception entry. To + // ensure we execute using the application stack we set the SPSEL bit to 1 + // to use the alternate (process) stack. + mov r0, #1 // r0 = 1 + bfi lr, r0, #2, #1 // LR = LR | (0x1<<2) // Switch to the app. bx lr @@ -124,9 +129,10 @@ core::arch::global_asm!( // (ISB). https://developer.arm.com/documentation/dai0321/latest isb - // Set the link register to the special EXC_RETURN value of 0xFFFFFFF9 which - // instructs the CPU to run in thread mode with the main (kernel) stack. - ldr lr, =0xFFFFFFF9 // LR = 0xFFFFFFF9 + // The link register is set to the `EXC_RETURN` value on exception entry. To + // ensure we continue executing in the kernel we ensure the SPSEL bit is set + // to 0 to use the main (kernel) stack. + bfc lr, #2, #1 // LR = LR & !(0x1<<2) // Return to the kernel. bx lr @@ -163,10 +169,6 @@ core::arch::global_asm!( // (ISB). https://developer.arm.com/documentation/dai0321/latest isb - // Set the link register to the special EXC_RETURN value of 0xFFFFFFF9 which - // instructs the CPU to run in thread mode with the main (kernel) stack. - ldr lr, =0xFFFFFFF9 // LR = 0xFFFFFFF9 - // Now need to disable the interrupt that fired in the NVIC to ensure it // does not trigger again before the scheduler has a chance to handle it. We // do this here in assembly for performance. @@ -206,6 +208,11 @@ core::arch::global_asm!( ldr r3, =0xe000e200 // r3 = &NVIC.ISPR str r0, [r3, r2, lsl #2] // *(r3 + r2 * 4) = r0 + // The link register is set to the `EXC_RETURN` value on exception entry. To + // ensure we continue executing in the kernel we ensure the SPSEL bit is set + // to 0 to use the main (kernel) stack. + bfc lr, #2, #1 // LR = LR & !(0x1<<2) + // Now we can return from the interrupt context and resume what we were // doing. If an app was executing we will switch to the kernel so it can // choose whether to service the interrupt. @@ -516,9 +523,11 @@ core::arch::global_asm!( // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHFJCAC.html isb - // Switch to the kernel (MSP) stack: - movw lr, #0xFFF9 - movt lr, #0xFFFF + // The link register is set to the `EXC_RETURN` value on exception + // entry. To ensure we continue executing in the kernel we ensure the + // SPSEL bit is set to 0 to use the main (kernel) stack. + bfc lr, #2, #1 // LR = LR & !(0x1<<2) + bx lr", estack = sym _estack, kernel_hard_fault_handler = sym hard_fault_handler_arm_v7m_kernel, From d7fd11c0680674ef1f8a7c8dbaba23ddac8e779a Mon Sep 17 00:00:00 2001 From: Brad Campbell Date: Mon, 25 Nov 2024 12:08:54 -0500 Subject: [PATCH 2/3] arch: v7m: cleanup comment for svc handler --- arch/cortex-v7m/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/cortex-v7m/src/lib.rs b/arch/cortex-v7m/src/lib.rs index 6194eb858a..79287065a1 100644 --- a/arch/cortex-v7m/src/lib.rs +++ b/arch/cortex-v7m/src/lib.rs @@ -77,8 +77,8 @@ core::arch::global_asm!( // alternative/process stack was in use) then we are coming from an app // which has called a syscall. ubfx r0, lr, #2, #1 // r0 = (LR & (0x1<<2)) >> 2 - cmp r0, #0 // LR ≟ 0 - bne 100f // to_kernel // if LR != 1, jump to to_kernel + cmp r0, #0 // r0 (SPSEL bit) ≟ 0 + bne 100f // to_kernel // if SPSEL == 1, jump to to_kernel // If we get here, then this is a context switch from the kernel to the // application. Use the CONTROL register to set the thread mode to From 5ca70175976209629ffc2ad890f67edbc5621de5 Mon Sep 17 00:00:00 2001 From: Amit Levy Date: Wed, 27 Nov 2024 10:25:58 -0800 Subject: [PATCH 3/3] arch: cortex-v7m: fix wording re process vs app --- arch/cortex-v7m/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/cortex-v7m/src/lib.rs b/arch/cortex-v7m/src/lib.rs index 79287065a1..1738fe05c2 100644 --- a/arch/cortex-v7m/src/lib.rs +++ b/arch/cortex-v7m/src/lib.rs @@ -74,10 +74,10 @@ core::arch::global_asm!( svc_handler_arm_v7m: // First check to see which direction we are going in. If the link register // (containing EXC_RETURN) has a 1 in the SPSEL bit (meaning the - // alternative/process stack was in use) then we are coming from an app + // alternative/process stack was in use) then we are coming from a process // which has called a syscall. ubfx r0, lr, #2, #1 // r0 = (LR & (0x1<<2)) >> 2 - cmp r0, #0 // r0 (SPSEL bit) ≟ 0 + cmp r0, #0 // r0 (SPSEL bit) =≟ 0 bne 100f // to_kernel // if SPSEL == 1, jump to to_kernel // If we get here, then this is a context switch from the kernel to the @@ -97,7 +97,7 @@ core::arch::global_asm!( isb // The link register is set to the `EXC_RETURN` value on exception entry. To - // ensure we execute using the application stack we set the SPSEL bit to 1 + // ensure we execute using the process stack we set the SPSEL bit to 1 // to use the alternate (process) stack. mov r0, #1 // r0 = 1 bfi lr, r0, #2, #1 // LR = LR | (0x1<<2)