diff --git a/arch/risc-v/src/common/riscv_percpu.c b/arch/risc-v/src/common/riscv_percpu.c index 13072ff8cd..a74d114c35 100644 --- a/arch/risc-v/src/common/riscv_percpu.c +++ b/arch/risc-v/src/common/riscv_percpu.c @@ -42,10 +42,16 @@ #define HART_CNT (CONFIG_SMP_NCPUS) +static_assert(RISCV_PERCPU_TCB == offsetof(riscv_percpu_t, tcb), + "RISCV_PERCPU_TCB offset is wrong"); static_assert(RISCV_PERCPU_HARTID == offsetof(riscv_percpu_t, hartid), "RISCV_PERCPU_HARTID offset is wrong"); static_assert(RISCV_PERCPU_IRQSTACK == offsetof(riscv_percpu_t, irq_stack), "RISCV_PERCPU_IRQSTACK offset is wrong"); +static_assert(RISCV_PERCPU_USP == offsetof(riscv_percpu_t, usp), + "RISCV_PERCPU_USP offset is wrong"); +static_assert(RISCV_PERCPU_KSP == offsetof(riscv_percpu_t, ksp), + "RISCV_PERCPU_KSP offset is wrong"); /**************************************************************************** * Private Data @@ -223,3 +229,35 @@ void riscv_percpu_set_kstack(uintptr_t ksp) ((riscv_percpu_t *)scratch)->ksp = ksp; leave_critical_section(flags); } + +/**************************************************************************** + * Name: riscv_percpu_set_thread + * + * Description: + * Set current thread (tcb), so it can be found quickly when a trap is + * taken. + * + * Input Parameters: + * tcb - Pointer to the current thread's tcb + * + * Returned Value: + * None + * + ****************************************************************************/ + +void riscv_percpu_set_thread(struct tcb_s *tcb) +{ + irqstate_t flags; + uintptr_t scratch; + + /* This must be done with interrupts disabled */ + + flags = enter_critical_section(); + scratch = READ_CSR(CSR_SCRATCH); + + DEBUGASSERT(scratch >= (uintptr_t) &g_percpu && + scratch < (uintptr_t) &g_percpu + sizeof(g_percpu)); + + ((riscv_percpu_t *)scratch)->tcb = tcb; + leave_critical_section(flags); +} diff --git a/arch/risc-v/src/common/riscv_percpu.h b/arch/risc-v/src/common/riscv_percpu.h index cc09fe0b24..147e6c143d 100644 --- a/arch/risc-v/src/common/riscv_percpu.h +++ b/arch/risc-v/src/common/riscv_percpu.h @@ -47,7 +47,7 @@ * 2: REGLOAD a0, RISCV_PERCPU_HARTID(a0) */ -#define RISCV_PERCPU_LIST (0 * INT_REG_SIZE) +#define RISCV_PERCPU_TCB (0 * INT_REG_SIZE) #define RISCV_PERCPU_HARTID (1 * INT_REG_SIZE) #define RISCV_PERCPU_IRQSTACK (2 * INT_REG_SIZE) #define RISCV_PERCPU_USP (3 * INT_REG_SIZE) @@ -65,16 +65,20 @@ * will set up [m/s]scratch to point to the CPUs own area */ -struct riscv_percpu_s +union riscv_percpu_s { - struct riscv_percpu_s *next; /* For sl list linkage */ - uintptr_t hartid; /* Hart ID */ - uintptr_t irq_stack; /* Interrupt stack */ - uintptr_t usp; /* Area to store user sp */ - uintptr_t ksp; /* Area to load kernel sp */ + union riscv_percpu_s *next; /* For sl list linkage */ + struct + { + struct tcb_s *tcb; /* Current thread TCB */ + uintptr_t hartid; /* Hart ID */ + uintptr_t irq_stack; /* Interrupt stack */ + uintptr_t usp; /* Area to store user sp */ + uintptr_t ksp; /* Area to load kernel sp */ + }; }; -typedef struct riscv_percpu_s riscv_percpu_t; +typedef union riscv_percpu_s riscv_percpu_t; /**************************************************************************** * Public Function Prototypes @@ -137,5 +141,22 @@ uintptr_t riscv_percpu_get_irqstack(void); void riscv_percpu_set_kstack(uintptr_t ksp); +/**************************************************************************** + * Name: riscv_percpu_set_thread + * + * Description: + * Set current thread (tcb), so it can be found quickly when a trap is + * taken. + * + * Input Parameters: + * tcb - Pointer to the current thread's tcb + * + * Returned Value: + * None + * + ****************************************************************************/ + +void riscv_percpu_set_thread(struct tcb_s *tcb); + #endif /* __ASSEMBLY__ */ #endif /* __ARCH_RISC_V_SRC_COMMON_RISCV_PERCPU_H */