From e3fba3a2fc865a5b4d6fa622fd383b6d612e8c85 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Tue, 16 Sep 2025 20:53:43 -0400 Subject: kern: proc: Add initialization code for ring 3 This commit introduces several new functions for switching the processor into a ring three context along with its task's respective process descriptors to be implemented correctly. - Add md_set_ip() to update proc instruction pointer - Add stack definitions - Add stack mapping logic ... Signed-off-by: Ian Moffett --- src/sys/arch/amd64/os/os_proc.c | 88 +++++++++++++++++++++++++++++++++++++++++ src/sys/include/sys/proc.h | 18 +++++++++ 2 files changed, 106 insertions(+) (limited to 'src/sys') diff --git a/src/sys/arch/amd64/os/os_proc.c b/src/sys/arch/amd64/os/os_proc.c index 8fad7b6..7a65b34 100644 --- a/src/sys/arch/amd64/os/os_proc.c +++ b/src/sys/arch/amd64/os/os_proc.c @@ -30,8 +30,44 @@ #include #include #include +#include #include +#include #include +#include +#include +#include + +/* + * Put the current process into userland for its first + * 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) +{ + __ASMV( + "sti\n" + "mov %0, %%rax\n" + "push %1\n" + "push %2\n" + "push %3\n" + "push %%rax\n" + "push %4\n" + "lfence\n" + "swapgs\n" + "iretq" + : + : "r" (tfp->cs), + "i" (USER_DS | 3), + "r" (tfp->rsp), + "m" (tfp->rflags), + "r" (tfp->rip) + ); +} /* * MD proc init code @@ -40,6 +76,9 @@ int md_proc_init(struct proc *procp, int flags) { struct md_pcb *pcbp; + struct trapframe *tfp; + struct mmu_map spec; + uint8_t cs, ds; int error; if (procp == NULL) { @@ -51,5 +90,54 @@ md_proc_init(struct proc *procp, int flags) printf("md_proc_init: could not create new vas\n"); return error; } + + ds = USER_DS | 3; + cs = USER_CS | 3; + + /* + * Set up the mapping specifier, we'll use zero + * to allocate new pages. + */ + spec.pa = 0; + spec.va = STACK_TOP; + + /* Put the trapframe in a known state */ + tfp = &pcbp->tf; + memset(tfp, 0, sizeof(*tfp)); + tfp->rflags = 0x202; + tfp->cs = cs; + tfp->ss = ds; + + /* Map the stack */ + vm_map( + &pcbp->vas, &spec, + STACK_LEN, + PROT_READ + | PROT_WRITE + | PROT_USER + ); + + tfp->rsp = STACK_TOP; + return 0; +} + +/* + * Set process instruction pointer + */ +int +md_set_ip(struct proc *procp, uintptr_t ip) +{ + struct md_pcb *pcbp; + struct trapframe *tfp; + + if (procp == NULL) { + return -EINVAL; + } + + pcbp = &procp->pcb; + tfp = &pcbp->tf; + tfp->rip = ip; + mmu_write_vas(&procp->pcb.vas); + __proc_kick(tfp); return 0; } diff --git a/src/sys/include/sys/proc.h b/src/sys/include/sys/proc.h index deed09b..d09e459 100644 --- a/src/sys/include/sys/proc.h +++ b/src/sys/include/sys/proc.h @@ -34,6 +34,12 @@ #include #include /* standard */ +/* + * The stack starts here and grows down + */ +#define STACK_TOP 0xBFFFFFFF +#define STACK_LEN 4096 + /* * A process describes a running program image * on the system. @@ -69,4 +75,16 @@ int proc_init(struct proc *procp, int flags); */ int md_proc_init(struct proc *procp, int flags); +/* + * Set the instruction pointer field of a specific + * process + * + * @procp: Process to update + * @ip: Instruction pointer to write + * + * Returns zero on success, otherwise a less than + * zero value to indicate failure. + */ +int md_set_ip(struct proc *procp, uintptr_t ip); + #endif /* !_SYS_PROC_H_ */ -- cgit v1.2.3