diff --git a/arch/arm/core/swap_helper.S b/arch/arm/core/swap_helper.S index 7e397396364..2847afebeb1 100644 --- a/arch/arm/core/swap_helper.S +++ b/arch/arm/core/swap_helper.S @@ -41,6 +41,8 @@ GDATA(_kernel) * already been taken. In other words, when z_arm_pendsv() runs, we *know* we * have to swap *something*. * + * For Cortex-M, z_arm_pendsv() is invoked with no arguments. + * * For Cortex-R, PendSV exception is not supported by the architecture and this * function is directly called either by _IntExit in case of preemption, or * z_arm_svc in case of cooperative switching. @@ -163,7 +165,9 @@ out_fp_endif: str v3, [v4, #0] #endif - /* Restore previous interrupt disable state (irq_lock key) */ + /* Restore previous interrupt disable state (irq_lock key) + * (We clear the arch.basepri field after restoring state) + */ #if (defined(CONFIG_CPU_CORTEX_M0PLUS) || defined(CONFIG_CPU_CORTEX_M0)) && \ _thread_offset_to_basepri > 124 /* Doing it this way since the offset to thread->arch.basepri can in @@ -410,13 +414,21 @@ _oops: * @return N/A */ SECTION_FUNC(TEXT, z_arm_svc) + /* Use EXC_RETURN state to find out if stack frame is on the + * MSP or PSP + */ tst lr, #0x4 /* did we come from thread mode ? */ ite eq /* if zero (equal), came from handler mode */ mrseq r0, MSP /* handler mode, stack frame is on MSP */ mrsne r0, PSP /* thread mode, stack frame is on PSP */ + + /* Figure out what SVC call number was invoked */ + ldr r1, [r0, #24] /* grab address of PC from stack frame */ - /* SVC is a two-byte instruction, point to it and read encoding */ + /* SVC is a two-byte instruction, point to it and read the + * SVC number (lower byte of SCV instruction) + */ ldrh r1, [r1, #-2] /* @@ -425,8 +437,6 @@ SECTION_FUNC(TEXT, z_arm_svc) * 1: irq_offload (if configured) * 2: kernel panic or oops (software generated fatal exception) * 3: System call (if user mode supported) - * Planned implementation of system calls for memory protection will - * expand this case. */ ands r1, #0xff #if defined(CONFIG_USERSPACE) @@ -442,7 +452,7 @@ SECTION_FUNC(TEXT, z_arm_svc) tst r2, #0x1 bne _oops -#endif +#endif /* CONFIG_USERSPACE */ cmp r1, #2 beq _oops diff --git a/arch/arm/core/userspace.S b/arch/arm/core/userspace.S index 986333d7fce..518404ea832 100644 --- a/arch/arm/core/userspace.S +++ b/arch/arm/core/userspace.S @@ -33,6 +33,9 @@ GDATA(_k_syscall_table) * The conversion is one way, and threads which transition to user mode do * not transition back later, unless they are doing system calls. * + * The function is invoked as: + * z_arm_userspace_enter(user_entry, p1, p2, p3, + * stack_info.start, stack_info.size); */ SECTION_FUNC(TEXT,z_arm_userspace_enter) /* move user_entry to lr */ @@ -44,14 +47,20 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter) msr PSPLIM, r0 #endif - /* set stack to privileged stack */ + /* prepare to set stack to privileged stack */ ldr r0, =_kernel ldr r0, [r0, #_kernel_offset_to_current] ldr r0, [r0, #_thread_offset_to_priv_stack_start] /* priv stack ptr */ ldr ip, =CONFIG_PRIVILEGED_STACK_SIZE add r0, r0, ip + /* store current stack pointer to ip + * the current stack pointer is needed to retrieve + * stack_info.start and stack_info.size + */ mov ip, sp + + /* set stack to privileged stack */ msr PSP, r0 #if defined(CONFIG_BUILTIN_STACK_GUARD)