This is an automated email from the ASF dual-hosted git repository.

ligd pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 948ac9b4cc4407120b671c5237dd7ff64b37e94e
Author: hujun5 <[email protected]>
AuthorDate: Tue Jul 23 21:11:45 2024 +0800

    arm64: add up_this_task and up_change_task macro impl
    
    Signed-off-by: hujun5 <[email protected]>
---
 arch/arm64/include/arch.h                  |  6 ++++-
 arch/arm64/include/irq.h                   | 43 ++++++------------------------
 arch/arm64/src/common/arm64_cpustart.c     |  6 ++++-
 arch/arm64/src/common/arm64_doirq.c        | 15 +++++------
 arch/arm64/src/common/arm64_fatal.c        | 15 ++++++-----
 arch/arm64/src/common/arm64_registerdump.c |  1 +
 6 files changed, 34 insertions(+), 52 deletions(-)

diff --git a/arch/arm64/include/arch.h b/arch/arm64/include/arch.h
index 157169cea9..2e39948a04 100644
--- a/arch/arm64/include/arch.h
+++ b/arch/arm64/include/arch.h
@@ -55,7 +55,7 @@
 
 /****************************************************************************
  * Name:
- *   read_/write_/zero_ sysreg
+ *   read_/write_/zero_/modify_ sysreg
  *
  * Description:
  *
@@ -84,6 +84,10 @@
                       ::: "memory");                \
   })
 
+#define modify_sysreg(v,m,a)                        \
+  write_sysreg((read_sysreg(a) & ~(m)) |            \
+               ((uintptr_t)(v) & (m)), a)
+
 /****************************************************************************
  * Inline functions
  ****************************************************************************/
diff --git a/arch/arm64/include/irq.h b/arch/arm64/include/irq.h
index dbb8a11a20..aad83b14e9 100644
--- a/arch/arm64/include/irq.h
+++ b/arch/arm64/include/irq.h
@@ -387,31 +387,17 @@ static inline void up_irq_restore(irqstate_t flags)
 #endif /* CONFIG_ARCH_HAVE_MULTICPU */
 
 /****************************************************************************
- * Name:
- *   up_current_regs/up_set_current_regs
- *
- * Description:
- *   We use the following code to manipulate the tpidr_el1 register,
- *   which exists uniquely for each CPU and is primarily designed to store
- *   current thread information. Currently, we leverage it to store interrupt
- *   information, with plans to further optimize its use for storing both
- *   thread and interrupt information in the future.
+ * Schedule acceleration macros
  *
+ * The lsbit of tpidr_el1 stores information about whether the current
+ * execution is in an interrupt context, where 1 indicates being in an
+ * interrupt context and 0 indicates being in a thread context.
  ****************************************************************************/
 
-noinstrument_function
-static inline_function uint64_t *up_current_regs(void)
-{
-  uint64_t *regs;
-  __asm__ volatile ("mrs %0, " "tpidr_el1" : "=r" (regs));
-  return regs;
-}
-
-noinstrument_function
-static inline_function void up_set_current_regs(uint64_t *regs)
-{
-  __asm__ volatile ("msr " "tpidr_el1" ", %0" : : "r" (regs));
-}
+#define up_current_regs()      (this_task()->xcp.regs)
+#define up_this_task()         ((struct tcb_s *)(read_sysreg(tpidr_el1) & 
~1ul))
+#define up_update_task(t)      modify_sysreg(t, ~1ul, tpidr_el1)
+#define up_interrupt_context() (read_sysreg(tpidr_el1) & 1)
 
 #define up_switch_context(tcb, rtcb)                              \
   do {                                                            \
@@ -422,19 +408,6 @@ static inline_function void up_set_current_regs(uint64_t 
*regs)
       }                                                           \
   } while (0)
 
-/****************************************************************************
- * Name: up_interrupt_context
- *
- * Description: Return true is we are currently executing in
- * the interrupt handler context.
- *
- ****************************************************************************/
-
-static inline bool up_interrupt_context(void)
-{
-  return up_current_regs() != NULL;
-}
-
 /****************************************************************************
  * Name: up_getusrpc
  ****************************************************************************/
diff --git a/arch/arm64/src/common/arm64_cpustart.c 
b/arch/arm64/src/common/arm64_cpustart.c
index 46f9b72151..fcc9a41b18 100644
--- a/arch/arm64/src/common/arm64_cpustart.c
+++ b/arch/arm64/src/common/arm64_cpustart.c
@@ -113,7 +113,11 @@ static inline void local_delay(void)
 
 static void arm64_smp_init_top(void)
 {
-  struct tcb_s *tcb = this_task();
+  struct tcb_s *tcb = current_task(this_cpu());
+
+  /* Init idle task to percpu reg */
+
+  up_update_task(tcb);
 
 #ifndef CONFIG_SUPPRESS_INTERRUPTS
   /* And finally, enable interrupts */
diff --git a/arch/arm64/src/common/arm64_doirq.c 
b/arch/arm64/src/common/arm64_doirq.c
index 9806c2c41c..499b2ab3e4 100644
--- a/arch/arm64/src/common/arm64_doirq.c
+++ b/arch/arm64/src/common/arm64_doirq.c
@@ -61,13 +61,12 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
 
   /* Nested interrupts are not supported */
 
-  DEBUGASSERT(up_current_regs() == NULL);
+  DEBUGASSERT(!up_interrupt_context());
 
-  /* Current regs non-zero indicates that we are processing an interrupt;
-   * current_regs is also used to manage interrupt level context switches.
-   */
+  /* Set irq flag */
+
+  write_sysreg((uintptr_t)tcb | 1, tpidr_el1);
 
-  up_set_current_regs(regs);
   tcb->xcp.regs = regs;
 
   /* Deliver the IRQ */
@@ -110,11 +109,9 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
       regs = tcb->xcp.regs;
     }
 
-  /* Set current_regs to NULL to indicate that we are no longer in an
-   * interrupt handler.
-   */
+  /* Clear irq flag */
 
-  up_set_current_regs(NULL);
+  write_sysreg((uintptr_t)tcb & ~1ul, tpidr_el1);
 
   return regs;
 }
diff --git a/arch/arm64/src/common/arm64_fatal.c 
b/arch/arm64/src/common/arm64_fatal.c
index 997fe7f675..3e779ba35a 100644
--- a/arch/arm64/src/common/arm64_fatal.c
+++ b/arch/arm64/src/common/arm64_fatal.c
@@ -541,13 +541,18 @@ static int arm64_exception_handler(uint64_t *regs)
 
 void arm64_fatal_handler(uint64_t *regs)
 {
+  struct tcb_s *tcb = this_task();
   int ret;
 
   /* Nested exception are not supported */
 
-  DEBUGASSERT(up_current_regs() == NULL);
+  DEBUGASSERT(!up_interrupt_context());
 
-  up_set_current_regs((uint64_t *)regs);
+  tcb->xcp.regs = (uint64_t *)regs;
+
+  /* Set irq flag */
+
+  write_sysreg((uintptr_t)tcb | 1, tpidr_el1);
 
   ret = arm64_exception_handler(regs);
 
@@ -558,11 +563,9 @@ void arm64_fatal_handler(uint64_t *regs)
       PANIC_WITH_REGS("panic", regs);
     }
 
-  /* Set CURRENT_REGS to NULL to indicate that we are no longer in an
-   * Exception handler.
-   */
+  /* Clear irq flag */
 
-  up_set_current_regs(NULL);
+  write_sysreg((uintptr_t)tcb & ~1ul, tpidr_el1);
 }
 
 void arm64_register_debug_hook(int nr, fatal_handle_func_t fn)
diff --git a/arch/arm64/src/common/arm64_registerdump.c 
b/arch/arm64/src/common/arm64_registerdump.c
index 2b0be8d908..d19dbd704e 100644
--- a/arch/arm64/src/common/arm64_registerdump.c
+++ b/arch/arm64/src/common/arm64_registerdump.c
@@ -31,6 +31,7 @@
 #include <nuttx/arch.h>
 #include <nuttx/irq.h>
 
+#include "sched/sched.h"
 #include "arm64_arch.h"
 #include "arm64_internal.h"
 #include "chip.h"

Reply via email to