Modify device to take a binary struct.
authorRonald G. Minnich <rminnich@gmail.com>
Thu, 30 Jul 2015 16:36:34 +0000 (09:36 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 2 Nov 2015 23:24:25 +0000 (18:24 -0500)
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/vmm/intel/vmx.c
kern/arch/x86/vmm/vmm.c
kern/arch/x86/vmm/vmm.h
kern/drivers/dev/cons.c
kern/include/ros/vmm.h
kern/kfs/bin/TIMER [new file with mode: 0644]
tests/vmm/vmrunkernel.c

index 41982d0..ae634bd 100644 (file)
@@ -93,8 +93,8 @@
  * We divide this into two things: vmm_proc_init and vm_run.
  * Currently, on Intel, vmm_proc_init does nothing.
  *
- * vm_run is really complicated. It is called with a coreid, rip, rsp,
- * cr3, and flags.  On intel, it calls vmx_launch. vmx_launch is set
+ * vm_run is really complicated. It is called with a coreid, and
+ * vmctl struct. On intel, it calls vmx_launch. vmx_launch is set
  * up for a few test cases. If rip is 1, it sets the guest rip to
  * a function which will deref 0 and should exit with failure 2. If rip is 0,
  * it calls an infinite loop in the guest.
@@ -1803,7 +1803,7 @@ static int vmx_handle_nmi_exception(struct vmx_vcpu *vcpu) {
  * vmx_launch - the main loop for a VMX Dune process
  * @conf: the launch configuration
  */
-int vmx_launch(uint64_t rip, uint64_t rsp, uint64_t cr3) {
+int vmx_launch(struct vmctl *v) {
        int ret;
        struct vmx_vcpu *vcpu;
        int errors = 0;
@@ -1822,14 +1822,28 @@ int vmx_launch(uint64_t rip, uint64_t rsp, uint64_t cr3) {
         * core is the KERN_GS_BASE). */
        rdmsrl(MSR_KERNEL_GS_BASE, vcpu->msr_autoload.host[0].value);
        /* if cr3 is set, means 'set everything', else means 'start where you left off' */
-       if (cr3) {
-               vmx_get_cpu(vcpu);
-               vmcs_writel(GUEST_RIP, rip);
-               vmcs_writel(GUEST_RSP, rsp);
-               vmcs_writel(GUEST_CR3, cr3);
-               vmx_put_cpu(vcpu);
+       vmx_get_cpu(vcpu);
+       switch(v->command) {
+       case REG_ALL:
+               printk("REG_ALL\n");
+               // fallthrough
+               vcpu->regs = v->regs;
+       case REG_RSP_RIP_CR3:
+               printk("REG_RSP_RIP_CR3\n");
+               vmcs_writel(GUEST_RSP, v->regs.tf_rsp);
+               vmcs_writel(GUEST_CR3, v->cr3);
+               // fallthrough
+       case REG_RIP:
+               printk("REG_RIP\n");
+               vmcs_writel(GUEST_RIP, v->regs.tf_rip);
+               break;
+       case RESUME:
+               printk("RESUME\n");
+               break;
+       default: 
+               error(EINVAL, "Bad command in vmx_launch");
        }
-
+       vmx_put_cpu(vcpu);
        vcpu->ret_code = -1;
 
        while (1) {
@@ -1919,6 +1933,7 @@ int vmx_launch(uint64_t rip, uint64_t rsp, uint64_t cr3) {
 
        printd("RETURN. ip %016lx sp %016lx\n",
               vcpu->regs.tf_rip, vcpu->regs.tf_rsp);
+       v->regs = vcpu->regs;
 //  hexdump((void *)vcpu->regs.tf_rsp, 128 * 8);
        /*
         * Return both the reason for the shutdown and a status value.
index 34428af..8c97606 100644 (file)
@@ -57,13 +57,13 @@ void vmm_pcpu_init(void)
        printk("vmm_pcpu_init failed\n");
 }
 
-int vm_run(uint64_t rip, uint64_t rsp, uint64_t cr3)
+int vm_run(struct vmctl *v)
 {
-       int vmx_launch(uint64_t rip, uint64_t rsp, uint64_t cr3);
+       int vmx_launch(struct vmctl *v);
        if (current->vmm.amd) {
                return -1;
        } else {
-               return vmx_launch(rip, rsp, cr3);
+               return vmx_launch(v);
        }
        return -1;
 }
index 26a9060..d1965fb 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _VMM_H_
 #define        _VMM_H_
 
+#include <ros/vmm.h>
+
 static inline int cpu_has_vmx(void)
 {
        unsigned long ecx = cpuid_ecx(1);
@@ -45,7 +47,7 @@ void vmm_pcpu_init(void);
 int vmm_struct_init(struct proc *p, unsigned int nr_guest_pcores, int flags);
 void __vmm_struct_cleanup(struct proc *p);
 
-int vm_run(uint64_t,uint64_t, uint64_t);
+int vm_run(struct vmctl *);
 int intel_vmx_start(int id);
 int intel_vmx_setup(int nvmcs);
 
index 045ef7d..27431aa 100644 (file)
@@ -39,6 +39,7 @@
 #include <pmap.h>
 #include <smp.h>
 #include <ip.h>
+#include <ros/vmm.h>
 
 struct dev consdevtab;
 
@@ -529,6 +530,7 @@ enum {
        Qdir,
        Qcons,
        Qsysctl,
+       Qvmctl,
        Qconsctl,
        Qdrivers,
        Qhostowner,
@@ -552,6 +554,7 @@ static struct dirtab consdir[] = {
        {"cons", {Qcons}, 0, 0660},
        {"consctl", {Qconsctl}, 0, 0220},
        {"sysctl", {Qsysctl}, 0, 0666},
+       {"vmctl", {Qvmctl}, 0, 0666},
        {"drivers", {Qdrivers}, 0, 0444},
        {"hostowner", {Qhostowner}, 0, 0644},
        {"keyboard", {Qkeyboard}, 0, 0666},
@@ -872,7 +875,7 @@ static long consread(struct chan *c, void *buf, long n, int64_t offset)
                        poperror();
                        return n;
                case Qklog:
-                       //return qread(klogq, buf, n);  
+                       //return qread(klogq, buf, n);
                        /* the queue gives us some elasticity for log reading. */
                        if (!logqueue)
                                logqueue = qopen(1 << 20, 0, 0, 0);
@@ -919,6 +922,7 @@ static long conswrite(struct chan *c, void *va, long n, int64_t offset)
        int x;
        uint64_t rip, rsp, cr3, flags, vcpu;
        int ret;
+       struct vmctl vmctl;
 
        switch ((uint32_t) c->qid.path) {
 #if 0
@@ -1034,10 +1038,17 @@ static long conswrite(struct chan *c, void *va, long n, int64_t offset)
                        kstrdup(&sysname, buf);
                        break;
 #endif
+               case Qvmctl:
+                       memmove(&vmctl, a, sizeof(vmctl));
+                       ret = vm_run(&vmctl);
+                       printd("vm_run returns %d\n", ret);
+                       n = ret;
+                       memmove(a, &vmctl, sizeof(vmctl));
+                       break;
                case Qsysctl:
                        //if (!iseve()) error(EPERM, NULL);
                        cb = parsecmd(a, n);
-                       if (cb->nf > 1) 
+                       if (cb->nf > 1)
                        printd("cons sysctl cmd %s\n", cb->f[0]);
                        if (waserror()) {
                                kfree(cb);
@@ -1063,10 +1074,23 @@ static long conswrite(struct chan *c, void *va, long n, int64_t offset)
                                        keepbroken = 0;
                                        break;
                                case CMV:
+                                       /* it's ok to throw away this struct each time;
+                                        * this is stateless and going away soon anyway.
+                                        * we only kept it here until we can rewrite all the
+                                        * tests
+                                        */
                                        rip =  strtoul(cb->f[1], NULL, 0);
                                        rsp =  strtoul(cb->f[2], NULL, 0);
                                        cr3 =  strtoul(cb->f[3], NULL, 0);
-                                       ret = vm_run(rip, rsp, cr3);
+                                       if (cr3) {
+                                               vmctl.command = REG_RSP_RIP_CR3;
+                                               vmctl.cr3 = cr3;
+                                               vmctl.regs.tf_rip = rip;
+                                               vmctl.regs.tf_rsp = rsp;
+                                       } else {
+                                               vmctl.command = RESUME;
+                                       }
+                                       ret = vm_run(&vmctl);
                                        printd("vm_run returns %d\n", ret);
                                        n = ret;
                                        break;
index 309e9f8..1bf2bd0 100644 (file)
 #define        VMM_VMCALL_PRINTF       0x1     /* Enable VMCALL output console hack */
 
 #define VMM_ALL_FLAGS  (VMM_VMCALL_PRINTF)
+
+enum {
+       RESUME,
+       REG_RSP_RIP_CR3,
+       REG_RIP,
+       REG_ALL,
+};
+
+/* eventually, this is a system call. For now, it's #c/vmctl.
+ * You fill in the blanks, and write the struct to #c/vmctl.
+ * On return, i.e. vmexit, it's updated with the new values.
+ */
+struct vmctl {
+       uint64_t command;
+       uint64_t cr3;
+       struct hw_trapframe regs;
+};
+
 #endif /* ROS_INC_VMM_H */
diff --git a/kern/kfs/bin/TIMER b/kern/kfs/bin/TIMER
new file mode 100644 (file)
index 0000000..3a05291
--- /dev/null
@@ -0,0 +1,5 @@
+echo optimer period 1000000 > /prof/kpctl
+echo optimer all on > /prof/kpctl
+
+
+
index 5ea9e5b..c903d2a 100644 (file)
@@ -22,6 +22,7 @@
 int *mmap_blob;
 unsigned long long stack[1024];
 volatile int shared = 0;
+volatile int quit = 0;
 int mcp = 1;
 
 #define MiB 0x100000u
@@ -113,6 +114,7 @@ void *talk_thread(void *arg)
        uint32_t vv;
        int i;
        int num;
+       return;
        printf("Sleep 15 seconds\n");
        uthread_sleep(15);
        printf("----------------------- TT a %p\n", a);
@@ -129,7 +131,7 @@ void *talk_thread(void *arg)
        }
        if (debug)printf("vv %x, set selector %x\n", vv, read32(v + VIRTIO_MMIO_DRIVER_FEATURES_SEL));
        if (debug) printf("loop forever");
-       while (1)
+       while (! quit)
                ;
        for(num = 0;;num++) {
                /* host: use any buffers we should have been sent. */
@@ -175,11 +177,12 @@ struct ttargs t;
 
 int main(int argc, char **argv)
 {
+       struct vmctl vmctl;
        int amt;
        int vmmflags = VMM_VMCALL_PRINTF;
        uint64_t entry = 0x1000000, kerneladdress = 0x1000000;
        int nr_gpcs = 1;
-       int fd = open("#cons/sysctl", O_RDWR), ret;
+       int fd = open("#c/vmctl", O_RDWR), ret;
        void * x;
        int kfd = -1;
        static char cmd[512];
@@ -312,7 +315,10 @@ int main(int argc, char **argv)
        hexdump(stdout, (void *)VIRTIOBASE, 128);
        printf("kernbase for pml4 is 0x%llx and entry is %llx\n", kernbase, entry);
        printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
-       sprintf(cmd, "V 0x%llx 0x%llx 0x%llx", entry, (unsigned long long) &stack[1024], (unsigned long long) p512);
+       vmctl.command = REG_RSP_RIP_CR3;
+       vmctl.cr3 = (uint64_t) p512;
+       vmctl.regs.tf_rip = entry;
+       vmctl.regs.tf_rsp = (uint64_t) &stack[1024];
        if (mcp) {
                if (pthread_create(&my_threads[0], NULL, &talk_thread, &t))
                        perror("pth_create failed");
@@ -320,25 +326,27 @@ int main(int argc, char **argv)
        printf("threads started\n");
        printf("Writing command :%s:\n", cmd);
        // sys_getpcoreid
-       ret = write(fd, cmd, strlen(cmd));
-       if (ret != strlen(cmd)) {
+       ret = write(fd, &vmctl, sizeof(vmctl));
+       if (ret != sizeof(vmctl)) {
                perror(cmd);
        }
-       sprintf(cmd, "V 0 0 0");
+       vmctl.command = RESUME;
        while (1) {
                int c;
                printf("RESUME?\n");
                c = getchar();
                if (c == 'q')
                        break;
-               ret = write(fd, cmd, strlen(cmd));
-               if (ret != strlen(cmd)) {
+               ret = write(fd, &vmctl, sizeof(vmctl));
+               if (ret != sizeof(vmctl)) {
                        perror(cmd);
                }
+               printf("RIP %p\n", vmctl.regs.tf_rip);
        }
        dumpvirtio_mmio(stdout, (void *)VIRTIOBASE);
        printf("shared is %d, blob is %d\n", shared, *mmap_blob);
 
+       quit = 1;
        for (int i = 0; i < nr_threads-1; i++) {
                int ret;
                if (pthread_join(my_threads[i], &my_retvals[i]))