Demo code to set up a VMMCP, including #c access
authorRon Minnich <rminnich@gmail.com>
Thu, 12 Mar 2015 20:55:12 +0000 (13:55 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 17 Mar 2015 14:55:59 +0000 (10:55 -0400)
This correctly starts a VMMCP as an 'unrestricted guest'.

Next step is to handle the resulting EPT page fault, which exits the vm with
error 0x21.

(git-fu'd by brho)

kern/drivers/dev/cons.c
tests/vmmcp.c [new file with mode: 0644]

index 07b6b1d..16ae518 100644 (file)
 
 extern char *eve;
 /* much stuff not ready yet. */
-#if 0
+
 extern int cflag;
-extern int keepbroken;
 
+/* this would be good to have; when processes die, keep them around so we can
+ * debug them.
+ */
+int keepbroken;
+
+#if 0
 void (*serwrite) (char *, int);
 
 struct queue *kscanq;                  /* keyboard raw scancodes (when needed) */
@@ -60,6 +65,7 @@ enum {
        CMbroken,
        CMnobroken,
        CMconsole,
+       CMV,
 };
 
 static struct cmdtab sysctlcmd[] = {
@@ -69,6 +75,7 @@ static struct cmdtab sysctlcmd[] = {
        {CMconsole, "console", 1},
        {CMbroken, "broken", 0},
        {CMnobroken, "nobroken", 0},
+       {CMV, "V", 4},
 };
 
 void printinit(void)
@@ -510,7 +517,7 @@ static struct dirtab consdir[] = {
        {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0555},
        {"cons", {Qcons}, 0, 0660},
        {"consctl", {Qconsctl}, 0, 0220},
-       {"sysctl", {Qsysctl}, 0, 0644},
+       {"sysctl", {Qsysctl}, 0, 0666},
        {"drivers", {Qdrivers}, 0, 0444},
        {"hostowner", {Qhostowner}, 0, 0644},
        {"keyboard", {Qkeyboard}, 0, 0666},
@@ -875,12 +882,15 @@ static long conswrite(struct chan *c, void *va, long n, int64_t offset)
 {
        ERRSTACK(1);
        int64_t t;
+       uint64_t ip;
        long l, bp;
        char *a = va;
        struct cmdbuf *cb;
        struct cmdtab *ct;
        char buf[256];
        int x;
+       uint64_t rip, rsp, cr3, flags, vcpu;
+       int ret;
 
        switch ((uint32_t) c->qid.path) {
 #if 0
@@ -995,11 +1005,12 @@ static long conswrite(struct chan *c, void *va, long n, int64_t offset)
                                buf[n - 1] = 0;
                        kstrdup(&sysname, buf);
                        break;
-
+#endif
                case Qsysctl:
-                       if (!iseve())
-                               error(Eperm);
+                       //if (!iseve()) error(Eperm);
                        cb = parsecmd(a, n);
+                       if (cb->nf > 1) 
+                       printk("cons sysctl cmd %s\n", cb->f[0]);
                        if (waserror()) {
                                kfree(cb);
                                nexterror();
@@ -1010,12 +1021,12 @@ static long conswrite(struct chan *c, void *va, long n, int64_t offset)
                                        reboot();
                                        break;
                                case CMhalt:
-                                       halt();
+                                       cpu_halt();
                                        break;
                                case CMpanic:
                                        panic("sysctl");
-                               case CMconsole:
-                                       consoleprint = strcmp(cb->f[1], "off") != 0;
+                                       //case CMconsole:
+                                       //consoleprint = strcmp(cb->f[1], "off") != 0;
                                        break;
                                case CMbroken:
                                        keepbroken = 1;
@@ -1023,11 +1034,23 @@ static long conswrite(struct chan *c, void *va, long n, int64_t offset)
                                case CMnobroken:
                                        keepbroken = 0;
                                        break;
+                               case CMV:
+                                       rip =  strtoul(cb->f[1], NULL, 0);
+                                       rsp =  strtoul(cb->f[2], NULL, 0);
+                                       cr3 =  strtoul(cb->f[3], NULL, 0);
+                                       disable_irq();
+                                       ret = vm_run(rip, rsp, cr3);
+                                       enable_irq();
+                                       printk("vm_run returns %d\n", ret);
+                                       return ret;
+       
+                                       ip = strtoul(cb->f[1], 0, 0);
+                                       //                      vm_run(ip);
+                                       break;
                        }
                        poperror();
                        kfree(cb);
                        break;
-#endif
                default:
                        printd("conswrite: %llu\n", c->qid.path);
                        error(Egreg);
diff --git a/tests/vmmcp.c b/tests/vmmcp.c
new file mode 100644 (file)
index 0000000..acd67d3
--- /dev/null
@@ -0,0 +1,58 @@
+#include <stdio.h> 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <arch/arch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ros/syscall.h>
+
+unsigned long stack[1024];
+
+static void fail(void)
+{
+       __asm__ __volatile__("mov $0xdeadbeef, %rbx; mov 5, %rax\n");
+}
+
+unsigned long long *p512, *p1, *p2m;
+
+int main(int argc, char **argv)
+{
+       int fd = open("#c/sysctl", O_RDWR), ret;
+       static char cmd[512];
+       if (fd < 0) {
+               perror("#c/sysctl");
+               exit(1);
+       }
+       ret = syscall(33, 1);
+       if (ret < 0) {
+               perror("vm setup");
+               exit(1);
+       }
+       ret = posix_memalign((void **)&p512, 4096, 3*4096);
+       if (ret) {
+               perror("ptp alloc");
+               exit(1);
+       }
+       p1 = &p512[512];
+       p2m = &p512[1024];
+       p512[0] = (unsigned long long)p1 | 7;
+       p1[0] = /*0x87; */(unsigned long long)p2m | 7;
+       p2m[0] = 0x87;
+       p2m[1] = 0x200000 | 0x87;
+       p2m[2] = 0x400000 | 0x87;
+       p2m[3] = 0x600000 | 0x87;
+
+       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%x 0x%x 0x%x", (unsigned long long)fail, (unsigned long long) stack, (unsigned long long) p512);
+       printf("Writing command :%s:\n", cmd);
+       ret = write(fd, cmd, strlen(cmd));
+       if (ret != strlen(cmd)) {
+               perror(cmd);
+       }
+       
+       return 0;
+}