riscv: Initialize TP register when starting threads

Set TP in exception context so that it gets loaded into the CPU when
first running the thread. Set TP for secondary cores to related idle TLS
area.

Signed-off-by: Keith Packard <keithp@keithp.com>
diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c
index f3283e4..9b02f9d 100644
--- a/arch/riscv/core/fatal.c
+++ b/arch/riscv/core/fatal.c
@@ -42,6 +42,7 @@
 #ifdef CONFIG_USERSPACE
 		LOG_ERR("     sp: " PR_REG, esf->sp);
 #endif
+		LOG_ERR("     tp: " PR_REG, esf->tp);
 		LOG_ERR("     ra: " PR_REG, esf->ra);
 		LOG_ERR("   mepc: " PR_REG, esf->mepc);
 		LOG_ERR("mstatus: " PR_REG, esf->mstatus);
diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S
index 75a6cf8..62bd429 100644
--- a/arch/riscv/core/isr.S
+++ b/arch/riscv/core/isr.S
@@ -59,6 +59,7 @@
 	op a5, __z_arch_esf_t_a5_OFFSET(sp)		;\
 	op a6, __z_arch_esf_t_a6_OFFSET(sp)		;\
 	op a7, __z_arch_esf_t_a7_OFFSET(sp)		;\
+	op tp, __z_arch_esf_t_tp_OFFSET(sp)             ;\
 	op ra, __z_arch_esf_t_ra_OFFSET(sp)
 
 #ifdef CONFIG_SMP
diff --git a/arch/riscv/core/offsets/offsets.c b/arch/riscv/core/offsets/offsets.c
index 1cfbf9b..9f14e26 100644
--- a/arch/riscv/core/offsets/offsets.c
+++ b/arch/riscv/core/offsets/offsets.c
@@ -81,6 +81,8 @@
 
 GEN_OFFSET_SYM(z_arch_esf_t, s0);
 
+GEN_OFFSET_SYM(z_arch_esf_t, tp);
+
 #ifdef CONFIG_USERSPACE
 GEN_OFFSET_SYM(z_arch_esf_t, sp);
 #endif
diff --git a/arch/riscv/core/smp.c b/arch/riscv/core/smp.c
index 22ed3d0..dcc20b7 100644
--- a/arch/riscv/core/smp.c
+++ b/arch/riscv/core/smp.c
@@ -41,6 +41,9 @@
 #ifdef CONFIG_SMP
 	irq_enable(RISCV_MACHINE_SOFT_IRQ);
 #endif
+#ifdef CONFIG_THREAD_LOCAL_STORAGE
+	__asm__("mv tp, %0" : : "r" (z_idle_threads[cpu_num].tls));
+#endif
 	riscv_cpu_init[cpu_num].fn(riscv_cpu_init[cpu_num].arg);
 }
 
diff --git a/arch/riscv/core/thread.c b/arch/riscv/core/thread.c
index e035935..e7709a0 100644
--- a/arch/riscv/core/thread.c
+++ b/arch/riscv/core/thread.c
@@ -94,6 +94,11 @@
 	stack_init->sp = (ulong_t)(stack_init + 1);
 #endif /* CONFIG_USERSPACE */
 
+#if defined(CONFIG_THREAD_LOCAL_STORAGE)
+	stack_init->tp = thread->tls;
+	thread->callee_saved.tp = thread->tls;
+#endif
+
 	/* Assign thread entry point and mstatus.MPRV mode. */
 	if (IS_ENABLED(CONFIG_USERSPACE)
 	    && (thread->base.user_options & K_USER)) {
diff --git a/include/zephyr/arch/riscv/exp.h b/include/zephyr/arch/riscv/exp.h
index 9d120b3..35682f1 100644
--- a/include/zephyr/arch/riscv/exp.h
+++ b/include/zephyr/arch/riscv/exp.h
@@ -74,6 +74,7 @@
 
 	ulong_t s0;		/* callee-saved s0 */
 
+	ulong_t tp;		/* thread pointer */
 #ifdef CONFIG_USERSPACE
 	ulong_t sp;		/* preserved (user or kernel) stack pointer */
 #endif