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 5cdfa6fec46aea89a2c7bb613ad23204311ddcc8
Author: wangming9 <[email protected]>
AuthorDate: Sat Jul 8 19:37:54 2023 +0800

    arch/armv8-m: Supports interrupt nesting
    
    1、The process stack supports interrupt nesting, Execute in MSP;
    2、The interrupt stack supports interrupt nesting;
       The thread mode use PSP, and the handle mode use MSP;
    3、Adjust arm_doirq、exception_common implementation to meet interrupt nesting
    4、Adjust the conditions for returning MSP and PSP;
    5、remove setintstack;
    
    Signed-off-by: wangming9 <[email protected]>
---
 arch/arm/src/armv8-m/arm_doirq.c             | 17 ++-----
 arch/arm/src/armv8-m/arm_exception.S         | 69 +++++++++-------------------
 arch/arm/src/armv8-m/arm_initialstate.c      | 65 +++++++++++++++++++++++++-
 arch/arm/src/armv8-m/arm_schedulesigaction.c | 12 ++---
 arch/arm/src/armv8-m/arm_svcall.c            | 10 ++--
 arch/arm/src/armv8-m/exc_return.h            | 40 ++++++++--------
 6 files changed, 119 insertions(+), 94 deletions(-)

diff --git a/arch/arm/src/armv8-m/arm_doirq.c b/arch/arm/src/armv8-m/arm_doirq.c
index d4e9b29d14..5c5e86a150 100644
--- a/arch/arm/src/armv8-m/arm_doirq.c
+++ b/arch/arm/src/armv8-m/arm_doirq.c
@@ -47,20 +47,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
   PANIC();
 #else
 
-  /* Nested interrupts are not supported in this implementation.  If you
-   * want to implement nested interrupts, you would have to (1) change the
-   * way that CURRENT_REGS is handled and (2) the design associated with
-   * CONFIG_ARCH_INTERRUPTSTACK.
-   */
-
-  /* Current regs non-zero indicates that we are processing an interrupt;
-   * CURRENT_REGS is also used to manage interrupt level context switches.
-   */
-
-  if (CURRENT_REGS == NULL)
+  if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
     {
       CURRENT_REGS = regs;
-      regs         = NULL;
     }
 
   /* Acknowledge the interrupt */
@@ -69,7 +58,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   /* Deliver the IRQ */
 
-  irq_dispatch(irq, (uint32_t *)CURRENT_REGS);
+  irq_dispatch(irq, regs);
 
   /* If a context switch occurred while processing the interrupt then
    * CURRENT_REGS may have change value.  If we return any value different
@@ -77,7 +66,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
    * switch occurred during interrupt processing.
    */
 
-  if (regs == NULL)
+  if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
     {
       /* Restore the cpu lock */
 
diff --git a/arch/arm/src/armv8-m/arm_exception.S 
b/arch/arm/src/armv8-m/arm_exception.S
index 4ff4ee7fc0..38b025d217 100644
--- a/arch/arm/src/armv8-m/arm_exception.S
+++ b/arch/arm/src/armv8-m/arm_exception.S
@@ -92,29 +92,6 @@
        .thumb
        .file           "arm_exception.S"
 
-/****************************************************************************
- * Macro Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: setintstack
- *
- * Description:
- *   Set the current stack pointer to the  "top" the interrupt stack.  Single 
CPU
- *   case.  Must be provided by MCU-specific logic in the SMP case.
- *
- ****************************************************************************/
-
-#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 7
-       .macro  setintstack, tmp1, tmp2
-#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
-       ldr             \tmp1, =g_intstackalloc
-       msr             msplim, \tmp1
-#endif
-       ldr             sp, =g_intstacktop
-       .endm
-#endif
-
 /****************************************************************************
  * .text
  ****************************************************************************/
@@ -145,31 +122,34 @@
        .type   exception_common, function
 exception_common:
 
-       mrs             r0, ipsr                                /* R0=exception 
number */
        mrs             r12, control                            /* R12=control 
*/
 
        /* Complete the context save */
 
        /* The EXC_RETURN value tells us whether the context is on the MSP or 
PSP */
 
-       tst             r14, #EXC_RETURN_PROCESS_STACK          /* nonzero if 
context on process stack */
+       tst             r14, #EXC_RETURN_PROCESS_STACK          /* Nonzero if 
context on process stack */
        beq             1f                                      /* Branch if 
context already on the MSP */
        mrs             r1, psp                                 /* R1=The 
process stack pointer (PSP) */
-       mov             sp, r1                                  /* Set the MSP 
to the PSP */
+       b               2f
 1:
-       mov             r2, sp                                  /* R2=Copy of 
the main/process stack pointer */
+       mrs             r1, msp                                 /* R1=The main 
stack pointer (MSP) */
+       sub             r2, r1, #SW_XCPT_SIZE                   /* Reserve the 
stack space */
+       msr             msp, r2
+2:
+       mov             r2, r1                                  /* R2=Copy of 
the main/process stack pointer */
        add             r2, #HW_XCPT_SIZE                       /* R2=MSP/PSP 
before the interrupt was taken */
                                                                /* (ignoring 
the xPSR[9] alignment bit) */
 #ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
        mov             r3, #0x0
 
        ittee           eq
-       mrseq           r1, msplim
+       mrseq           r0, msplim
        msreq           msplim, r3
-       mrsne           r1, psplim
+       mrsne           r0, psplim
        msrne           psplim, r3
 
-       stmdb           sp!, {r1}
+       stmdb           r1!, {r0}
 #endif
 
 #ifdef CONFIG_ARMV8M_USEBASEPRI
@@ -195,11 +175,11 @@ exception_common:
 
        tst             r14, #EXC_RETURN_STD_CONTEXT
        ite             eq
-       vstmdbeq        sp!, {s16-s31}                  /* Save the 
non-volatile FP context */
-       subne           sp, #(4*SW_FPU_REGS)
+       vstmdbeq        r1!, {s16-s31}                  /* Save the 
non-volatile FP context */
+       subne           r1, #(4*SW_FPU_REGS)
 #endif
 
-       stmdb           sp!, {r2-r12,r14}               /* Save the remaining 
registers plus the SP/PRIMASK values */
+       stmdb           r1!, {r2-r12,r14}               /* Save the remaining 
registers plus the SP/PRIMASK values */
 
        /* There are two arguments to arm_doirq:
         *
@@ -207,19 +187,12 @@ exception_common:
         *   R1 = The top of the stack points to the saved state
         */
 
-       mov             r1, sp
+       mrs             r0, ipsr
 
-#if CONFIG_ARCH_INTERRUPTSTACK > 7
-       /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will set the MSP to use
-        * a special special interrupt stack pointer.  The way that this is done
-        * here prohibits nested interrupts without some additional logic!
-        */
-
-       setintstack     r2, r3                  /* SP = IRQ stack top */
-#else
-       /* Otherwise, we will re-use the interrupted thread's stack.  That may
-        * mean using either MSP or PSP stack for interrupt level processing (in
-        * kernel mode).
+#if CONFIG_ARCH_INTERRUPTSTACK < 7
+       /* If CONFIG_ARCH_INTERRUPTSTACK is not defined, we will re-use the
+        * interrupted thread's stack.  That may mean using either MSP or PSP
+        * stack for interrupt level processing (in kernel mode).
         */
 
        /* If the interrupt stack is disabled, reserve xcpcontext to ensure
@@ -232,10 +205,12 @@ exception_common:
         *      ----------------------   <- SP
         * also the sp should be restore after arm_doirq()
         */
-
+       tst             r14, #EXC_RETURN_THREAD_MODE            /* Nonzero if 
context on thread mode */
+       beq             3f                                      /* Branch if 
context already on the handle mode */
        sub             r2, r1, #XCPTCONTEXT_SIZE               /* Reserve 
signal context */
        bic             r2, r2, #7                              /* Get the 
stack pointer with 8-byte alignment */
        mov             sp, r2                                  /* Instantiate 
the aligned stack */
+3:
 #endif
 
        bl              arm_doirq                               /* R0=IRQ, 
R1=register save (msp) */
@@ -261,7 +236,7 @@ exception_common:
        /* The EXC_RETURN value tells us whether we are returning on the MSP or 
PSP
         */
 
-       tst             r14, #EXC_RETURN_PROCESS_STACK          /* nonzero if 
context on process stack */
+       tst             r14, #EXC_RETURN_PROCESS_STACK          /* Nonzero if 
context on process stack */
 #ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
        itete           eq
        msreq           msplim, r1
diff --git a/arch/arm/src/armv8-m/arm_initialstate.c 
b/arch/arm/src/armv8-m/arm_initialstate.c
index 5ad73e3727..536f464b28 100644
--- a/arch/arm/src/armv8-m/arm_initialstate.c
+++ b/arch/arm/src/armv8-m/arm_initialstate.c
@@ -148,7 +148,7 @@ void up_initial_state(struct tcb_s *tcb)
    * mode before transferring control to the user task.
    */
 
-  xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
+  xcp->regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
 
   xcp->regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
 
@@ -174,3 +174,66 @@ void up_initial_state(struct tcb_s *tcb)
 
 #endif /* CONFIG_SUPPRESS_INTERRUPTS */
 }
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 7
+/****************************************************************************
+ * Name: arm_initialize_stack
+ *
+ * Description:
+ *   If interrupt stack is defined, the PSP and MSP need to be reinitialized.
+ *
+ ****************************************************************************/
+
+noinline_function void arm_initialize_stack(void)
+{
+#ifdef CONFIG_SMP
+  uint32_t stack = (uint32_t)arm_intstack_top();
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+  uint32_t stacklim = (uint32_t)arm_intstack_alloc();
+#endif
+#else
+  uint32_t stack = (uint32_t)g_intstacktop;
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+  uint32_t stacklim = (uint32_t)g_intstackalloc;
+#endif
+#endif
+  uint32_t temp = 0;
+
+  __asm__ __volatile__
+    (
+      "mrs %1, CONTROL\n"
+      "tst %1, #2\n"
+      "bne 1f\n"
+
+      /* Initialize PSP */
+
+      "mrs %1, msp\n"
+      "msr psp, %1\n"
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+      "mrs %1, msplim\n"
+      "msr psplim, %1\n"
+#endif
+
+      /* Select PSP */
+
+      "mrs %1, CONTROL\n"
+      "orr %1, #2\n"
+      "msr CONTROL, %1\n"
+      "isb sy\n"
+
+      /* Initialize MSP */
+
+      "1:\n"
+      "msr msp, %0\n"
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+      "msr msplim, %2\n"
+#endif
+      :
+#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
+      : "r" (stack), "r" (temp), "r" (stacklim)
+#else
+      : "r" (stack), "r" (temp)
+#endif
+      : "memory");
+}
+#endif
diff --git a/arch/arm/src/armv8-m/arm_schedulesigaction.c 
b/arch/arm/src/armv8-m/arm_schedulesigaction.c
index 0caf5ccbb7..5641b7b430 100644
--- a/arch/arm/src/armv8-m/arm_schedulesigaction.c
+++ b/arch/arm/src/armv8-m/arm_schedulesigaction.c
@@ -160,8 +160,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t 
sigdeliver)
 #endif
               CURRENT_REGS[REG_XPSR]       = ARMV8M_XPSR_T;
 #ifdef CONFIG_BUILD_PROTECTED
-              CURRENT_REGS[REG_LR]         = EXC_RETURN_PRIVTHR;
-              CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
+              CURRENT_REGS[REG_LR]         = EXC_RETURN_THREAD;
+              CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_THREAD;
               CURRENT_REGS[REG_CONTROL]    = getcontrol() & ~CONTROL_NPRIV;
 #endif
             }
@@ -209,7 +209,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t 
sigdeliver)
 #endif
           tcb->xcp.regs[REG_XPSR]    = ARMV8M_XPSR_T;
 #ifdef CONFIG_BUILD_PROTECTED
-          tcb->xcp.regs[REG_LR]      = EXC_RETURN_PRIVTHR;
+          tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
           tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
 #endif
         }
@@ -320,7 +320,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t 
sigdeliver)
 #endif
                   tcb->xcp.regs[REG_XPSR]    = ARMV8M_XPSR_T;
 #ifdef CONFIG_BUILD_PROTECTED
-                  tcb->xcp.regs[REG_LR]      = EXC_RETURN_PRIVTHR;
+                  tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
                   tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
 #endif
                 }
@@ -367,7 +367,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t 
sigdeliver)
 #endif
                   CURRENT_REGS[REG_XPSR]    = ARMV8M_XPSR_T;
 #ifdef CONFIG_BUILD_PROTECTED
-                  CURRENT_REGS[REG_LR]      = EXC_RETURN_PRIVTHR;
+                  CURRENT_REGS[REG_LR]      = EXC_RETURN_THREAD;
                   CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
 #endif
                 }
@@ -434,7 +434,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t 
sigdeliver)
 #endif
           tcb->xcp.regs[REG_XPSR]    = ARMV8M_XPSR_T;
 #ifdef CONFIG_BUILD_PROTECTED
-          tcb->xcp.regs[REG_LR]      = EXC_RETURN_PRIVTHR;
+          tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
           tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
 #endif
         }
diff --git a/arch/arm/src/armv8-m/arm_svcall.c 
b/arch/arm/src/armv8-m/arm_svcall.c
index f24ba53a69..1d384392e5 100644
--- a/arch/arm/src/armv8-m/arm_svcall.c
+++ b/arch/arm/src/armv8-m/arm_svcall.c
@@ -270,7 +270,7 @@ 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;
+          regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
 
           /* Return unprivileged mode */
 
@@ -308,7 +308,7 @@ 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;
+          regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
 
           /* Return unprivileged mode */
 
@@ -353,7 +353,7 @@ 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;
+          regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
 
           /* Return unprivileged mode */
 
@@ -390,7 +390,7 @@ int arm_svcall(int irq, void *context, void *arg)
           DEBUGASSERT(rtcb->xcp.sigreturn != 0);
 
           regs[REG_PC]         = rtcb->xcp.sigreturn & ~1;
-          regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
+          regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
 
           /* Return privileged mode */
 
@@ -429,7 +429,7 @@ int arm_svcall(int irq, void *context, void *arg)
           rtcb->xcp.nsyscalls  = index + 1;
 
           regs[REG_PC]         = (uint32_t)dispatch_syscall & ~1;
-          regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
+          regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
 
           /* Return privileged mode */
 
diff --git a/arch/arm/src/armv8-m/exc_return.h 
b/arch/arm/src/armv8-m/exc_return.h
index f415558a7c..d88c62355a 100644
--- a/arch/arm/src/armv8-m/exc_return.h
+++ b/arch/arm/src/armv8-m/exc_return.h
@@ -91,9 +91,9 @@
 /* EXC_RETURN_BASE: Bits that are always set in an EXC_RETURN value. */
 
 #ifdef CONFIG_ARCH_TRUSTZONE_NONSECURE
-#define EXC_RETURN_BASE          (0xffffff80)
+#  define EXC_RETURN_BASE        (0xffffff80)
 #else
-#define EXC_RETURN_BASE          (0xffffff80 | EXC_RETURN_EXC_SECURE | \
+#  define EXC_RETURN_BASE        (0xffffff80 | EXC_RETURN_EXC_SECURE | \
                                   EXC_RETURN_SECURE_STACK)
 #endif
 
@@ -104,35 +104,33 @@
 #define EXC_RETURN_HANDLER       (EXC_RETURN_BASE | EXC_RETURN_DEF_STACKING | \
                                   EXC_RETURN_STD_CONTEXT)
 
-/* EXC_RETURN_PRIVTHR: Return to privileged thread mode. Exception return
- * gets state from the main stack. Execution uses MSP after return.
- */
-
 #ifdef CONFIG_ARCH_FPU
-#  define EXC_RETURN_PRIVTHR     (EXC_RETURN_BASE | EXC_RETURN_THREAD_MODE | \
-                                  EXC_RETURN_DEF_STACKING)
+#  define EXC_RETURN_FPU         0
 #else
-#  define EXC_RETURN_PRIVTHR     (EXC_RETURN_BASE | EXC_RETURN_STD_CONTEXT | \
-                                  EXC_RETURN_THREAD_MODE | 
EXC_RETURN_DEF_STACKING)
+#  define EXC_RETURN_FPU         EXC_RETURN_STD_CONTEXT
 #endif
 
-/* EXC_RETURN_UNPRIVTHR: Return to unprivileged thread mode. Exception return
- * gets state from the process stack. Execution uses PSP after return.
+#if CONFIG_ARCH_INTERRUPTSTACK > 7
+#  define EXC_RETURN_STACK       EXC_RETURN_PROCESS_STACK
+#else
+#  define EXC_RETURN_STACK       0
+#endif
+
+/* EXC_RETURN_THREAD: Return to thread mode.
+ * If EXC_RETURN_STACK is 0, Return to thread mode.
+ * Execution uses MSP after return.
+ * If EXC_RETURN_STACK is EXC_RETURN_PROCESS_STACK, Return to
+ * thread mode. Execution uses PSP after return.
  */
 
-#ifdef CONFIG_ARCH_FPU
-#  define EXC_RETURN_UNPRIVTHR   (EXC_RETURN_BASE | EXC_RETURN_THREAD_MODE | \
-                                  EXC_RETURN_PROCESS_STACK | 
EXC_RETURN_DEF_STACKING)
-#else
-#  define EXC_RETURN_UNPRIVTHR   (EXC_RETURN_BASE | EXC_RETURN_STD_CONTEXT | \
-                                  EXC_RETURN_THREAD_MODE | 
EXC_RETURN_PROCESS_STACK | \
+#define EXC_RETURN_THREAD        (EXC_RETURN_BASE | EXC_RETURN_FPU | \
+                                  EXC_RETURN_THREAD_MODE | EXC_RETURN_STACK | \
                                   EXC_RETURN_DEF_STACKING)
-#endif
 
 #ifdef CONFIG_ARCH_FPU
-#define EXC_INTEGRITY_SIGNATURE  (0xfefa125a)
+#  define EXC_INTEGRITY_SIGNATURE (0xfefa125a)
 #else
-#define EXC_INTEGRITY_SIGNATURE  (0xfefa125b)
+#  define EXC_INTEGRITY_SIGNATURE (0xfefa125b)
 #endif
 
 /* FUNC_RETURN_EXC_SECURE: Exception Secure.  The security domain the

Reply via email to