arch: fix addrenv_switch changing this_task causing exceptions

After addrenv_switch(), the current running task (this_task) may change due to
deferred work execution. Update all architecture interrupt, syscall, and exit
handlers to re-fetch tcb = this_task() after addrenv_switch(). Ensures scheduler
and context operations use the correct TCB, preventing context corruption and
exceptions across SMP and memory-protected builds.

Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
hujun5
2025-05-06 19:24:52 +08:00
committed by Alan C. Assis
parent 113bb02568
commit 657ac8317e
35 changed files with 92 additions and 50 deletions
+1
View File
@@ -98,6 +98,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+4 -3
View File
@@ -95,6 +95,10 @@ uint32_t *arm_syscall(uint32_t *regs)
nxsched_switch_context(*running_task, tcb);
case SYS_restore_context:
#ifdef CONFIG_ARCH_ADDRENV
addrenv_switch(tcb);
tcb = this_task();
#endif
/* No context switch occurs in SYS_restore_context, or the
* context switch has been completed, so there is no
@@ -106,9 +110,6 @@ uint32_t *arm_syscall(uint32_t *regs)
/* Restore the cpu lock */
restore_critical_section(tcb, cpu);
#ifdef CONFIG_ARCH_ADDRENV
addrenv_switch(tcb);
#endif
break;
default:
+1
View File
@@ -98,6 +98,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+8 -3
View File
@@ -274,6 +274,14 @@ uint32_t *arm_syscall(uint32_t *regs)
case SYS_restore_context:
#ifdef CONFIG_ARCH_ADDRENV
/* The addrenv_switch may change this_task, for example addrenv drop
* will post sem to hpwork, so we have to call before restore context
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* No context switch occurs in SYS_restore_context, or the
* context switch has been completed, so there is no
* need to update scheduler parameters.
@@ -285,9 +293,6 @@ uint32_t *arm_syscall(uint32_t *regs)
restore_critical_section(tcb, cpu);
regs = tcb->xcp.regs;
#ifdef CONFIG_ARCH_ADDRENV
addrenv_switch(tcb);
#endif
break;
/* R0=SYS_task_start: This a user task start
+4 -4
View File
@@ -270,7 +270,10 @@ uint32_t *arm_syscall(uint32_t *regs)
nxsched_switch_context(*running_task, tcb);
case SYS_restore_context:
#ifdef CONFIG_ARCH_ADDRENV
addrenv_switch(tcb);
tcb = this_task();
#endif
/* No context switch occurs in SYS_restore_context, or the
* context switch has been completed, so there is no
* need to update scheduler parameters.
@@ -282,9 +285,6 @@ uint32_t *arm_syscall(uint32_t *regs)
restore_critical_section(tcb, cpu);
regs = tcb->xcp.regs;
#ifdef CONFIG_ARCH_ADDRENV
addrenv_switch(tcb);
#endif
break;
/* R0=SYS_task_start: This a user task start
+1
View File
@@ -128,6 +128,7 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+7 -3
View File
@@ -196,11 +196,18 @@ uint64_t *arm64_syscall(uint64_t *regs)
restore_critical_section(tcb, cpu);
#ifdef CONFIG_ARCH_ADDRENV
addrenv_switch(tcb);
tcb = this_task();
*running_task = tcb;
#endif
break;
case SYS_switch_context:
#ifdef CONFIG_ARCH_ADDRENV
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
nxsched_switch_context(*running_task, tcb);
@@ -209,9 +216,6 @@ uint64_t *arm64_syscall(uint64_t *regs)
/* Restore the cpu lock */
restore_critical_section(tcb, cpu);
#ifdef CONFIG_ARCH_ADDRENV
addrenv_switch(tcb);
#endif
break;
#ifdef CONFIG_BUILD_KERNEL
+1
View File
@@ -107,6 +107,7 @@ uint32_t *avr_doirq(int irq, uint32_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters. */
+1
View File
@@ -88,6 +88,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+5 -4
View File
@@ -67,10 +67,6 @@ void up_exit(int status)
tcb = this_task();
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously running
* task is closed down gracefully (data caches dump, MMU flushed) and
@@ -79,8 +75,13 @@ void up_exit(int status)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
/* Then switch contexts */
avr_fullcontextrestore(tcb->xcp.regs);
+1
View File
@@ -107,6 +107,7 @@ uint8_t *hc_doirq(int irq, uint8_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters. */
+5 -4
View File
@@ -66,10 +66,6 @@ void up_exit(int status)
tcb = this_task();
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously running
* task is closed down gracefully (data caches dump, MMU flushed) and
@@ -78,8 +74,13 @@ void up_exit(int status)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
/* Then switch contexts */
hc_fullcontextrestore(tcb->xcp.regs);
+1
View File
@@ -91,6 +91,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+1
View File
@@ -116,6 +116,7 @@ uint32_t *mips_doirq(int irq, uint32_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters. */
+1
View File
@@ -101,6 +101,7 @@ uint32_t *lm32_doirq(int irq, uint32_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters. */
+1
View File
@@ -100,6 +100,7 @@ uint32_t *minerva_doirq(int irq, uint32_t * regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters. */
+5 -4
View File
@@ -68,10 +68,6 @@ void up_exit(int status)
tcb = this_task();
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously running
* task is closed down gracefully (data caches dump, MMU flushed) and
@@ -80,8 +76,13 @@ void up_exit(int status)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
/* Then switch contexts */
or1k_fullcontextrestore(tcb->xcp.regs);
@@ -95,6 +95,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+1
View File
@@ -110,6 +110,7 @@ uint32_t *renesas_doirq(int irq, uint32_t * regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters. */
+5 -4
View File
@@ -66,10 +66,6 @@ void up_exit(int status)
tcb = this_task();
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously running
* task is closed down gracefully (data caches dump, MMU flushed) and
@@ -78,8 +74,13 @@ void up_exit(int status)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
/* Then switch contexts */
renesas_fullcontextrestore(tcb->xcp.regs);
@@ -91,6 +91,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+1
View File
@@ -124,6 +124,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
@@ -68,6 +68,7 @@ void *riscv_perform_syscall(uintreg_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+1
View File
@@ -111,6 +111,7 @@ uint32_t *sparc_doirq(int irq, uint32_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters. */
+1
View File
@@ -89,6 +89,7 @@ IFX_INTERRUPT_INTERNAL(tricore_doirq, 0, 255)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+7 -6
View File
@@ -67,12 +67,6 @@ void up_exit(int status)
tcb = this_task();
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
* NOTE: the API also adjusts the global IRQ control for SMP
*/
g_running_tasks[this_cpu()] = tcb;
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously running
* task is closed down gracefully (data caches dump, MMU flushed) and
@@ -81,8 +75,15 @@ void up_exit(int status)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
* NOTE: the API also adjusts the global IRQ control for SMP
*/
g_running_tasks[this_cpu()] = tcb;
/* Then switch contexts */
x86_fullcontextrestore(tcb->xcp.regs);
+1
View File
@@ -91,6 +91,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+1
View File
@@ -121,6 +121,7 @@ static uint32_t *common_handler(int irq, uint32_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+11 -10
View File
@@ -66,6 +66,17 @@ void up_exit(int status)
tcb = this_task();
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously running
* task is closed down gracefully (data caches dump, MMU flushed) and
* set up the address environment for the new thread at the head of
* the ready-to-run list.
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
* NOTE: the API also adjusts the global IRQ control for SMP
*/
@@ -76,16 +87,6 @@ void up_exit(int status)
x86_64_restore_auxstate(tcb);
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously running
* task is closed down gracefully (data caches dump, MMU flushed) and
* set up the address environment for the new thread at the head of
* the ready-to-run list.
*/
addrenv_switch(tcb);
#endif
/* Restore the cpu lock */
restore_critical_section(tcb, this_cpu());
@@ -97,6 +97,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Restore the cpu lock */
@@ -102,6 +102,7 @@ static uint64_t *common_handler(int irq, uint64_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
@@ -93,6 +93,7 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+1
View File
@@ -93,6 +93,7 @@ FAR chipreg_t *z80_doirq(uint8_t irq, FAR chipreg_t *regs)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */
+7 -5
View File
@@ -67,11 +67,6 @@ void up_exit(int status)
*/
tcb = this_task();
sinfo("New Active Task TCB=%p\n", tcb);
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously running
@@ -81,8 +76,15 @@ void up_exit(int status)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
sinfo("New Active Task TCB=%p\n", tcb);
/* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases */
g_running_tasks[this_cpu()] = tcb;
/* Then switch contexts */
RESTORE_USERCONTEXT(tcb);
+1
View File
@@ -94,6 +94,7 @@ void up_switch_context(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb)
*/
addrenv_switch(tcb);
tcb = this_task();
#endif
/* Update scheduler parameters */