arch/armv6-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-05 20:18:28 +08:00 committed by Xiang Xiao
parent a4b6b158ce
commit eba9c61cad
5 changed files with 37 additions and 7 deletions

View File

@ -69,8 +69,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_XCPT_REGS (11)
#define REG_CONTROL (10) /* CONTROL */
#define REG_EXC_RETURN (11) /* EXC_RETURN */
#define SW_XCPT_REGS (12)
/* The total number of registers saved by software */

View File

@ -141,14 +141,15 @@ exception_common:
mov r0, r1 /* Copy the context array pointer */
stmia r0!, {r2-r7} /* Save the SP, PRIMASK, and R4-R7 in the context array */
/* Save R8-R11 and the EXEC_RETURN value in the context array */
/* Save R8-R11 control and the EXEC_RETURN value in the context array */
mov r2, r8 /* Copy high registers to low */
mov r3, r9
mov r4, r10
mov r5, r11
mov r6, r14
stmia r0!, {r2-r6} /* Save the high registers r8-r11 and r14 */
mrs r6, control /* R6=control */
mov r7, r14
stmia r0!, {r2-r7} /* Save the high registers r8-r11 control and r14 */
/* Get the exception number in R0=IRQ, R1=register save area on stack */
@ -188,12 +189,13 @@ exception_common:
movs r2, #(4*REG_R8) /* R2=Offset to R8 storage */
adds r1, r0, r2 /* R1=Address of R8 storage */
ldmia r1!, {r2-r6} /* Recover R8-R11 and R14 (5 registers)*/
ldmia r1!, {r2-r7} /* Recover R8-R11 control and R14 (6 registers)*/
mov r8, r2 /* Move to position in high registers */
mov r9, r3
mov r10, r4
mov r11, r5
mov r14, r6 /* EXEC_RETURN */
msr control, r6
mov r14, r7 /* EXEC_RETURN */
/* Recover SP (R2), PRIMASK (R3), and R4-R7. Determine the value of
* the stack pointer as it was on entry to the exception handler.

View File

@ -137,6 +137,8 @@ void up_initial_state(struct tcb_s *tcb)
xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
xcp->regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
/* Enable or disable interrupts, based on user configuration */
#ifdef CONFIG_SUPPRESS_INTERRUPTS

View File

@ -157,6 +157,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
}
}
@ -200,6 +201,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}
}
@ -306,6 +308,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}
else
@ -348,6 +351,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
CURRENT_REGS[REG_XPSR] = ARMV6M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}
@ -406,6 +410,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_XPSR] = ARMV6M_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

@ -264,6 +264,10 @@ int arm_svcall(int irq, void *context, void *arg)
regs[REG_PC] = (uint32_t)USERSPACE->task_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 struct
* userpace_s task_startup:
*/
@ -297,6 +301,10 @@ int arm_svcall(int irq, void *context, void *arg)
regs[REG_PC] = (uint32_t)regs[REG_R1]; /* 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:
*/
@ -338,6 +346,10 @@ int arm_svcall(int irq, void *context, void *arg)
regs[REG_PC] = (uint32_t)USERSPACE->signal_handler;
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.
*/
@ -370,6 +382,10 @@ int arm_svcall(int irq, void *context, void *arg)
regs[REG_PC] = rtcb->xcp.sigreturn;
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
/* Return privileged mode */
regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
rtcb->xcp.sigreturn = 0;
}
break;
@ -405,6 +421,10 @@ int arm_svcall(int irq, void *context, void *arg)
regs[REG_PC] = (uint32_t)dispatch_syscall;
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;