Try out Dune vmm stuff.
[akaros.git] / kern / arch / x86 / vmm / vmm.c
1 /* Copyright 2015 Google Inc.
2  * 
3  * See LICENSE for details.
4  */
5
6 /* We're not going to falll into the trap of only compiling support
7  * for AMD OR Intel for an image. It all gets compiled in, and which
8  * one you use depends on on cpuinfo, not a compile-time
9  * switch. That's proven to be the best strategy.  Conditionally
10  * compiling in support is the path to hell.
11  */
12 #include <assert.h>
13 #include <pmap.h>
14 #include <smp.h>
15 #include <kmalloc.h>
16
17 #include "intel/vmx.h"
18 #include "intel/compat.h"
19 #include "vmm.h"
20
21 /* Figure out what kind of CPU we are on, and if it supports any reasonable
22  * virtualization. For now, if we're not some sort of newer intel, don't
23  * bother. This does all cores. Again, note, we make these decisions at runtime,
24  * to avoid getting into the problems that compile-time decisions can cause. 
25  * At this point, of course, it's still all intel.
26  */
27 void vmm_init(void)
28 {
29         int ret;
30         /* Check first for intel capabilities. This is hence two back-to-back
31          * implementationd-dependent checks. That's ok, it's all msr dependent.
32          */
33         ret = intel_vmm_init();
34         if (! ret) {
35                 printd("intel_vmm_init worked\n");
36                 return;
37         }
38
39         /* TODO: AMD. Will we ever care? It's not clear. */
40         printk("vmm_init failed, ret %d\n", ret);
41         return;
42 }
43
44 void vmm_pcpu_init(void)
45 {
46         if (! intel_vmm_pcpu_init()) {
47                 printd("vmm_pcpu_init worked\n");
48                 return;
49         }
50         /* TODO: AMD. Will we ever care? It's not clear. */
51         printk("vmm_pcpu_init failed\n");
52 }
53
54 int vm_run(uint64_t rip, uint64_t rsp, uint64_t cr3)
55 {
56         struct dune_config d = {rip, rsp, cr3};
57         int vmx_launch(struct dune_config *conf);       
58         if (current->vmm.amd) {
59                 return -1;
60         } else {
61                 return vmx_launch(&d);
62         }
63         return -1;
64 }
65
66 /* Initializes a process to run virtual machine contexts, returning the number
67  * initialized, optionally setting errno */
68 int vmm_struct_init(struct vmm *vmm, unsigned int nr_guest_pcores)
69 {
70         unsigned int i;
71         qlock(&vmm->qlock);
72         if (vmm->vmmcp) {
73                 set_errno(EINVAL);
74                 qunlock(&vmm->qlock);
75                 return 0;
76         }
77         nr_guest_pcores = MIN(nr_guest_pcores, num_cpus);
78         vmm->amd = 0;
79         vmm->guest_pcores = kzmalloc(sizeof(void*) * nr_guest_pcores, KMALLOC_WAIT);
80         for (i = 0; i < nr_guest_pcores; i++) {
81                 vmm->guest_pcores[i] = vmx_create_vcpu();
82                 /* If we failed, we'll clean it up when the process dies */
83                 if (!vmm->guest_pcores[i]) {
84                         set_errno(ENOMEM);
85                         break;
86                 }
87         }
88         vmm->nr_guest_pcores = i;
89         vmm->vmmcp = TRUE;
90         qunlock(&vmm->qlock);
91         return i;
92 }
93
94 void vmm_struct_cleanup(struct vmm *vmm)
95 {
96         qlock(&vmm->qlock);
97         if (!vmm->vmmcp) {
98                 qunlock(&vmm->qlock);
99                 return;
100         }
101         for (int i = 0; i < vmm->nr_guest_pcores; i++) {
102                 if (vmm->guest_pcores[i])
103                         vmx_destroy_vcpu(vmm->guest_pcores[i]);
104         }
105         kfree(vmm->guest_pcores);
106         vmm->vmmcp = FALSE;
107         qunlock(&vmm->qlock);
108 }