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 4370487fd689d4a3ddbeada9cbabc9cde287de4f
Author: wangming9 <[email protected]>
AuthorDate: Tue Jul 4 20:39:08 2023 +0800

    arch/armv7-m: Add CONTROL register to xcptcontext.
    
    To simplify the interrupt handling in protected mode.
    
    Signed-off-by: wangming9 <[email protected]>
---
 arch/arm/include/armv7-m/irq.h               |  5 ++--
 arch/arm/src/armv7-m/arm_exception.S         | 27 ++++----------------
 arch/arm/src/armv7-m/arm_initialstate.c      |  2 ++
 arch/arm/src/armv7-m/arm_schedulesigaction.c |  5 ++++
 arch/arm/src/armv7-m/arm_svcall.c            | 37 +++++++++++++++++++---------
 5 files changed, 40 insertions(+), 36 deletions(-)

diff --git a/arch/arm/include/armv7-m/irq.h b/arch/arm/include/armv7-m/irq.h
index 626072c47d..f77ef08016 100644
--- a/arch/arm/include/armv7-m/irq.h
+++ b/arch/arm/include/armv7-m/irq.h
@@ -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
 
diff --git a/arch/arm/src/armv7-m/arm_exception.S 
b/arch/arm/src/armv7-m/arm_exception.S
index cc4b59ad8a..6716a9d7f8 100644
--- a/arch/arm/src/armv7-m/arm_exception.S
+++ b/arch/arm/src/armv7-m/arm_exception.S
@@ -142,6 +142,7 @@
 exception_common:
 
        mrs             r0, ipsr                                /* R0=exception 
number */
+       mrs             r12, control                            /* R12=control 
*/
 
        /* Complete the context save */
 
@@ -182,7 +183,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:
         *
@@ -227,7 +228,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 ? */
 
@@ -240,30 +241,10 @@ 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 */
-       msr             psp, r0                                 /* R0=The 
process stack pointer */
-       b               3f
-2:
-       bic             r2, r2, #1                              /* Privileged 
mode */
-       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 */
        ite             eq                                      /* Next two 
instructions conditional */
        msreq           msp, r0                                 /* R0=The main 
stack pointer */
        msrne           psp, r0                                 /* R0=The 
process stack pointer */
-#endif
 
        /* Restore the interrupt state */
 
@@ -273,6 +254,8 @@ exception_common:
        msr             primask, r3                             /* Restore 
interrupts */
 #endif
 
+       msr             control, r12                            /* Restore 
control */
+
        /* Always return with R14 containing the special value that will: (1)
         * return to thread mode, and (2) select the correct stack.
         */
diff --git a/arch/arm/src/armv7-m/arm_initialstate.c 
b/arch/arm/src/armv7-m/arm_initialstate.c
index 85ec6fadb4..c86390abdc 100644
--- a/arch/arm/src/armv7-m/arm_initialstate.c
+++ b/arch/arm/src/armv7-m/arm_initialstate.c
@@ -144,6 +144,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]   = 0; /* REVISIT: Initial FPSCR should be configurable 
*/
 #endif /* CONFIG_ARCH_FPU */
diff --git a/arch/arm/src/armv7-m/arm_schedulesigaction.c 
b/arch/arm/src/armv7-m/arm_schedulesigaction.c
index 70f90e1be5..127e66fe65 100644
--- a/arch/arm/src/armv7-m/arm_schedulesigaction.c
+++ b/arch/arm/src/armv7-m/arm_schedulesigaction.c
@@ -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]    = ARMV7M_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]    = ARMV7M_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]    = ARMV7M_XPSR_T;
 #ifdef CONFIG_BUILD_PROTECTED
                   CURRENT_REGS[REG_LR]      = EXC_RETURN_PRIVTHR;
+                  CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
 #endif
                 }
 
@@ -427,6 +431,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t 
sigdeliver)
           tcb->xcp.regs[REG_XPSR]    = ARMV7M_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/armv7-m/arm_svcall.c 
b/arch/arm/src/armv7-m/arm_svcall.c
index d9f5c0aa00..336a64dfb7 100644
--- a/arch/arm/src/armv7-m/arm_svcall.c
+++ b/arch/arm/src/armv7-m/arm_svcall.c
@@ -146,12 +146,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
 
@@ -277,6 +273,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,10 @@ 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 +430,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 +470,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

Reply via email to