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;