Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


refactoring to the point of compilation
[palacios.git] / palacios / src / palacios / vmm.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_intr.h>
22 #include <palacios/vmm_config.h>
23 #include <palacios/vm_guest.h>
24 #include <palacios/vmm_instrument.h>
25 #include <palacios/vmm_ctrl_regs.h>
26 #include <palacios/vmm_lowlevel.h>
27 #include <palacios/vmm_sprintf.h>
28
29 #ifdef CONFIG_SVM
30 #include <palacios/svm.h>
31 #endif
32 #ifdef CONFIG_VMX
33 #include <palacios/vmx.h>
34 #endif
35
36
37 v3_cpu_arch_t v3_cpu_types[CONFIG_MAX_CPUS];
38 struct v3_os_hooks * os_hooks = NULL;
39
40 int v3_dbg_enable = 0;
41
42
43
44 static void init_cpu(void * arg) {
45     uint32_t cpu_id = (uint32_t)(addr_t)arg;
46
47 #ifdef CONFIG_SVM
48     if (v3_is_svm_capable()) {
49         PrintDebug("Machine is SVM Capable\n");
50         v3_init_svm_cpu(cpu_id);
51         
52     } else 
53 #endif
54 #ifdef CONFIG_VMX
55     if (v3_is_vmx_capable()) {
56         PrintDebug("Machine is VMX Capable\n");
57         v3_init_vmx_cpu(cpu_id);
58
59     } else 
60 #endif
61     {
62        PrintError("CPU has no virtualization Extensions\n");
63     }
64 }
65
66
67
68 void Init_V3(struct v3_os_hooks * hooks, int num_cpus) {
69     int i;
70
71     V3_Print("V3 Print statement to fix a Kitten page fault bug\n");
72
73     // Set global variables. 
74     os_hooks = hooks;
75
76     for (i = 0; i < CONFIG_MAX_CPUS; i++) {
77         v3_cpu_types[i] = V3_INVALID_CPU;
78     }
79
80     // Register all the possible device types
81     v3_init_devices();
82
83 #ifdef INSTRUMENT_VMM
84     v3_init_instrumentation();
85 #endif
86
87     if ((hooks) && (hooks->call_on_cpu)) {
88
89         for (i = 0; i < num_cpus; i++) {
90
91             V3_Print("Initializing VMM extensions on cpu %d\n", i);
92             hooks->call_on_cpu(i, &init_cpu, (void *)(addr_t)i);
93         }
94     }
95 }
96
97
98 v3_cpu_arch_t v3_get_cpu_type(int cpu_id) {
99     return v3_cpu_types[cpu_id];
100 }
101
102
103 struct v3_vm_info * v3_create_vm(void * cfg) {
104     struct v3_vm_info * vm = v3_config_guest(cfg);
105
106     if (vm == NULL) {
107         PrintError("Could not configure guest\n");
108         return NULL;
109     }
110
111     return vm;
112 }
113
114
115 int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
116     int i = 0;
117     V3_Print("V3 --  Starting VM\n");
118
119
120     for (i = 0; i < vm->num_cores; i++) {
121         struct guest_info * info = &(vm->cores[i]);
122
123         /* GRUESOM HACK... */
124         //      vm->cpu_id = v3_get_cpu_id();
125
126         switch (v3_cpu_types[info->cpu_id]) {
127 #ifdef CONFIG_SVM
128             case V3_SVM_CPU:
129             case V3_SVM_REV3_CPU:
130                 return v3_start_svm_guest(info);
131                 break;
132 #endif
133 #if CONFIG_VMX
134             case V3_VMX_CPU:
135             case V3_VMX_EPT_CPU:
136                 return v3_start_vmx_guest(info);
137                 break;
138 #endif
139             default:
140                 PrintError("Attemping to enter a guest on an invalid CPU\n");
141                 return -1;
142         }
143     }
144
145     return 0;
146 }
147
148
149 #ifdef __V3_32BIT__
150
151 v3_cpu_mode_t v3_get_host_cpu_mode() {
152     uint32_t cr4_val;
153     struct cr4_32 * cr4;
154
155     __asm__ (
156              "movl %%cr4, %0; "
157              : "=r"(cr4_val) 
158              );
159
160     
161     cr4 = (struct cr4_32 *)&(cr4_val);
162
163     if (cr4->pae == 1) {
164         return PROTECTED_PAE;
165     } else {
166         return PROTECTED;
167     }
168 }
169
170 #elif __V3_64BIT__
171
172 v3_cpu_mode_t v3_get_host_cpu_mode() {
173     return LONG;
174 }
175
176 #endif 
177
178
179 #define V3_Yield(addr)                                  \
180     do {                                                \
181         extern struct v3_os_hooks * os_hooks;           \
182         if ((os_hooks) && (os_hooks)->yield_cpu) {      \
183             (os_hooks)->yield_cpu();                    \
184         }                                               \
185     } while (0)                                         \
186
187
188
189 void v3_yield_cond(struct guest_info * info) {
190     uint64_t cur_cycle;
191     rdtscll(cur_cycle);
192
193     if (cur_cycle > (info->yield_start_cycle + info->vm_info->yield_cycle_period)) {
194
195         /*
196           PrintDebug("Conditional Yield (cur_cyle=%p, start_cycle=%p, period=%p)\n", 
197           (void *)cur_cycle, (void *)info->yield_start_cycle, (void *)info->yield_cycle_period);
198         */
199         V3_Yield();
200         rdtscll(info->yield_start_cycle);
201     }
202 }
203
204
205 /* 
206  * unconditional cpu yield 
207  * if the yielding thread is a guest context, the guest quantum is reset on resumption 
208  * Non guest context threads should call this function with a NULL argument
209  */
210 void v3_yield(struct guest_info * info) {
211     V3_Yield();
212
213     if (info) {
214         rdtscll(info->yield_start_cycle);
215     }
216 }
217
218
219
220
221 void v3_print_cond(const char * fmt, ...) {
222     if (v3_dbg_enable == 1) {
223         char buf[2048];
224         va_list ap;
225
226         va_start(ap, fmt);
227         vsnprintf(buf, 2048, fmt, ap);
228         va_end(ap);
229
230         V3_Print("%s", buf);
231     }    
232 }
233
234
235
236
237 void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu) {
238     extern struct v3_os_hooks * os_hooks;
239
240     if ((os_hooks) && (os_hooks)->interrupt_cpu) {
241         (os_hooks)->interrupt_cpu(vm, logical_cpu);
242     }
243 }
244
245
246
247 unsigned int v3_get_cpu_id() {
248     extern struct v3_os_hooks * os_hooks;
249     unsigned int ret = (unsigned int)-1;
250
251     if ((os_hooks) && (os_hooks)->get_cpu) {
252         ret = os_hooks->get_cpu();
253     }
254
255     return ret;
256 }
257
258
259
260 int v3_vm_enter(struct guest_info * info) {
261     switch (v3_cpu_types[info->cpu_id]) {
262 #ifdef CONFIG_SVM
263         case V3_SVM_CPU:
264         case V3_SVM_REV3_CPU:
265             return v3_svm_enter(info);
266             break;
267 #endif
268 #if CONFIG_VMX
269         case V3_VMX_CPU:
270         case V3_VMX_EPT_CPU:
271             return v3_vmx_enter(info);
272             break;
273 #endif
274         default:
275             PrintError("Attemping to enter a guest on an invalid CPU\n");
276             return -1;
277     }
278 }