Skip to content

Commit

Permalink
arch/x86_64:g_current_regs is only used to determine if we are in irq,
Browse files Browse the repository at this point in the history
with other functionalities removed.

Signed-off-by: liwenxiang1 <[email protected]>
  • Loading branch information
xianglyc committed Dec 26, 2024
1 parent ebf1ab5 commit d29b222
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 202 deletions.
7 changes: 0 additions & 7 deletions arch/x86_64/src/common/x86_64_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,6 @@
#define getreg32(p) inl(p)
#define putreg32(v,p) outl(v,p)

/* Macros to handle saving and restore interrupt state. In the current
* model, the state is copied from the stack to the TCB, but only a
* referenced is passed to get the state from the TCB.
*/

#define x86_64_restorestate(regs) (up_set_current_regs(regs))

/* ISR/IRQ stack size */

#if CONFIG_ARCH_INTERRUPTSTACK == 0
Expand Down
4 changes: 0 additions & 4 deletions arch/x86_64/src/common/x86_64_switchcontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
/* Restore addition x86_64 state */

x86_64_restore_auxstate(tcb);

/* Update current regs to signal that we need context switch */

x86_64_restorestate(tcb->xcp.regs);
}

/* We are not in an interrupt handler. Copy the user C context
Expand Down
53 changes: 40 additions & 13 deletions arch/x86_64/src/intel64/intel64_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,15 @@ static uint64_t *common_handler(int irq, uint64_t *regs)
/* Deliver the IRQ */

irq_dispatch(irq, regs);
tcb = this_task();

/* 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 the establish the
* correct address environment before returning from the interrupt.
*/

if (regs != up_current_regs())
if (*running_task != tcb)
{
tcb = this_task();

Expand Down Expand Up @@ -119,20 +120,12 @@ static uint64_t *common_handler(int irq, uint64_t *regs)
restore_critical_section(tcb, this_cpu());
}

/* If a context switch occurred while processing the interrupt then
* g_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 = (uint64_t *)up_current_regs();

/* Set g_current_regs to NULL to indicate that we are no longer in an
* interrupt handler.
*/

up_set_current_regs(NULL);
return regs;
return tcb->xcp.regs;
}
#endif

Expand All @@ -151,6 +144,7 @@ static uint64_t *common_handler(int irq, uint64_t *regs)
uint64_t *isr_handler(uint64_t *regs, uint64_t irq)
{
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
struct tcb_s *tcb;

if (*running_task != NULL)
{
Expand Down Expand Up @@ -196,16 +190,49 @@ uint64_t *isr_handler(uint64_t *regs, uint64_t irq)
break;
}

/* Maybe we need a context switch */
tcb = this_task();

/* 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 the establish the
* correct address environment before returning from the interrupt.
*/

if (*running_task != 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(NULL);
#endif

regs = (uint64_t *)up_current_regs();
/* Update scheduler parameters */

nxsched_suspend_scheduler(*running_task);
nxsched_resume_scheduler(tcb);

/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/

*running_task = tcb;

/* Restore the cpu lock */

restore_critical_section(tcb, this_cpu());
}

/* Set g_current_regs to NULL to indicate that we are no longer in an
* interrupt handler.
*/

up_set_current_regs(NULL);
return regs;
return tcb->xcp.regs;
#endif
}

Expand Down
175 changes: 4 additions & 171 deletions arch/x86_64/src/intel64/intel64_schedulesigaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,185 +72,19 @@
*
****************************************************************************/

#ifndef CONFIG_SMP
void up_schedule_sigaction(struct tcb_s *tcb)
{
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), up_current_regs());

/* First, handle some special cases when the signal is being delivered
* to the currently executing task.
*/

if (tcb == this_task())
{
/* CASE 1: We are not in an interrupt handler and a task is
* signalling itself for some reason.
*/

if (!up_current_regs())
{
/* In this case just deliver the signal with a function call
* now.
*/

(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}

/* CASE 2: We are in an interrupt handler AND the interrupted task
* is the same as the one that must receive the signal, then we
* will have to modify the return state as well as the state in the
* TCB.
*
* Hmmm... there looks like a latent bug here: The following logic
* would fail in the strange case where we are in an interrupt
* handler, the thread is signalling itself, but a context switch
* to another task has occurred so that current_regs does not
* refer to the thread of this_task()!
*/

else
{
/* Save the return lr and cpsr and one scratch register. These
* will be restored by the signal trampoline after the signals
* have been delivered.
*/

tcb->xcp.saved_rip = up_current_regs()[REG_RIP];
tcb->xcp.saved_rsp = up_current_regs()[REG_RSP];
tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS];

/* Then set up to vector to the trampoline with interrupts
* disabled
*/

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;

#ifdef CONFIG_ARCH_KERNEL_STACK
/* Update segments to kernel segments */

up_current_regs()[REG_SS] = tcb->xcp.regs[REG_SS];
up_current_regs()[REG_CS] = tcb->xcp.regs[REG_CS];
up_current_regs()[REG_DS] = tcb->xcp.regs[REG_DS];

/* Update RSP to kernel stack */

up_current_regs()[REG_RSP] = (uint64_t)x86_64_get_ktopstk();
#endif
}
}

/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
*/

else
{
/* Save the return lr and cpsr and one scratch register
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/

tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP];
tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];

/* Then set up to vector to the trampoline with interrupts
* disabled
*/

tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
tcb->xcp.regs[REG_RFLAGS] = 0;
}
}
#else /* !CONFIG_SMP */
void up_schedule_sigaction(struct tcb_s *tcb)
{
int cpu;
int me;

sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), up_current_regs());
this_task(), this_task()->xcp.regs);

/* First, handle some special cases when the signal is being delivered
* to task that is currently executing on any CPU.
*/

if (tcb->task_state == TSTATE_TASK_RUNNING)
if (tcb == this_task() && !up_interrupt_context())
{
me = this_cpu();
cpu = tcb->cpu;

/* CASE 1: We are not in an interrupt handler and a task is
* signaling itself for some reason.
*/

if (cpu == me && !up_current_regs())
{
/* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/

(tcb->sigdeliver)(tcb);
tcb->sigdeliver = NULL;
}

/* CASE 2: The task that needs to receive the signal is running.
* This could happen if the task is running on another CPU OR if
* we are in an interrupt handler and the task is running on this
* CPU. In the former case, we will have to PAUSE the other CPU
* first. But in either case, we will have to modify the return
* state as well as the state in the TCB.
*/

else
{
/* tcb is running on the same CPU */

/* Save the return lr and cpsr and one scratch register.
* These will be restored by the signal trampoline after
* the signals have been delivered.
*/

tcb->xcp.saved_rip = up_current_regs()[REG_RIP];
tcb->xcp.saved_rsp = up_current_regs()[REG_RSP];
tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS];

/* Then set up to vector to the trampoline with interrupts
* disabled
*/

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;

#ifdef CONFIG_ARCH_KERNEL_STACK
/* Update segments to kernel segments */

up_current_regs()[REG_SS] = tcb->xcp.regs[REG_SS];
up_current_regs()[REG_CS] = tcb->xcp.regs[REG_CS];
up_current_regs()[REG_DS] = tcb->xcp.regs[REG_DS];

/* Update RSP to kernel stack */

up_current_regs()[REG_RSP] =
(uint64_t)x86_64_get_ktopstk();
#endif
/* 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
*/

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

/* Otherwise, we are (1) signaling a task is not running from an
Expand Down Expand Up @@ -278,4 +112,3 @@ void up_schedule_sigaction(struct tcb_s *tcb)
tcb->xcp.regs[REG_RFLAGS] = 0;
}
}
#endif /* CONFIG_SMP */
10 changes: 3 additions & 7 deletions arch/x86_64/src/intel64/intel64_smpcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,11 @@

int x86_64_smp_call_handler(int irq, void *c, void *arg)
{
struct tcb_s *tcb;
int cpu = this_cpu();

tcb = current_task(cpu);
current_task(cpu);
nxsched_smp_call_handler(irq, c, arg);
tcb = current_task(cpu);
x86_64_restorestate(tcb->xcp.regs);
current_task(cpu);

return OK;
}
Expand All @@ -93,12 +91,10 @@ int x86_64_smp_call_handler(int irq, void *c, void *arg)

int x86_64_smp_sched_handler(int irq, void *c, void *arg)
{
struct tcb_s *tcb;
int cpu = this_cpu();

nxsched_process_delivered(cpu);
tcb = current_task(cpu);
x86_64_restorestate(tcb->xcp.regs);
current_task(cpu);

return OK;
}
Expand Down

0 comments on commit d29b222

Please sign in to comment.