Skip to content

Commit

Permalink
arch/intel64: optimise context switch
Browse files Browse the repository at this point in the history
We save interrupted TCB state on tcb->xcp.regs not interrupt stack now
which allows us to remove x86_64_savestate() from up_switch_context()
and other places.

Signed-off-by: p-szafonimateusz <[email protected]>
Signed-off-by: hujun5 <[email protected]>
  • Loading branch information
szafonimateusz-mi authored and hujun260 committed Oct 14, 2024
1 parent b964eee commit 9368d43
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 142 deletions.
8 changes: 8 additions & 0 deletions arch/x86_64/include/intel64/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@

#define XMMAREA_REGS (25)

/* Aux register used by implementation */

#define REG_AUX (26 + XMMAREA_REG_OFFSET)

/* NOTE 2: This is not really state data. Rather, this is just a convenient
* way to pass parameters from the interrupt handler to C code.
*/
Expand All @@ -478,6 +482,10 @@
#define XCP_ALIGN_DOWN(a) ((a) & ~XCP_ALIGN_MASK)
#define XCP_ALIGN_UP(a) (((a) + XCP_ALIGN_MASK) & ~XCP_ALIGN_MASK)

/* Aux register flags */

#define REG_AUX_FULLCONTEXT (1 << 0) /* Force full context switch */

/****************************************************************************
* Public Types
****************************************************************************/
Expand Down
1 change: 0 additions & 1 deletion arch/x86_64/src/common/x86_64_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,6 @@ void x86_64_boardinitialize(void);
/* Defined in files with the same name as the function */

void x86_64_copystate(uint64_t *dest, uint64_t *src);
void x86_64_savestate(uint64_t *regs);
void x86_64_decodeirq(uint64_t *regs);
#ifdef CONFIG_ARCH_DMA
void weak_function x86_64_dmainitialize(void);
Expand Down
10 changes: 2 additions & 8 deletions arch/x86_64/src/common/x86_64_switchcontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,11 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)

if (up_interrupt_context())
{
/* Yes, then we have to do things differently.
* Just copy the g_current_regs into the OLD rtcb.
*/

x86_64_savestate(rtcb->xcp.regs);
/* Restore addition x86_64 state */

x86_64_restore_auxstate(tcb);

/* Then switch contexts. Any necessary address environment
* changes will be made when the interrupt returns.
*/
/* Update current regs to signal that we need context switch */

x86_64_restorestate(tcb->xcp.regs);
}
Expand Down
1 change: 0 additions & 1 deletion arch/x86_64/src/intel64/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ set(SRCS
intel64_releasestack.c
intel64_rtc.c
intel64_restore_auxstate.c
intel64_savestate.c
intel64_stackframe.c
intel64_schedulesigaction.c
intel64_sigdeliver.c
Expand Down
2 changes: 1 addition & 1 deletion arch/x86_64/src/intel64/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ include common/Make.defs

CMN_CSRCS += intel64_createstack.c intel64_initialstate.c intel64_irq.c
CMN_CSRCS += intel64_map_region.c intel64_regdump.c intel64_releasestack.c
CMN_CSRCS += intel64_rtc.c intel64_restore_auxstate.c intel64_savestate.c
CMN_CSRCS += intel64_rtc.c intel64_restore_auxstate.c
CMN_CSRCS += intel64_stackframe.c intel64_schedulesigaction.c
CMN_CSRCS += intel64_sigdeliver.c intel64_usestack.c x86_64_tcbinfo.c
CMN_CSRCS += intel64_systemreset.c intel64_freq.c intel64_cache.c
Expand Down
29 changes: 26 additions & 3 deletions arch/x86_64/src/intel64/intel64_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,8 @@ static uint64_t *common_handler(int irq, uint64_t *regs)

/* Check for a context switch. If a context switch occurred, then
* g_current_regs will have a different value than it did on entry. If an
* interrupt level context switch has occurred, then restore the floating
* point state and the establish the correct address environment before
* returning from the interrupt.
* interrupt level context switch has occurred, then the establish the
* correct address environment before returning from the interrupt.
*/

if (regs != up_current_regs())
Expand Down Expand Up @@ -238,3 +237,27 @@ uint64_t *irq_handler(uint64_t *regs, uint64_t irq_no)
return ret;
#endif
}

/****************************************************************************
* Name: irq_xcp_regs
*
* Description:
* Return current task XCP registers area.
*
* ASSUMPTION:
* Interrupts are disabled.
*
* This function should be called only form intel64_vector.S file !
* Any other use must be carefully considered.
*
****************************************************************************/

uint64_t *irq_xcp_regs(void)
{
/* This must be the simplest as possible, so we not use too much registers.
* Now this function corrupts only RAX and RDX registers regardless of
* the compiler optimization.
*/

return (current_task(this_cpu()))->xcp.regs;
}
50 changes: 0 additions & 50 deletions arch/x86_64/src/intel64/intel64_savestate.c

This file was deleted.

6 changes: 3 additions & 3 deletions arch/x86_64/src/intel64/intel64_saveusercontext.S
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ up_saveusercontext:
/* Save the value of SP as will be at the time of the IRET that will
* appear to be the return from this function.
*
* CURRENT STACK IRET STACK
* ------------------------------ -----------------
* CURRENT STACK IRET STACK
* --------------------- -----------------
* RIP
* CS
* RFLAGS
* RSP
* ESP->Return address SS
* RSP->Return address SS
* Argument Alignment (16bytes)
*
*/
Expand Down
15 changes: 6 additions & 9 deletions arch/x86_64/src/intel64/intel64_schedulesigaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
up_current_regs()[REG_RIP] = (uint64_t)x86_64_sigdeliver;
up_current_regs()[REG_RSP] = up_current_regs()[REG_RSP] - 8;
up_current_regs()[REG_RFLAGS] = 0;

/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/

x86_64_savestate(tcb->xcp.regs);
}
}

Expand Down Expand Up @@ -222,11 +216,14 @@ void up_schedule_sigaction(struct tcb_s *tcb)
up_current_regs()[REG_RSP] = up_current_regs()[REG_RSP] - 8;
up_current_regs()[REG_RFLAGS] = 0;

/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
/* Mark that full context switch is necessary when we
* return from interrupt handler.
* In that case RIP, RSP and RFLAGS are changed, but
* register area pointer remains the same, so we need an
* additional variable to signal the need for full context switch
*/

x86_64_savestate(tcb->xcp.regs);
tcb->xcp.regs[REG_AUX] = REG_AUX_FULLCONTEXT;
}
}

Expand Down
2 changes: 0 additions & 2 deletions arch/x86_64/src/intel64/intel64_smpcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ int x86_64_smp_call_handler(int irq, void *c, void *arg)
int cpu = this_cpu();

tcb = current_task(cpu);
x86_64_savestate(tcb->xcp.regs);
nxsched_smp_call_handler(irq, c, arg);
tcb = current_task(cpu);
x86_64_restorestate(tcb->xcp.regs);
Expand Down Expand Up @@ -97,7 +96,6 @@ int x86_64_smp_sched_handler(int irq, void *c, void *arg)

tcb = current_task(cpu);
nxsched_suspend_scheduler(tcb);
x86_64_savestate(tcb->xcp.regs);
nxsched_process_delivered(cpu);
tcb = current_task(cpu);
nxsched_resume_scheduler(tcb);
Expand Down
Loading

0 comments on commit 9368d43

Please sign in to comment.