From 4370487fd689d4a3ddbeada9cbabc9cde287de4f Mon Sep 17 00:00:00 2001 From: wangming9 Date: Tue, 4 Jul 2023 20:39:08 +0800 Subject: [PATCH] arch/armv7-m: Add CONTROL register to xcptcontext. To simplify the interrupt handling in protected mode. Signed-off-by: wangming9 --- arch/arm/include/armv7-m/irq.h | 5 +-- arch/arm/src/armv7-m/arm_exception.S | 27 +++----------- arch/arm/src/armv7-m/arm_initialstate.c | 2 ++ arch/arm/src/armv7-m/arm_schedulesigaction.c | 5 +++ arch/arm/src/armv7-m/arm_svcall.c | 37 +++++++++++++------- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/arch/arm/include/armv7-m/irq.h b/arch/arm/include/armv7-m/irq.h index 626072c47d..f77ef08016 100644 --- a/arch/arm/include/armv7-m/irq.h +++ b/arch/arm/include/armv7-m/irq.h @@ -72,8 +72,9 @@ #define REG_R9 (7) /* R9 */ #define REG_R10 (8) /* R10 */ #define REG_R11 (9) /* R11 */ -#define REG_EXC_RETURN (10) /* EXC_RETURN */ -#define SW_INT_REGS (11) +#define REG_CONTROL (10) /* CONTROL */ +#define REG_EXC_RETURN (11) /* EXC_RETURN */ +#define SW_INT_REGS (12) #ifdef CONFIG_ARCH_FPU diff --git a/arch/arm/src/armv7-m/arm_exception.S b/arch/arm/src/armv7-m/arm_exception.S index cc4b59ad8a..6716a9d7f8 100644 --- a/arch/arm/src/armv7-m/arm_exception.S +++ b/arch/arm/src/armv7-m/arm_exception.S @@ -142,6 +142,7 @@ exception_common: mrs r0, ipsr /* R0=exception number */ + mrs r12, control /* R12=control */ /* Complete the context save */ @@ -182,7 +183,7 @@ exception_common: subne sp, #(4*SW_FPU_REGS) #endif - stmdb sp!, {r2-r11,r14} /* Save the remaining registers plus the SP/PRIMASK values */ + stmdb sp!, {r2-r12,r14} /* Save the remaining registers plus the SP/PRIMASK values */ /* There are two arguments to arm_doirq: * @@ -227,7 +228,7 @@ exception_common: * array to use for the interrupt return. */ - ldmia r0!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ + ldmia r0!, {r2-r12,r14} /* Recover R4-R12, r14 + 2 temp values */ #ifdef CONFIG_ARCH_FPU /* Switched-in task including volatile FP registers ? */ @@ -240,30 +241,10 @@ exception_common: /* The EXC_RETURN value tells us whether we are returning on the MSP or PSP */ -#ifdef CONFIG_BUILD_PROTECTED - /* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1 - * (handler mode) if the stack is on the MSP. It can only be on the PSP if - * EXC_RETURN is 0xfffffffd (unprivileged thread) - */ - - mrs r2, control /* R2=Contents of the control register */ - tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */ - beq 2f /* Branch if privileged */ - - orr r2, r2, #1 /* Unprivileged mode */ - msr psp, r0 /* R0=The process stack pointer */ - b 3f -2: - bic r2, r2, #1 /* Privileged mode */ - msr msp, r0 /* R0=The main stack pointer */ -3: - msr control, r2 /* Save the updated control register */ -#else tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */ ite eq /* Next two instructions conditional */ msreq msp, r0 /* R0=The main stack pointer */ msrne psp, r0 /* R0=The process stack pointer */ -#endif /* Restore the interrupt state */ @@ -273,6 +254,8 @@ exception_common: msr primask, r3 /* Restore interrupts */ #endif + msr control, r12 /* Restore control */ + /* Always return with R14 containing the special value that will: (1) * return to thread mode, and (2) select the correct stack. */ diff --git a/arch/arm/src/armv7-m/arm_initialstate.c b/arch/arm/src/armv7-m/arm_initialstate.c index 85ec6fadb4..c86390abdc 100644 --- a/arch/arm/src/armv7-m/arm_initialstate.c +++ b/arch/arm/src/armv7-m/arm_initialstate.c @@ -144,6 +144,8 @@ void up_initial_state(struct tcb_s *tcb) xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + xcp->regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; + #ifdef CONFIG_ARCH_FPU xcp->regs[REG_FPSCR] = 0; /* REVISIT: Initial FPSCR should be configurable */ #endif /* CONFIG_ARCH_FPU */ diff --git a/arch/arm/src/armv7-m/arm_schedulesigaction.c b/arch/arm/src/armv7-m/arm_schedulesigaction.c index 70f90e1be5..127e66fe65 100644 --- a/arch/arm/src/armv7-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-m/arm_schedulesigaction.c @@ -162,6 +162,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) #ifdef CONFIG_BUILD_PROTECTED CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR; CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } } @@ -209,6 +210,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR; + tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } } @@ -319,6 +321,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR; + tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } else @@ -365,6 +368,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) CURRENT_REGS[REG_XPSR] = ARMV7M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR; + CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } @@ -427,6 +431,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR; + tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; #endif } } diff --git a/arch/arm/src/armv7-m/arm_svcall.c b/arch/arm/src/armv7-m/arm_svcall.c index d9f5c0aa00..336a64dfb7 100644 --- a/arch/arm/src/armv7-m/arm_svcall.c +++ b/arch/arm/src/armv7-m/arm_svcall.c @@ -146,12 +146,8 @@ int arm_svcall(int irq, void *context, void *arg) svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11], regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]); -# ifdef REG_EXC_RETURN - svcinfo(" PSR: %08x EXC_RETURN: %08x\n", - regs[REG_XPSR], regs[REG_EXC_RETURN]); -# else - svcinfo(" PSR: %08x\n", regs[REG_XPSR]); -# endif + svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n", + regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]); } #endif @@ -277,6 +273,10 @@ int arm_svcall(int irq, void *context, void *arg) regs[REG_PC] = (uint32_t)USERSPACE->task_startup & ~1; regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + /* Return unprivileged mode */ + + regs[REG_CONTROL] = getcontrol() | CONTROL_NPRIV; + /* Change the parameter ordering to match the expectation of struct * userpace_s task_startup: */ @@ -310,6 +310,10 @@ int arm_svcall(int irq, void *context, void *arg) regs[REG_PC] = (uint32_t)regs[REG_R1] & ~1; /* startup */ regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + /* Return unprivileged mode */ + + regs[REG_CONTROL] = getcontrol() | CONTROL_NPRIV; + /* Change the parameter ordering to match the expectation of the * user space pthread_startup: */ @@ -351,6 +355,10 @@ int arm_svcall(int irq, void *context, void *arg) regs[REG_PC] = (uint32_t)USERSPACE->signal_handler & ~1; regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + /* Return unprivileged mode */ + + regs[REG_CONTROL] = getcontrol() | CONTROL_NPRIV; + /* Change the parameter ordering to match the expectation of struct * userpace_s signal_handler. */ @@ -383,6 +391,10 @@ int arm_svcall(int irq, void *context, void *arg) regs[REG_PC] = rtcb->xcp.sigreturn & ~1; regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + + /* Return privileged mode */ + + regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; rtcb->xcp.sigreturn = 0; } break; @@ -418,6 +430,10 @@ int arm_svcall(int irq, void *context, void *arg) regs[REG_PC] = (uint32_t)dispatch_syscall & ~1; regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + /* Return privileged mode */ + + regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; + /* Offset R0 to account for the reserved values */ regs[REG_R0] -= CONFIG_SYS_RESERVED; @@ -454,12 +470,9 @@ int arm_svcall(int irq, void *context, void *arg) CURRENT_REGS[REG_R10], CURRENT_REGS[REG_R11], CURRENT_REGS[REG_R12], CURRENT_REGS[REG_R13], CURRENT_REGS[REG_R14], CURRENT_REGS[REG_R15]); -# ifdef REG_EXC_RETURN - svcinfo(" PSR: %08x EXC_RETURN: %08x\n", - CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_EXC_RETURN]); -# else - svcinfo(" PSR: %08x\n", CURRENT_REGS[REG_XPSR]); -# endif + svcinfo(" PSR: %08x EXC_RETURN: %08x, CONTROL: %08x\n", + CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_EXC_RETURN], + CURRENT_REGS[REG_CONTROL]); } # ifdef CONFIG_DEBUG_SVCALL else