arch/armv8-m: Add CONTROL register to xcptcontext.

To simplify the interrupt handling in protected mode.

Signed-off-by: wangming9 <wangming9@xiaomi.com>
This commit is contained in:
wangming9 2023-07-06 21:01:54 +08:00 committed by Xiang Xiao
parent 2684642a7a
commit f8aaed780a
5 changed files with 41 additions and 42 deletions

View File

@ -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

View File

@ -146,6 +146,7 @@
exception_common:
mrs r0, ipsr /* R0=exception number */
mrs r12, control /* R12=control */
/* Complete the context save */
@ -198,7 +199,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:
*
@ -243,7 +244,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 ? */
@ -260,31 +261,6 @@ 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 */
#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
msr psplim, r1
#endif
msr psp, r0 /* R0=The process stack pointer */
b 3f
2:
bic r2, r2, #1 /* Privileged mode */
#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
msr msplim, r1
#endif
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 */
#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
itete eq
@ -295,7 +271,6 @@ exception_common:
#endif
msreq msp, r0 /* R0=The main stack pointer */
msrne psp, r0 /* R0=The process stack pointer */
#endif
/* Restore the interrupt state */
@ -305,6 +280,8 @@ exception_common:
msr primask, r3 /* Restore interrupts */
#endif
msr control, r12
/* Always return with R14 containing the special value that will: (1)
* return to thread mode, and (2) select the correct stack.
*/

View File

@ -150,6 +150,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] |= ARMV8M_FPSCR_LTPSIZE_NONE;
#endif /* CONFIG_ARCH_FPU */

View File

@ -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] = ARMV8M_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] = ARMV8M_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] = ARMV8M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}
@ -431,6 +435,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}
}

View File

@ -145,12 +145,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
@ -276,6 +272,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,11 @@ 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 +431,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 +471,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