From d1fec65e1ba3e3fac554697c5832f58e4fde093e Mon Sep 17 00:00:00 2001 From: hujun5 Date: Fri, 27 Sep 2024 14:42:11 +0800 Subject: [PATCH] riscv: use g_running_task store current regs This commit fixes the regression from https://github.com/apache/nuttx/pull/13561 In order to determine whether a context switch has occurred, we can use g_running_task to store the current regs. This allows us to compare the current register state with the previously stored state to identify if a context switch has taken place. Signed-off-by: hujun5 --- arch/risc-v/src/common/riscv_doirq.c | 20 +++++--------- arch/risc-v/src/common/riscv_exit.c | 4 +++ arch/risc-v/src/common/riscv_internal.h | 4 --- arch/risc-v/src/common/riscv_sigdeliver.c | 4 +++ arch/risc-v/src/common/riscv_swint.c | 2 -- .../common/supervisor/riscv_perform_syscall.c | 27 ++++++++----------- 6 files changed, 26 insertions(+), 35 deletions(-) diff --git a/arch/risc-v/src/common/riscv_doirq.c b/arch/risc-v/src/common/riscv_doirq.c index 895bd910de..c02d1196e8 100644 --- a/arch/risc-v/src/common/riscv_doirq.c +++ b/arch/risc-v/src/common/riscv_doirq.c @@ -58,6 +58,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs) { + struct tcb_s **running_task = &g_running_tasks[this_cpu()]; struct tcb_s *tcb = this_task(); board_autoled_on(LED_INIRQ); @@ -71,9 +72,10 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs) { regs[REG_EPC] += 4; } - else + + if (*running_task != NULL) { - tcb->xcp.regs = regs; + (*running_task)->xcp.regs = regs; } /* Current regs non-zero indicates that we are processing an interrupt; @@ -97,7 +99,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs) * returning from the interrupt. */ - if (regs != tcb->xcp.regs) + if ((*running_task) != tcb) { #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously @@ -114,15 +116,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs) * crashes. */ - g_running_tasks[this_cpu()] = tcb; - - /* If a context switch occurred while processing the interrupt then - * current_regs may have change value. If we return any value - * different from the input regs, then the lower level will know - * that a context switch occurred during interrupt processing. - */ - - regs = tcb->xcp.regs; + *running_task = tcb; } /* Set current_regs to NULL to indicate that we are no longer in an @@ -133,5 +127,5 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs) #endif board_autoled_off(LED_INIRQ); - return regs; + return tcb->xcp.regs; } diff --git a/arch/risc-v/src/common/riscv_exit.c b/arch/risc-v/src/common/riscv_exit.c index 5c747e58e0..201cf52163 100644 --- a/arch/risc-v/src/common/riscv_exit.c +++ b/arch/risc-v/src/common/riscv_exit.c @@ -78,6 +78,10 @@ void up_exit(int status) nxsched_resume_scheduler(tcb); + /* g_running_tasks is not valid now */ + + g_running_tasks[this_cpu()] = NULL; + /* Then switch contexts */ riscv_fullcontextrestore(tcb); diff --git a/arch/risc-v/src/common/riscv_internal.h b/arch/risc-v/src/common/riscv_internal.h index c8b5f184bf..d9165356a9 100644 --- a/arch/risc-v/src/common/riscv_internal.h +++ b/arch/risc-v/src/common/riscv_internal.h @@ -109,10 +109,6 @@ #define PMP_ACCESS_DENIED (-1) /* Access set and denied */ #define PMP_ACCESS_FULL (1) /* Access set and allowed */ -/* Return values from riscv_swint */ - -#define SWINT_CONTEXT_SWITCH (1) /* Indicate we need context switch */ - #ifndef __ASSEMBLY__ /* Use ASM as rv64ilp32 compiler generated address is limited */ diff --git a/arch/risc-v/src/common/riscv_sigdeliver.c b/arch/risc-v/src/common/riscv_sigdeliver.c index 9d00ef40ee..a9d63a66b3 100644 --- a/arch/risc-v/src/common/riscv_sigdeliver.c +++ b/arch/risc-v/src/common/riscv_sigdeliver.c @@ -162,6 +162,10 @@ retry: rtcb->irqcount--; #endif + /* g_running_tasks is not valid now */ + + g_running_tasks[this_cpu()] = NULL; + rtcb->xcp.regs = regs; riscv_fullcontextrestore(rtcb); } diff --git a/arch/risc-v/src/common/riscv_swint.c b/arch/risc-v/src/common/riscv_swint.c index 4cf68ac0aa..ef64f4dadb 100644 --- a/arch/risc-v/src/common/riscv_swint.c +++ b/arch/risc-v/src/common/riscv_swint.c @@ -257,7 +257,6 @@ int riscv_swint(int irq, void *context, void *arg) struct tcb_s *next = (struct tcb_s *)(uintptr_t)regs[REG_A2]; DEBUGASSERT(regs[REG_A1] != 0 && regs[REG_A2] != 0); - prev->xcp.regs = regs; riscv_savecontext(prev); new_regs = next->xcp.regs; riscv_restorecontext(next); @@ -496,7 +495,6 @@ int riscv_swint(int irq, void *context, void *arg) if (regs != new_regs) { restore_critical_section(this_task(), this_cpu()); - return SWINT_CONTEXT_SWITCH; } return OK; diff --git a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c index 022c58155e..224b891f06 100644 --- a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c +++ b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c @@ -37,9 +37,13 @@ void *riscv_perform_syscall(uintreg_t *regs) { + struct tcb_s **running_task = &g_running_tasks[this_cpu()]; struct tcb_s *tcb; - int cpu; - int ret; + + if (*running_task != NULL) + { + (*running_task)->xcp.regs = regs; + } /* Set up the interrupt register set needed by swint() */ @@ -47,9 +51,10 @@ void *riscv_perform_syscall(uintreg_t *regs) /* Run the system call handler (swint) */ - ret = riscv_swint(0, regs, NULL); + riscv_swint(0, regs, NULL); + tcb = this_task(); - if (ret == SWINT_CONTEXT_SWITCH) + if ((*running_task) != tcb) { #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously @@ -65,20 +70,10 @@ void *riscv_perform_syscall(uintreg_t *regs) * assertion logic for reporting crashes. */ - cpu = this_cpu(); - tcb = current_task(cpu); - g_running_tasks[cpu] = tcb; - - /* If a context switch occurred while processing the interrupt then - * current_regs may have change value. If we return any value - * different from the input regs, then the lower level will know - * that a context switch occurred during interrupt processing. - */ - - regs = tcb->xcp.regs; + *running_task = tcb; } up_set_current_regs(NULL); - return regs; + return tcb->xcp.regs; }