diff options
author | Ian Moffett <ian@osmora.org> | 2025-09-16 20:53:43 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-09-16 20:53:43 -0400 |
commit | e3fba3a2fc865a5b4d6fa622fd383b6d612e8c85 (patch) | |
tree | 36a0309a727b315a912e771d71a3a06b40a3e395 /src/sys/arch/amd64 | |
parent | 3ed526d5ae90130bcc8e12c53d970c503eab9004 (diff) |
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 <ian@osmora.org>
Diffstat (limited to 'src/sys/arch/amd64')
-rw-r--r-- | src/sys/arch/amd64/os/os_proc.c | 88 |
1 files changed, 88 insertions, 0 deletions
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 <sys/errno.h> #include <sys/proc.h> #include <sys/syslog.h> +#include <sys/cdefs.h> #include <vm/mmu.h> +#include <vm/map.h> #include <machine/pcb.h> +#include <machine/gdt.h> +#include <machine/frame.h> +#include <string.h> + +/* + * 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; } |