Update to linuxemu syscall structure 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>
diff --git a/tests/dune/Makefrag b/tests/dune/Makefrag index 5cce02c..1d3801e 100644 --- a/tests/dune/Makefrag +++ b/tests/dune/Makefrag
@@ -4,11 +4,11 @@ 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)/%, \
diff --git a/tests/dune/dune.c b/tests/dune/dune.c index 78ee960..785b414 100644 --- a/tests/dune/dune.c +++ b/tests/dune/dune.c
@@ -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 @@ __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 @@ 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 @@ return; } while (*s) { - // xnum((uint64_t)s);pc(';'); - pc(*s); + pc(s); s++; } } @@ -88,8 +90,11 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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
diff --git a/user/vmm/include/vmm/linux_syscalls.h b/user/vmm/include/vmm/linux_syscalls.h index 045c756..99c45ce 100644 --- a/user/vmm/include/vmm/linux_syscalls.h +++ b/user/vmm/include/vmm/linux_syscalls.h
@@ -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 index 0000000..79b7062 --- /dev/null +++ b/user/vmm/include/vmm/linuxemu.h
@@ -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);
diff --git a/user/vmm/linuxemu.c b/user/vmm/linuxemu.c index bd217e8..e6ac53c 100644 --- a/user/vmm/linuxemu.c +++ b/user/vmm/linuxemu.c
@@ -14,6 +14,76 @@ #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 @@ 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. */ - 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; + + if (tf->tf_rax >= dune_max_syscall) { + fprintf(stderr, "System call %d is out of range\n", tf->tf_rax); + return false; } - return ret; + + + if (dune_syscall_table[tf->tf_rax].call == NULL) { + fprintf(stderr, "System call %d is not implemented\n", tf->tf_rax); + return false; + } + + return (dune_syscall_table[tf->tf_rax].call)(tf); }