diff options
author | Ian Moffett <ian@osmora.org> | 2025-09-17 15:06:35 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-09-17 15:08:32 -0400 |
commit | bb840ef326ab3570d201e045e894710fd6db18f2 (patch) | |
tree | 89133e8bfed5ead413648ad0f2ef331ec40ba031 /src/sys/arch/amd64/os | |
parent | 9ed326263929d215887dd9bab18d292d6632ed34 (diff) |
kern/amd64: proc: Add initial context switch logic
This commit introduces new functions that will be useful for
having multiple processes run on the system.
- Add md_proc_yield()
- Add md_proc_kick()
- Add md_sched_switch()
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'src/sys/arch/amd64/os')
-rw-r--r-- | src/sys/arch/amd64/os/os_proc.c | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/src/sys/arch/amd64/os/os_proc.c b/src/sys/arch/amd64/os/os_proc.c index 61ef51e..8c7b6f3 100644 --- a/src/sys/arch/amd64/os/os_proc.c +++ b/src/sys/arch/amd64/os/os_proc.c @@ -36,6 +36,7 @@ #include <machine/pcb.h> #include <machine/gdt.h> #include <machine/frame.h> +#include <machine/lapic.h> #include <string.h> /* @@ -43,12 +44,16 @@ * run. The catch is that we have never been in userland * from this context so we'll have to fake an IRET frame * to force the processor to have a CPL of 3. - * - * @tfp: Trapframe of context to enter */ -static inline void -__proc_kick(struct trapframe *tfp) +__dead void +md_proc_kick(struct proc *procp) { + struct md_pcb *pcbp = &procp->pcb; + struct trapframe *tfp = &pcbp->tf; + + mmu_write_vas(&pcbp->vas); + lapic_timer_oneshot_us(SCHED_QUANTUM); + __ASMV( "sti\n" "mov %0, %%rax\n" @@ -67,6 +72,8 @@ __proc_kick(struct trapframe *tfp) "m" (tfp->rflags), "r" (tfp->rip) ); + + __builtin_unreachable(); } /* @@ -122,6 +129,21 @@ md_proc_init(struct proc *procp, int flags) } /* + * Process idle loop + */ +__dead void +md_proc_yield(void) +{ + /* Clear pending interrupts and oneshot */ + lapic_eoi(); + lapic_timer_oneshot_us(9000); + + for (;;) { + __ASMV("sti; hlt"); + } +} + +/* * Set process instruction pointer */ int @@ -139,3 +161,54 @@ md_set_ip(struct proc *procp, uintptr_t ip) tfp->rip = ip; return 0; } + +void +md_sched_switch(struct trapframe *tf) +{ + struct proc *self, *proc = NULL; + struct md_pcb *pcbp; + struct pcore *core; + int error; + + if ((core = this_core()) == NULL) { + printf("sched_switch: could not get core\n"); + goto done; + } + + /* Don't switch if no self */ + if ((self = core->curproc) == NULL) { + md_proc_yield(); + } + + error = sched_enq(&core->scq, self); + if (error < 0) { + goto done; + } + + /* + * Save the current trapframe to our process control + * block as we'll want it later when we're back. + */ + pcbp = &self->pcb; + memcpy(&pcbp->tf, tf, sizeof(*tf)); + + /* + * Grab the next process. If we cannot find any, assume + * we are the only one and continue on... + */ + error = sched_deq(&core->scq, &proc); + if (error < 0) { + goto done; + } + + /* Load the next trapframe into the live one */ + pcbp = &proc->pcb; + memcpy(tf, &pcbp->tf, sizeof(*tf)); + core->curproc = proc; + + /* Switch the address space and hope for the best */ + mmu_write_vas(&pcbp->vas); +done: + lapic_eoi(); + lapic_timer_oneshot_us(SCHED_QUANTUM); +} |