You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/08/07 12:43:24 UTC
[nuttx] 04/09: arch/armv6-m: Add CONTROL register to xcptcontext.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit eba9c61caddfd1a7a731ef75bfca16b134a6812f
Author: wangming9 <wa...@xiaomi.com>
AuthorDate: Wed Jul 5 20:18:28 2023 +0800
arch/armv6-m: Add CONTROL register to xcptcontext.
To simplify the interrupt handling in protected mode.
Signed-off-by: wangming9 <wa...@xiaomi.com>
---
arch/arm/include/armv6-m/irq.h | 5 +++--
arch/arm/src/armv6-m/arm_exception.S | 12 +++++++-----
arch/arm/src/armv6-m/arm_initialstate.c | 2 ++
arch/arm/src/armv6-m/arm_schedulesigaction.c | 5 +++++
arch/arm/src/armv6-m/arm_svcall.c | 20 ++++++++++++++++++++
5 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/arch/arm/include/armv6-m/irq.h b/arch/arm/include/armv6-m/irq.h
index b7ea799fc4..e900b6b1c5 100644
--- a/arch/arm/include/armv6-m/irq.h
+++ b/arch/arm/include/armv6-m/irq.h
@@ -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 */
diff --git a/arch/arm/src/armv6-m/arm_exception.S b/arch/arm/src/armv6-m/arm_exception.S
index 595198b698..a2c6ce854b 100644
--- a/arch/arm/src/armv6-m/arm_exception.S
+++ b/arch/arm/src/armv6-m/arm_exception.S
@@ -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.
diff --git a/arch/arm/src/armv6-m/arm_initialstate.c b/arch/arm/src/armv6-m/arm_initialstate.c
index c7639d26ed..fa730969c7 100644
--- a/arch/arm/src/armv6-m/arm_initialstate.c
+++ b/arch/arm/src/armv6-m/arm_initialstate.c
@@ -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
diff --git a/arch/arm/src/armv6-m/arm_schedulesigaction.c b/arch/arm/src/armv6-m/arm_schedulesigaction.c
index a9c25d883d..f03b9e535b 100644
--- a/arch/arm/src/armv6-m/arm_schedulesigaction.c
+++ b/arch/arm/src/armv6-m/arm_schedulesigaction.c
@@ -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
}
}
diff --git a/arch/arm/src/armv6-m/arm_svcall.c b/arch/arm/src/armv6-m/arm_svcall.c
index b9f96459fb..231c796301 100644
--- a/arch/arm/src/armv6-m/arm_svcall.c
+++ b/arch/arm/src/armv6-m/arm_svcall.c
@@ -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;