vmm: Support basic vthread syscalls
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 13 Sep 2017 18:45:14 +0000 (14:45 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 15 Sep 2017 13:33:05 +0000 (09:33 -0400)
You can extend these if you want (example forthcoming), but most generic
vthread apps will want some basic vmcalls.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/vmm/include/vmm/vthread.h
user/vmm/vthread.c

index 7b44d56..4de09ab 100644 (file)
@@ -42,4 +42,32 @@ void vthread_join(struct vthread *vth, void **retval_loc);
 /* Callback, here for sched.c */
 void __vthread_exited(struct vthread *vth);
 
+/* Vmcall support.
+ *
+ * Vthread apps can make their own vmcalls, either replacing this list or
+ * growing their own.  vth_handle_vmcall() will handle all of these.  Apps can
+ * start their list at VTH_VMCALL_NEXT. */
+
+#define VTH_VMCALL_NULL                        0
+#define VTH_VMCALL_PRINTC              1
+#define VTH_VMCALL_EXIT                        2
+#define VTH_VMCALL_NEXT                        3
+
+/* TODO: arch-specific */
+static long raw_vmcall(long arg0, long arg1, long arg2, long arg3, long arg4,
+                       unsigned int vmcall_nr)
+{
+       long ret;
+       register long r8 asm ("r8") = arg4;
+
+       asm volatile("vmcall"
+                    : "=a"(ret)
+                    : "a"(vmcall_nr), "D"(arg0), "S"(arg1), "d"(arg2), "c"(arg3),
+                      "r"(r8));
+       return ret;
+}
+
+long vmcall(unsigned int vmcall_nr, ...);
+bool vth_handle_vmcall(struct guest_thread *gth, struct vm_trapframe *vm_tf);
+
 __END_DECLS
index f773eda..8c82b13 100644 (file)
@@ -227,3 +227,40 @@ void vthread_join(struct vthread *vth, void **retval_loc)
 
        uthread_join((struct uthread*)cth, retval_loc);
 }
+
+long vmcall(unsigned int vmcall_nr, ...)
+{
+       va_list vl;
+       long a0, a1, a2, a3, a4;
+
+       va_start(vl, vmcall_nr);
+       a0 = va_arg(vl, long);
+       a1 = va_arg(vl, long);
+       a2 = va_arg(vl, long);
+       a3 = va_arg(vl, long);
+       a4 = va_arg(vl, long);
+       va_end(vl);
+       return raw_vmcall(a0, a1, a2, a3, a4, vmcall_nr);
+}
+
+bool vth_handle_vmcall(struct guest_thread *gth, struct vm_trapframe *vm_tf)
+{
+       switch (vm_tf->tf_rax) {
+       case VTH_VMCALL_NULL:
+               goto out_ok;
+       case VTH_VMCALL_PRINTC:
+               fprintf(stdout, "%c", vm_tf->tf_rdi);
+               fflush(stdout);
+               goto out_ok;
+       case VTH_VMCALL_EXIT:
+               uth_2ls_thread_exit((void*)vm_tf->tf_rdi);
+               assert(0);
+       default:
+               fprintf(stderr, "Unknown syscall nr %d\n", vm_tf->tf_rax);
+               return FALSE;
+       }
+       assert(0);
+out_ok:
+       vm_tf->tf_rip += 3;
+       return TRUE;
+}