Update to linuxemu syscall structure
authorZach Zimmerman <zpzimmerman@gmail.com>
Thu, 17 Aug 2017 23:06:51 +0000 (16:06 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 25 Aug 2017 17:02:56 +0000 (13:02 -0400)
Changed linuxemu to use array of function pointers
Changed dune test to use linuxemu by default
Modified linuxemu to use a shared library for syscall extensions

Signed-off-by: Zach Zimmerman <zpzimmerman@gmail.com>
Change-Id: Id4b7d86b5f9cc95b224ebe9e282a3973e80b9130
[ checkpatch warning ]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tests/dune/Makefrag
tests/dune/dune.c
user/vmm/include/vmm/linux_syscalls.h
user/vmm/include/vmm/linuxemu.h [new file with mode: 0644]
user/vmm/linuxemu.c

index 5cce02c..1d3801e 100644 (file)
@@ -4,11 +4,11 @@ DUNE_TESTS_CFLAGS += $(CFLAGS_TESTS) -Wunused -Werror
 
 ALL_DUNE_TEST_FILES := $(wildcard $(DUNE_TESTS_DIR)/*.c)
 
-DUNE_TESTS_LDLIBS := $(TESTS_LDLIBS) -lelf -liplib
+DUNE_TESTS_LDLIBS := $(TESTS_LDLIBS) -lelf -liplib -ldl
 
 DUNE_TESTS_SRCS := $(ALL_DUNE_TEST_FILES)
 
-DUNE_TESTS_LDDEPENDS := $(DUNE_TESTS_DIR)/%.c 
+DUNE_TESTS_LDDEPENDS := $(DUNE_TESTS_DIR)/%.c
 
 TESTS_EXECS_C  += $(patsubst $(DUNE_TESTS_DIR)/%.c, \
                       $(OBJDIR)/$(DUNE_TESTS_DIR)/%, \
index 78ee960..785b414 100644 (file)
@@ -28,7 +28,7 @@
 #include <sys/eventfd.h>
 #include <sys/uio.h>
 #include <err.h>
-
+#include <vmm/linuxemu.h>
 struct vmm_gpcore_init gpci;
 bool linuxemu(struct guest_thread *gth, struct vm_trapframe *tf);
 
@@ -51,10 +51,14 @@ 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 +68,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 +82,7 @@ static void show(char *s)
                return;
        }
        while (*s) {
-       //      xnum((uint64_t)s);pc(';');
-               pc(*s);
+               pc(s);
                s++;
        }
 }
@@ -88,8 +90,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,9 +127,6 @@ 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");
        hlt();
 }
 
@@ -341,28 +343,6 @@ 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;
@@ -429,6 +409,8 @@ int main(int argc, char **argv)
                usage();
        }
 
+       init_syscall_table();
+
        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",
@@ -480,7 +462,7 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       vm.gths[0]->vmcall = test ? testvmcall : linuxemu;
+       vm.gths[0]->vmcall = linuxemu;
        vm_tf = gth_to_vmtf(vm.gths[0]);
 
        /* we can't use the default stack since we set one up
index 045c756..99c45ce 100644 (file)
@@ -1,3 +1,7 @@
+#pragma once
+
+#define linux_max_syscall 311
+
 char *syscalls[] = {
 [0]    "DUNE_SYS_READ",
 [1]    "DUNE_SYS_WRITE",
diff --git a/user/vmm/include/vmm/linuxemu.h b/user/vmm/include/vmm/linuxemu.h
new file mode 100644 (file)
index 0000000..79b7062
--- /dev/null
@@ -0,0 +1,16 @@
+#pragma once
+
+typedef bool (*dune_syscall_t)(struct vm_trapframe *);
+
+struct dune_sys_table_entry {
+       dune_syscall_t call;
+       const char *name;
+};
+
+#define dune_max_syscall 1024
+
+struct dune_sys_table_entry dune_syscall_table[dune_max_syscall];
+
+void init_syscall_table(void);
+bool dune_sys_write(struct vm_trapframe *tf);
+bool dune_sys_read(struct vm_trapframe *tf);
index bd217e8..e6ac53c 100644 (file)
 #include <sys/syscall.h>
 #include <vmm/linux_syscalls.h>
 #include <sys/time.h>
+#include <vmm/linuxemu.h>
+#include <dlfcn.h>
+
+bool dune_sys_read(struct vm_trapframe *tf)
+{
+       int retval = read(tf->tf_rdi, (void *)tf->tf_rsi, (size_t)tf->tf_rdx);
+
+       if (retval == -1)
+               tf->tf_rax = -errno;
+       else
+               tf->tf_rax = retval;
+
+       return true;
+}
+
+bool dune_sys_write(struct vm_trapframe *tf)
+{
+       int retval = write(tf->tf_rdi, (void *)tf->tf_rsi, (size_t)tf->tf_rdx);
+
+       if (retval == -1)
+               tf->tf_rax = -errno;
+       else
+               tf->tf_rax = retval;
+
+       return true;
+}
+
+bool dune_sys_gettid(struct vm_trapframe *tf)
+{
+       tf->tf_rax = tf->tf_guest_pcoreid;
+       return true;
+}
+
+bool dune_sys_gettimeofday(struct vm_trapframe *tf)
+{
+       int retval = gettimeofday((struct timeval*)tf->tf_rdi,
+                                 (struct timezone*)tf->tf_rsi);
+       if (retval == -1)
+               tf->tf_rax = -errno;
+       else
+               tf->tf_rax = retval;
+
+       return true;
+}
+
+void init_syscall_table(void)
+{
+       int i;
+
+       for (i = 0; i < dune_max_syscall ; ++i) {
+               dune_syscall_table[i].call = NULL;
+               dune_syscall_table[i].name = "nosyscall";
+       }
+       // For now setup the syscalls here,
+       // there is probably a better way to do this.
+       dune_syscall_table[DUNE_SYS_WRITE].call = dune_sys_write;
+       dune_syscall_table[DUNE_SYS_WRITE].name = syscalls[DUNE_SYS_WRITE];
+       dune_syscall_table[DUNE_SYS_GETTID].call = dune_sys_gettid;
+       dune_syscall_table[DUNE_SYS_GETTID].name = syscalls[DUNE_SYS_GETTID];
+       dune_syscall_table[DUNE_SYS_GETTIMEOFDAY].call = dune_sys_gettimeofday;
+       dune_syscall_table[DUNE_SYS_GETTIMEOFDAY].name =
+               syscalls[DUNE_SYS_GETTIMEOFDAY];
+       dune_syscall_table[DUNE_SYS_READ].call = dune_sys_read;
+       dune_syscall_table[DUNE_SYS_READ].name = syscalls[DUNE_SYS_READ];
+       if (dlopen("liblinuxemu_extend.so", RTLD_NOW) == NULL)
+               fprintf(stderr, "Not using any syscall extensions\n Reason: %s\n",
+                       dlerror());
+
+}
+
 
 /* TODO: have an array which classifies syscall args
  * and "special" system calls (ones with weird return
@@ -32,29 +102,17 @@ linuxemu(struct guest_thread *gth, struct vm_trapframe *tf)
                tf->tf_rcx, tf->tf_r8, tf->tf_r9);
 
        tf->tf_rip += 3;
-       /* we don't do tic/tou checking here yet. */
-       switch (tf->tf_rax) {
-       default:
-               /* TODO: just return the error to the guest once we are done
-                * debugging this. */
+
+       if (tf->tf_rax >= dune_max_syscall) {
+               fprintf(stderr, "System call %d is out of range\n", tf->tf_rax);
+               return false;
+       }
+
+
+       if (dune_syscall_table[tf->tf_rax].call == NULL) {
                fprintf(stderr, "System call %d is not implemented\n", tf->tf_rax);
-               //tf->tf_rax = -ENOSYS;
-               break;
-       case DUNE_SYS_GETTIMEOFDAY:
-               tf->tf_rax = gettimeofday((struct timeval*)tf->tf_rdi,
-                                         (struct timezone*)tf->tf_rsi);
-               ret = true;
-               break;
-       case DUNE_SYS_GETTID:
-               tf->tf_rax = 1;
-               ret = true;
-               break;
-       case DUNE_SYS_WRITE:
-               /* debug: write to stdout too for now. */
-               write(2, (void *)tf->tf_rsi, (size_t)tf->tf_rdx);
-               tf->tf_rax = write(tf->tf_rdi, (void *)tf->tf_rsi, (size_t)tf->tf_rdx);
-               ret = true;
-               break;
+               return false;
        }
-       return ret;
+
+       return (dune_syscall_table[tf->tf_rax].call)(tf);
 }