summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/arch/amd64/os/os_proc.c86
-rw-r--r--src/sys/include/sys/proc.h18
2 files changed, 104 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..61ef51e 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,52 @@ 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;
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
@@ -35,6 +35,12 @@
#include <machine/pcb.h> /* 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_ */