vmmcp: cut over to virtual apic; fix include mess after upgrade
[akaros.git] / kern / arch / x86 / vmm / vmm.c
index e0ddfce..142fec9 100644 (file)
 #include <smp.h>
 #include <kmalloc.h>
 
+#include <ros/vmm.h>
 #include "intel/vmx.h"
-#include "intel/compat.h"
 #include "vmm.h"
 
+/* TODO: have better cpuid info storage and checks */
+bool x86_supports_vmx = FALSE;
+
 /* Figure out what kind of CPU we are on, and if it supports any reasonable
  * virtualization. For now, if we're not some sort of newer intel, don't
  * bother. This does all cores. Again, note, we make these decisions at runtime,
@@ -33,6 +36,7 @@ void vmm_init(void)
        ret = intel_vmm_init();
        if (! ret) {
                printd("intel_vmm_init worked\n");
+               x86_supports_vmx = TRUE;
                return;
        }
 
@@ -43,6 +47,8 @@ void vmm_init(void)
 
 void vmm_pcpu_init(void)
 {
+       if (!x86_supports_vmx)
+               return;
        if (! intel_vmm_pcpu_init()) {
                printd("vmm_pcpu_init worked\n");
                return;
@@ -51,34 +57,48 @@ void vmm_pcpu_init(void)
        printk("vmm_pcpu_init failed\n");
 }
 
-int vm_run(uint64_t rip, uint64_t rsp, uint64_t cr3)
+int vm_run(struct vmctl *v)
 {
-       struct dune_config d = {rip, rsp, cr3};
-       int vmx_launch(struct dune_config *conf);       
+       int vmx_launch(struct vmctl *v);
        if (current->vmm.amd) {
                return -1;
        } else {
-               return vmx_launch(&d);
+               return vmx_launch(v);
        }
        return -1;
 }
 
 /* Initializes a process to run virtual machine contexts, returning the number
  * initialized, optionally setting errno */
-int vmm_struct_init(struct vmm *vmm, unsigned int nr_guest_pcores)
+int vmm_struct_init(struct proc *p, unsigned int nr_guest_pcores, int flags)
 {
+       struct vmm *vmm = &p->vmm;
        unsigned int i;
+       if (flags & ~VMM_ALL_FLAGS) {
+               set_errstr("%s: flags is 0x%lx, VMM_ALL_FLAGS is 0x%lx\n", __func__,
+                          flags, VMM_ALL_FLAGS);
+               set_errno(EINVAL);
+               return 0;
+       }
+       vmm->flags = flags;
+
+       if (!x86_supports_vmx) {
+               set_errno(ENODEV);
+               return 0;
+       }
        qlock(&vmm->qlock);
        if (vmm->vmmcp) {
                set_errno(EINVAL);
                qunlock(&vmm->qlock);
                return 0;
        }
-       nr_guest_pcores = MIN(nr_guest_pcores, num_cpus);
+       /* Set this early, so cleanup checks the gpc array */
+       vmm->vmmcp = TRUE;
+       nr_guest_pcores = MIN(nr_guest_pcores, num_cores);
        vmm->amd = 0;
        vmm->guest_pcores = kzmalloc(sizeof(void*) * nr_guest_pcores, KMALLOC_WAIT);
        for (i = 0; i < nr_guest_pcores; i++) {
-               vmm->guest_pcores[i] = vmx_create_vcpu();
+               vmm->guest_pcores[i] = vmx_create_vcpu(p);
                /* If we failed, we'll clean it up when the process dies */
                if (!vmm->guest_pcores[i]) {
                        set_errno(ENOMEM);
@@ -86,23 +106,23 @@ int vmm_struct_init(struct vmm *vmm, unsigned int nr_guest_pcores)
                }
        }
        vmm->nr_guest_pcores = i;
-       vmm->vmmcp = TRUE;
        qunlock(&vmm->qlock);
        return i;
 }
 
-void vmm_struct_cleanup(struct vmm *vmm)
+/* Has no concurrency protection - only call this when you know you have the
+ * only ref to vmm.  For instance, from __proc_free, where there is only one ref
+ * to the proc (and thus proc.vmm). */
+void __vmm_struct_cleanup(struct proc *p)
 {
-       qlock(&vmm->qlock);
-       if (!vmm->vmmcp) {
-               qunlock(&vmm->qlock);
+       struct vmm *vmm = &p->vmm;
+       if (!vmm->vmmcp)
                return;
-       }
        for (int i = 0; i < vmm->nr_guest_pcores; i++) {
                if (vmm->guest_pcores[i])
                        vmx_destroy_vcpu(vmm->guest_pcores[i]);
        }
        kfree(vmm->guest_pcores);
+       ept_flush(p->env_pgdir.eptp);
        vmm->vmmcp = FALSE;
-       qunlock(&vmm->qlock);
 }