diff --git a/arch/risc-v/include/irq.h b/arch/risc-v/include/irq.h index 32710c7e292ed..f903972fe427c 100644 --- a/arch/risc-v/include/irq.h +++ b/arch/risc-v/include/irq.h @@ -749,6 +749,33 @@ int up_this_cpu(void); * Inline Functions ****************************************************************************/ +/**************************************************************************** + * Schedule acceleration macros + ****************************************************************************/ + +/* When thread local storage is disabled (the usual case), the TP (Thread Pointer) + * register is available for use as a general purpose register. We use it to store + * the current task's TCB pointer for quick access. + * + * Note: If you want to use TLS (CONFIG_SCHED_THREAD_LOCAL), your toolchain must + * be compiled with --enable-tls option to properly support thread-local storage. + */ + +#ifndef CONFIG_SCHED_THREAD_LOCAL +#define up_this_task() \ + ({ \ + struct tcb_s* t; \ + __asm__ __volatile__("mv %0, tp" : "=r"(t)); \ + t; \ + }) + +/* Update the current task pointer stored in TP register */ +#define up_update_task(t) \ + { \ + __asm__ __volatile__("mv tp, %0" : : "r"(t)); \ + } +#endif /* CONFIG_SCHED_THREAD_LOCAL */ + /**************************************************************************** * Name: up_irq_save * diff --git a/arch/risc-v/src/common/riscv_cpustart.c b/arch/risc-v/src/common/riscv_cpustart.c index f659babe6fd4b..27d671dcd04a5 100644 --- a/arch/risc-v/src/common/riscv_cpustart.c +++ b/arch/risc-v/src/common/riscv_cpustart.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "sched/sched.h" #include "init/init.h" @@ -69,6 +70,8 @@ void riscv_cpu_boot(int cpu) { + struct tcb_s *tcb; + /* Clear IPI for CPU(cpu) */ riscv_ipi_clear(cpu); @@ -100,9 +103,9 @@ void riscv_cpu_boot(int cpu) sinfo("CPU%d Started\n", this_cpu()); -#ifdef CONFIG_STACK_COLORATION - struct tcb_s *tcb = this_task(); + tcb = current_task(this_cpu()); +#ifdef CONFIG_STACK_COLORATION /* If stack debug is enabled, then fill the stack with a * recognizable value that we can use later to test for high * water marks. @@ -111,6 +114,8 @@ void riscv_cpu_boot(int cpu) riscv_stack_color(tcb->stack_alloc_ptr, 0); #endif + up_update_task(tcb); + /* TODO: Setup FPU */ /* Clear machine software interrupt for CPU(cpu) */ diff --git a/arch/risc-v/src/common/riscv_initialstate.c b/arch/risc-v/src/common/riscv_initialstate.c index 8a3527204caf1..c991b90e10457 100644 --- a/arch/risc-v/src/common/riscv_initialstate.c +++ b/arch/risc-v/src/common/riscv_initialstate.c @@ -153,6 +153,8 @@ void up_initial_state(struct tcb_s *tcb) #ifdef CONFIG_SCHED_THREAD_LOCAL xcp->regs[REG_TP] = (uintptr_t)tcb->stack_alloc_ptr + sizeof(struct tls_info_s); +#else + xcp->regs[REG_TP] = (uintptr_t)tcb; #endif /* Set the initial value of the interrupt context register. diff --git a/arch/risc-v/src/common/riscv_macros.S b/arch/risc-v/src/common/riscv_macros.S index ae530fb03dec7..48894850e3950 100644 --- a/arch/risc-v/src/common/riscv_macros.S +++ b/arch/risc-v/src/common/riscv_macros.S @@ -58,7 +58,9 @@ #ifdef RISCV_SAVE_GP REGSTORE x3, REG_X3(\in) /* gp */ #endif +#ifdef CONFIG_SCHED_THREAD_LOCAL REGSTORE x4, REG_X4(\in) /* tp */ +#endif REGSTORE x5, REG_X5(\in) /* t0 */ REGSTORE x6, REG_X6(\in) /* t1 */ REGSTORE x7, REG_X7(\in) /* t2 */ @@ -201,7 +203,9 @@ #ifdef RISCV_SAVE_GP REGLOAD x3, REG_X3(\out) /* gp */ #endif +#ifdef CONFIG_SCHED_THREAD_LOCAL REGLOAD x4, REG_X4(\out) /* tp */ +#endif REGLOAD x5, REG_X5(\out) /* t0 */ REGLOAD x6, REG_X6(\out) /* t1 */ REGLOAD x7, REG_X7(\out) /* t2 */