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 <[email protected]>
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 <[email protected]>
---
 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;

Reply via email to