vmm: Added more syscalls and helpers to linuxemu
[akaros.git] / tests / dune / dune.c
index 78ee960..94e0f90 100644 (file)
 #include <sys/eventfd.h>
 #include <sys/uio.h>
 #include <err.h>
+#include <vmm/linuxemu.h>
+#include <vmm/vmm.h>
+#include <vmm/vthread.h>
 
 struct vmm_gpcore_init gpci;
 bool linuxemu(struct guest_thread *gth, struct vm_trapframe *tf);
 
-/* ah, elf. */
-struct elf_aux {
-       unsigned long v[2];
-};
 
 extern char **environ;
 
-static struct virtual_machine vm = {.halt_exit = true,};
+static struct virtual_machine vm = {.halt_exit = true,
+                                    .mtx = UTH_MUTEX_INIT,
+                                    .vmcall = linuxemu};
 
 static unsigned long long memsize = GiB;
 static uintptr_t memstart = MinMemory;
 
-static int debug;
+static int dune_debug;
 
 static void hlt(void)
 {
        __asm__ __volatile__("\thlt\n\t");
 }
 
-static int pc(uint16_t c)
+static int pc(char *c)
 {
-       __asm__ __volatile__("movw $0, %%rax\nmovw %0, %%di\n\tvmcall\n" ::
-                            "m"(c) : "rdi", "rax");
+       __asm__ __volatile__("movq $1, %%rax\n"
+                            "movq $1, %%rdi\n"
+                            "movq %0, %%rsi\n"
+                            "movq $1, %%rdx\n"
+                            "vmcall\n" ::
+                            "m"(c) : "rdi", "rax", "rsi", "rdx");
        return 0;
 }
 
@@ -64,9 +69,8 @@ static void xnum(uint64_t x)
 
        for (int i = 0; i < 8; i++) {
                uint8_t v = ((uint8_t*)&x)[7 - i];
-
-               pc(hex[v >> 4]);
-               pc(hex[v & 0xf]);
+               pc(&hex[v >> 4]);
+               pc(&hex[v & 0xf]);
        }
 }
 
@@ -79,8 +83,7 @@ static void show(char *s)
                return;
        }
        while (*s) {
-       //      xnum((uint64_t)s);pc(';');
-               pc(*s);
+               pc(s);
                s++;
        }
 }
@@ -88,8 +91,11 @@ static void show(char *s)
 /* This is a small test that runs in gr0 and tests our argument setup.
  * This test can grow in capability as we find more broken bits in our
  * dune-like environment. */
+
 void dune_test(void *stack)
 {
+       show("Hello this is dune's test\n");
+
        int argc;
        char **argv;
        struct elf_aux *auxv;
@@ -122,136 +128,15 @@ void dune_test(void *stack)
                xnum(auxv[i].v[1]); show("\n");
        }
        show("Done dumping [argv, env, auxv]\n");
-       __asm__ __volatile__("movl $0xdeadbeef, %eax\nmovq $1, %rdi\nmov $2,"
-                            "%rsi\nmovq $3, %rdx\n"
-                            "movq $4,%rcx\nmovq $5, %r8\nmovq $6,%r9\nvmcall\n");
+       show("Testing syscall extensions\n");
+       __asm__ __volatile__("movq $400, %%rax\n"
+                            "vmcall\n" :: );
        hlt();
 }
 
-/* populate_stack fills the stack with an argv, envp, and auxv.
- * We assume the stack pointer is backed by real memory.
- * It will go hard with you if it does not. For your own health,
- * stack should be 16-byte aligned. */
-void *populate_stack(uintptr_t *stack, int argc, char *argv[],
-                         int envc, char *envp[],
-                         int auxc, struct elf_aux auxv[])
-{
-       /* Function to get the lengths of the argument and environment strings. */
-       int get_lens(int argc, char *argv[], int arg_lens[])
-       {
-               int total = 0;
-
-               if (!argc)
-                       return 0;
-               for (int i = 0; i < argc; i++) {
-                       arg_lens[i] = strlen(argv[i]) + 1;
-                       total += arg_lens[i];
-               }
-               return total;
-       }
-
-       /* Function to help map the argument and environment strings, to their
-        * final location. */
-       int remap(int argc, char *argv[], char *new_argv[],
-              char new_argbuf[], int arg_lens[])
-       {
-               int offset = 0;
-
-               if (!argc)
-                       return 0;
-               for (int i = 0; i < argc; i++) {
-                       memcpy(new_argbuf + offset, argv[i], arg_lens[i]);
-                       if (debug) {
-                               fprintf(stderr, "data: memcpy(%p, %p, %ld)\n",
-                                       new_argbuf + offset, argv[i], arg_lens[i]);
-                               fprintf(stderr, "arg: set arg %d, @%p, to %p\n", i,
-                                       &new_argv[i], new_argbuf + offset);
-                       }
-                       new_argv[i] = new_argbuf + offset;
-                       offset += arg_lens[i];
-               }
-               new_argv[argc] = NULL;
-               return offset;
-       }
-
-       /* Start tracking the size of the buffer necessary to hold all of our data
-        * on the stack. Preallocate space for argc, argv, envp, and auxv in this
-        * buffer. */
-       int bufsize = 0;
-
-       bufsize += 1 * sizeof(size_t);
-       bufsize += (auxc + 1) * sizeof(struct elf_aux);
-       bufsize += (envc + 1) * sizeof(char**);
-       bufsize += (argc + 1) * sizeof(char**);
-       if (debug)
-               fprintf(stderr, "Bufsize for pointers and argc is %d\n", bufsize);
-
-       /* Add in the size of the env and arg strings. */
-       int arg_lens[argc];
-       int env_lens[envc];
-
-       bufsize += get_lens(argc, argv, arg_lens);
-       bufsize += get_lens(envc, envp, env_lens);
-       if (debug)
-               fprintf(stderr, "Bufsize for pointers, argc, and strings is %d\n",
-                       bufsize);
-
-       /* Adjust bufsize so that our buffer will ultimately be 16 byte aligned. */
-       bufsize = (bufsize + 15) & ~0xf;
-       if (debug)
-               fprintf(stderr,
-                       "Bufsize for pointers, argc, and strings is rounded is %d\n",
-                       bufsize);
-
-       /* Set up pointers to all of the appropriate data regions we map to. */
-       size_t *new_argc = (size_t*)((uint8_t*)stack - bufsize);
-       char **new_argv = (char**)(new_argc + 1);
-       char **new_envp = new_argv + argc + 1;
-       struct elf_aux *new_auxv = (struct elf_aux*)(new_envp + envc + 1);
-       char *new_argbuf = (char*)(new_auxv + auxc + 1);
-
-       if (debug) {
-               fprintf(stderr, "There are %d args, %d env, and %d aux\n", new_argc,
-                       envc, auxc);
-               fprintf(stderr, "Locations: argc: %p, argv: %p, envp: %p, auxv: %p\n",
-                               new_argc, new_argv, new_envp, new_auxv);
-               fprintf(stderr, "Locations: argbuf: %p, ", new_argbuf);
-               fprintf(stderr, "Sizeof argc is %d\n", sizeof(size_t));
-       }
-       /* Map argc into its final location. */
-       *new_argc = argc;
-
-       /* Map all data for argv and envp into its final location. */
-       int offset = 0;
-
-       offset = remap(argc, argv, new_argv, new_argbuf, arg_lens);
-       if (offset == -1)
-               return 0;
-       if (debug) {
-               fprintf(stderr, "Locations: argbuf: %p, envbuf: %p, ", new_argbuf,
-                       new_argbuf + offset);
-
-       }
-       offset = remap(envc, envp, new_envp, new_argbuf + offset, env_lens);
-       if (offset == -1)
-               return 0;
-
-       /* Map auxv into its final location. */
-       struct elf_aux null_aux = {0, 0};
-
-       memcpy(new_auxv, auxv, auxc * sizeof(struct elf_aux));
-       memcpy(new_auxv + auxc, &null_aux, sizeof(struct elf_aux));
-       if (debug) {
-               fprintf(stderr, "auxbuf: %p\n", new_auxv);
-               hexdump(stdout, new_auxv, auxc * sizeof(struct elf_aux));
-       }
-       return (uint8_t*)stack - bufsize;
-}
-
 static struct option long_options[] = {
        {"aux",           required_argument, 0, 'a'},
        {"debug",         no_argument,       0, 'd'},
-       {"vmmflags",      required_argument, 0, 'v'},
        {"memsize",       required_argument, 0, 'm'},
        {"memstart",      required_argument, 0, 'M'},
        {"cmdline_extra", required_argument, 0, 'c'},
@@ -291,7 +176,7 @@ getextra(int *auxc, char *_s)
        char *auxpairs[32];
 
        *auxc = gettokens(s, auxpairs, 32, ",");
-       if (debug)
+       if (dune_debug)
                fprintf(stderr, "Found %d extra aux pairs\n", *auxc);
        if (*auxc < 1)
                return NULL;
@@ -314,7 +199,7 @@ getextra(int *auxc, char *_s)
                v = strtoul(aux[1], 0, 0);
                auxv[i].v[0] = t;
                auxv[i].v[1] = v;
-               if (debug)
+               if (dune_debug)
                        fprintf(stderr, "Adding aux pair 0x%x:0x%x\n", auxv[i].v[0],
                                auxv[i].v[1]);
        }
@@ -332,7 +217,7 @@ buildaux(struct elf_aux *base, int basec, struct elf_aux *extra, int extrac)
        if (!ret)
                return NULL;
 
-       if (debug)
+       if (dune_debug)
                fprintf(stderr, "buildaux: consolidating %d aux and %d extra\n",
                        basec, extrac);
        /* TOOD: check for dups. */
@@ -341,37 +226,14 @@ buildaux(struct elf_aux *base, int basec, struct elf_aux *extra, int extrac)
        return ret;
 }
 
-static bool
-testvmcall(struct guest_thread *gth, struct vm_trapframe *tf)
-{
-       uintptr_t rax = tf->tf_rax;
-
-       switch (rax) {
-       default:
-               fprintf(stderr, "testvmcall: gth %p tf %p\n", gth, tf);
-               fprintf(stderr, "args should be 1, 2, 3, 4, 5, 6:\n");
-               fprintf(stderr, "%p %p %p %p %p %p\n",
-                       tf->tf_rdi, tf->tf_rsi, tf->tf_rdx,
-                       tf->tf_rcx, tf->tf_r8, tf->tf_r9);
-               fprintf(stderr, "RAX should be deadbeef: 0x%x\n", rax);
-               break;
-       case 0:
-               write(1, &tf->tf_rdi, 1);
-               break;
-       }
-       tf->tf_rip += 3;
-       return true;
-}
-
 int main(int argc, char **argv)
 {
        void *tos;
        int envc, auxc, extrac = 0;
        struct elf_aux *auxv, *extra = NULL;
-       int vmmflags = 0;
        uint64_t entry = 0;
-       int ret;
-       struct vm_trapframe *vm_tf;
+       struct vthread *vth;
+       struct vmm_gpcore_init gpci[1];
        int c;
        int test = 0;
        int option_index;
@@ -392,15 +254,12 @@ int main(int argc, char **argv)
                switch (c) {
                case 'a':
                        extra = getextra(&extrac, optarg);
-                       if (debug)
+                       if (dune_debug)
                                fprintf(stderr, "Added %d aux items\n", extrac);
                        break;
                case 'd':
                        fprintf(stderr, "SET DEBUG\n");
-                       debug++;
-                       break;
-               case 'v':
-                       vmmflags = strtoull(optarg, 0, 0);
+                       dune_debug++;
                        break;
                case 'm':
                        memsize = strtoull(optarg, 0, 0);
@@ -429,6 +288,9 @@ int main(int argc, char **argv)
                usage();
        }
 
+       init_lemu_logging(dune_debug);
+       init_linuxemu();
+
        if ((uintptr_t)(memstart + memsize) >= (uintptr_t)BRK_START) {
                fprintf(stderr,
                        "memstart 0x%lx memsize 0x%lx -> 0x%lx is too large; overlaps BRK_START at %p\n",
@@ -438,7 +300,7 @@ int main(int argc, char **argv)
 
        mmap_memory(&vm, memstart, memsize);
 
-       if (debug)
+       if (dune_debug)
                fprintf(stderr, "mmap guest physical memory at %p for 0x%lx bytes\n",
                        memstart, memsize);
 
@@ -458,7 +320,7 @@ int main(int argc, char **argv)
        auxc = auxc + extrac;
 
        if (!test) {
-               entry = load_elf(argv[0], MinMemory);
+               entry = load_elf(argv[0], MinMemory, NULL, NULL);
                if (entry == 0) {
                        fprintf(stderr, "Unable to load kernel %s\n", argv[0]);
                        exit(1);
@@ -467,29 +329,20 @@ int main(int argc, char **argv)
                fprintf(stderr, "Running dune test\n");
                entry = (uintptr_t) dune_test;
        }
-       if (debug)
+       if (dune_debug)
                fprintf(stderr, "Test: Populate stack at %p\n", tos);
        tos = populate_stack(tos, ac, av, envc, environ, auxc, auxv);
-       if (debug)
+       if (dune_debug)
                fprintf(stderr, "populated stack at %p; argc %d, envc %d, auxc %d\n",
                        tos, ac, envc, auxc);
 
-       ret = vthread_attr_init(&vm, vmmflags);
-       if (ret) {
-               fprintf(stderr, "vmm_init failed: %r\n");
-               exit(1);
-       }
-
-       vm.gths[0]->vmcall = test ? testvmcall : linuxemu;
-       vm_tf = gth_to_vmtf(vm.gths[0]);
-
-       /* we can't use the default stack since we set one up
-        * ourselves. */
-       vm_tf->tf_rsp = (uint64_t)tos;
-       if (debug)
+       if (dune_debug)
                fprintf(stderr, "stack is %p\n", tos);
 
-       vthread_create(&vm, 0, (void *)entry, tos);
+       gpci_init(gpci);
+       vth = vthread_alloc(&vm, gpci);
+       vthread_init_ctx(vth, entry, (uintptr_t)tos, (uintptr_t)tos);
+       vthread_run(vth);
 
        uthread_sleep_forever();
        return 0;