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;
}