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

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


The following commit(s) were added to refs/heads/master by this push:
     new 5cfe424bc3f arm64: cache TLS info pointer in TPIDR_EL0
5cfe424bc3f is described below

commit 5cfe424bc3f84c30b56cb3b67230462d1e1d140f
Author: hujun5 <[email protected]>
AuthorDate: Mon Oct 19 08:03:34 2026 +0800

    arm64: cache TLS info pointer in TPIDR_EL0
    
    Use TPIDR_EL0 to hold the current task's stack allocation pointer so that 
TLS information can be accessed without a global lookup. Initialize the 
register during primary and secondary CPU boot, and update it after interrupt 
and syscall context switches.
    
    Signed-off-by: hujun5 <[email protected]>
---
 arch/arm64/include/irq.h               |  1 +
 arch/arm64/src/common/arm64_boot.c     |  1 +
 arch/arm64/src/common/arm64_cpustart.c |  3 +++
 arch/arm64/src/common/arm64_doirq.c    |  4 ++++
 arch/arm64/src/common/arm64_head.S     |  6 ++++--
 arch/arm64/src/common/arm64_internal.h | 13 +++++++++++++
 arch/arm64/src/common/arm64_syscall.c  |  5 +++++
 7 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/irq.h b/arch/arm64/include/irq.h
index e38d46c5bd8..a3a14ad9f92 100644
--- a/arch/arm64/include/irq.h
+++ b/arch/arm64/include/irq.h
@@ -493,6 +493,7 @@ static inline_function void up_irq_restore(irqstate_t flags)
 #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_tls_info()          ((struct tls_info_s *)read_sysreg(tpidr_el0))
 
 #define up_switch_context(tcb, rtcb)                                      \
   do                                                                      \
diff --git a/arch/arm64/src/common/arm64_boot.c 
b/arch/arm64/src/common/arm64_boot.c
index 1dfacf867d4..cea799e62e8 100644
--- a/arch/arm64/src/common/arm64_boot.c
+++ b/arch/arm64/src/common/arm64_boot.c
@@ -238,6 +238,7 @@ void arm64_boot_el1_init(void)
 
 void arm64_boot_primary_c_routine(void)
 {
+  arm64_tp_boot(0);
   arm64_chip_boot();
   nx_start();
 }
diff --git a/arch/arm64/src/common/arm64_cpustart.c 
b/arch/arm64/src/common/arm64_cpustart.c
index 6a650ccd87b..d2ced2fa756 100644
--- a/arch/arm64/src/common/arm64_cpustart.c
+++ b/arch/arm64/src/common/arm64_cpustart.c
@@ -202,6 +202,7 @@ int up_cpu_start(int cpu)
 
 #ifdef CONFIG_SMP
   uint32_t *address = &g_smp_busy_wait_flag;
+
   *address = 1;
   up_flush_dcache((uintptr_t)address, (uintptr_t)address + sizeof(address));
 #endif
@@ -215,6 +216,8 @@ int up_cpu_start(int cpu)
 
 void arm64_boot_secondary_c_routine(void)
 {
+  arm64_tp_boot(this_cpu());
+
 #ifdef CONFIG_ARCH_HAVE_MPU
   arm64_mpu_init(false);
 #endif
diff --git a/arch/arm64/src/common/arm64_doirq.c 
b/arch/arm64/src/common/arm64_doirq.c
index c1fe07d1f04..3e93419473c 100644
--- a/arch/arm64/src/common/arm64_doirq.c
+++ b/arch/arm64/src/common/arm64_doirq.c
@@ -135,6 +135,10 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
 
       nxsched_switch_context(*running_task, tcb);
 
+      /* Update the TLS pointer */
+
+      write_sysreg(tcb->stack_alloc_ptr, tpidr_el0);
+
       /* Record the new "running" task when context switch occurred.
        * g_running_tasks[] is only used by assertion logic for reporting
        * crashes.
diff --git a/arch/arm64/src/common/arm64_head.S 
b/arch/arm64/src/common/arm64_head.S
index d219cf6c4dc..1c6c3752a5e 100644
--- a/arch/arm64/src/common/arm64_head.S
+++ b/arch/arm64/src/common/arm64_head.S
@@ -181,9 +181,10 @@ real_start:
     add    x24, x24, #(SMP_STACK_SIZE)
 #  endif
 
-    /* Initialize percpu reg tpidr_el1 */
+    /* Initialize percpu reg tpidr_el1 tpidr_el0 */
 
     msr    tpidr_el1, xzr
+    msr    tpidr_el0, xzr
     ldr    x25, =arm64_boot_secondary_c_routine
     bl     __reset_prep_c
 
@@ -209,9 +210,10 @@ primary_core:
     ldr    x24, =(g_idle_stack + CONFIG_IDLETHREAD_STACKSIZE)
 #endif /* CONFIG_SMP */
 
-    /* Initialize percpu reg tpidr_el1 */
+    /* Initialize percpu reg tpidr_el1 tpidr_el0 */
 
     msr    tpidr_el1, xzr
+    msr    tpidr_el0, xzr
     ldr    x25, =arm64_boot_primary_c_routine
 
     /* Prepare for calling C code */
diff --git a/arch/arm64/src/common/arm64_internal.h 
b/arch/arm64/src/common/arm64_internal.h
index 52f53be16a7..c76d2a17c61 100644
--- a/arch/arm64/src/common/arm64_internal.h
+++ b/arch/arm64/src/common/arm64_internal.h
@@ -392,6 +392,19 @@ void arm64_stack_color(void *stackbase, size_t nbytes);
 void arm64_enable_dbgmonitor(void);
 #endif
 
+static inline_function void arm64_tp_boot(int cpu)
+{
+  uintptr_t val;
+
+#ifdef CONFIG_SMP
+  val = (uintptr_t)(g_cpu_idlestackalloc[cpu]);
+#else
+  val = (uintptr_t)(g_idle_stack);
+#endif
+
+  write_sysreg(val, tpidr_el0);
+}
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/arch/arm64/src/common/arm64_syscall.c 
b/arch/arm64/src/common/arm64_syscall.c
index 312444b018b..2bc6712f592 100644
--- a/arch/arm64/src/common/arm64_syscall.c
+++ b/arch/arm64/src/common/arm64_syscall.c
@@ -360,5 +360,10 @@ uint64_t *arm64_syscall(uint64_t *regs)
   /* Clear irq flag */
 
   write_sysreg((uintptr_t)tcb & ~1ul, tpidr_el1);
+
+  /* Update the TLS pointer */
+
+  write_sysreg(tcb->stack_alloc_ptr, tpidr_el0);
+
   return regs;
 }

Reply via email to