Skip to content

Commit

Permalink
riscv: use g_running_task store current regs
Browse files Browse the repository at this point in the history
This commit fixes the regression from apache#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 <[email protected]>
  • Loading branch information
hujun260 authored and jlaitine committed Sep 30, 2024
1 parent b2b6fda commit bf75048
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 35 deletions.
20 changes: 7 additions & 13 deletions arch/risc-v/src/common/riscv_doirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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;
}
4 changes: 4 additions & 0 deletions arch/risc-v/src/common/riscv_exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 0 additions & 4 deletions arch/risc-v/src/common/riscv_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
4 changes: 4 additions & 0 deletions arch/risc-v/src/common/riscv_sigdeliver.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ void riscv_sigdeliver(void)
rtcb->irqcount--;
#endif

/* g_running_tasks is not valid now */

g_running_tasks[this_cpu()] = NULL;

rtcb->xcp.regs = regs;
riscv_fullcontextrestore(rtcb);
}
2 changes: 0 additions & 2 deletions arch/risc-v/src/common/riscv_swint.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
27 changes: 11 additions & 16 deletions arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,24 @@

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() */

up_set_current_regs(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
Expand All @@ -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;
}

0 comments on commit bf75048

Please sign in to comment.