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.


Convert shadow paging to use 32 PAE (Core)
[palacios.git] / palacios / src / palacios / vm_guest.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
21
22
23 #include <palacios/vm_guest.h>
24 #include <palacios/vmm_ctrl_regs.h>
25 #include <palacios/vmm.h>
26 #include <palacios/vmm_decoder.h>
27 #include <palacios/vmcb.h>
28 #include <palacios/vm_guest_mem.h>
29 #include <palacios/vmm_lowlevel.h>
30 #include <palacios/vmm_sprintf.h>
31 #include <palacios/vmm_xed.h>
32 #include <palacios/vmm_direct_paging.h>
33 #include <palacios/vmm_barrier.h>
34 #include <palacios/vmm_debug.h>
35
36
37 v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
38     struct cr0_32 * cr0;
39     struct efer_64 * efer;
40     struct v3_segment * cs = &(info->segments.cs);
41     struct cr4_32 * cr4;
42
43     if (info->shdw_pg_mode == SHADOW_PAGING) {
44         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
45         efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
46         cr4 = (struct cr4_32 *)&(info->shdw_pg_state.guest_cr4);
47     } else if (info->shdw_pg_mode == NESTED_PAGING) {
48         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
49         efer = (struct efer_64 *)&(info->ctrl_regs.efer);
50         cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
51     } else {
52         PrintError(info->vm_info, info, "Invalid Paging Mode...\n");
53         V3_ASSERT(info->vm_info, info, 0);
54         return -1;
55     }
56
57     if (cr0->pe == 0) {
58         return REAL;
59     } else if ((cr4->pae == 0) && (efer->lme == 0)) {
60         return PROTECTED;
61     } else if (efer->lme == 0) {
62         return PROTECTED_PAE;
63     } else if ((efer->lme == 1) && (cs->long_mode == 1)) {
64         return LONG;
65     } else {
66         // What about LONG_16_COMPAT???
67         return LONG_32_COMPAT;
68     }
69 }
70
71 // Get address width in bytes
72 uint_t v3_get_addr_width(struct guest_info * info) {
73     struct cr0_32 * cr0;
74     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
75     struct efer_64 * efer;
76     struct v3_segment * cs = &(info->segments.cs);
77
78
79     if (info->shdw_pg_mode == SHADOW_PAGING) {
80         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
81         efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
82     } else if (info->shdw_pg_mode == NESTED_PAGING) {
83         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
84         efer = (struct efer_64 *)&(info->ctrl_regs.efer);
85     } else {
86         PrintError(info->vm_info, info, "Invalid Paging Mode...\n");
87         V3_ASSERT(info->vm_info, info, 0);
88         return -1;
89     }
90
91     if (cr0->pe == 0) {
92         return 2;
93     } else if ((cr4->pae == 0) && (efer->lme == 0)) {
94         return 4;
95     } else if (efer->lme == 0) {
96         return 4;
97     } else if ((efer->lme == 1) && (cs->long_mode == 1)) {
98         return 8;
99     } else {
100         // What about LONG_16_COMPAT???
101         return 4;
102     }
103 }
104
105
106 static const uchar_t REAL_STR[] = "Real";
107 static const uchar_t PROTECTED_STR[] = "Protected";
108 static const uchar_t PROTECTED_PAE_STR[] = "Protected+PAE";
109 static const uchar_t LONG_STR[] = "Long";
110 static const uchar_t LONG_32_COMPAT_STR[] = "32bit Compat";
111 static const uchar_t LONG_16_COMPAT_STR[] = "16bit Compat";
112
113 const uchar_t * v3_cpu_mode_to_str(v3_cpu_mode_t mode) {
114     switch (mode) {
115         case REAL:
116             return REAL_STR;
117         case PROTECTED:
118             return PROTECTED_STR;
119         case PROTECTED_PAE:
120             return PROTECTED_PAE_STR;
121         case LONG:
122             return LONG_STR;
123         case LONG_32_COMPAT:
124             return LONG_32_COMPAT_STR;
125         case LONG_16_COMPAT:
126             return LONG_16_COMPAT_STR;
127         default:
128             return NULL;
129     }
130 }
131
132 v3_mem_mode_t v3_get_vm_mem_mode(struct guest_info * info) {
133     struct cr0_32 * cr0;
134
135     if (info->shdw_pg_mode == SHADOW_PAGING) {
136         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
137     } else if (info->shdw_pg_mode == NESTED_PAGING) {
138         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
139     } else {
140         PrintError(info->vm_info, info, "Invalid Paging Mode...\n");
141         V3_ASSERT(info->vm_info, info, 0);
142         return -1;
143     }
144
145     if (cr0->pg == 0) {
146         return PHYSICAL_MEM;
147     } else {
148         return VIRTUAL_MEM;
149     }
150 }
151
152 static const uchar_t PHYS_MEM_STR[] = "Physical Memory";
153 static const uchar_t VIRT_MEM_STR[] = "Virtual Memory";
154
155 const uchar_t * v3_mem_mode_to_str(v3_mem_mode_t mode) {
156     switch (mode) {
157         case PHYSICAL_MEM:
158             return PHYS_MEM_STR;
159         case VIRTUAL_MEM:
160             return VIRT_MEM_STR;
161         default:
162             return NULL;
163     }
164 }
165
166
167
168
169
170
171
172 #include <palacios/vmcs.h>
173 #include <palacios/vmcb.h>
174 static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_data) {
175     extern v3_cpu_arch_t v3_mach_type;
176     int cpu_valid = 0;
177
178     V3_Print(core->vm_info, core, "************** Guest State ************\n");
179     v3_print_guest_state(core);
180     
181     // init SVM/VMX
182 #ifdef V3_CONFIG_SVM
183     if ((v3_mach_type == V3_SVM_CPU) || (v3_mach_type == V3_SVM_REV3_CPU)) {
184         cpu_valid = 1;
185         PrintDebugVMCB((vmcb_t *)(core->vmm_data));
186     }
187 #endif
188 #ifdef V3_CONFIG_VMX
189     if ((v3_mach_type == V3_VMX_CPU) || (v3_mach_type == V3_VMX_EPT_CPU) || (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
190         cpu_valid = 1;
191         v3_print_vmcs();
192     }
193 #endif
194     if (!cpu_valid) {
195         PrintError(core->vm_info, core, "Invalid CPU Type 0x%x\n", v3_mach_type);
196         return -1;
197     }
198     
199
200     return 0;
201 }
202
203
204 #ifdef V3_CONFIG_SVM
205 #include <palacios/svm.h>
206 #include <palacios/svm_io.h>
207 #include <palacios/svm_msr.h>
208 #include <palacios/svm_exits.h>
209 #endif
210
211 #ifdef V3_CONFIG_VMX
212 #include <palacios/vmx.h>
213 #include <palacios/vmx_io.h>
214 #include <palacios/vmx_msr.h>
215 #include <palacios/vmx_exits.h>
216 #endif
217
218
219 int v3_init_vm(struct v3_vm_info * vm) {
220     extern v3_cpu_arch_t v3_mach_type;
221
222     v3_init_events(vm);
223
224 #ifdef V3_CONFIG_TELEMETRY
225     v3_init_telemetry(vm);
226 #endif
227
228     v3_init_exit_hooks(vm);
229     v3_init_hypercall_map(vm);
230     v3_init_io_map(vm);
231     v3_init_msr_map(vm);
232     v3_init_cpuid_map(vm);
233     v3_init_host_events(vm);
234
235     v3_init_intr_routers(vm);
236     v3_init_ext_manager(vm);
237
238     v3_init_barrier(vm);
239
240     // Initialize the memory map
241     if (v3_init_mem_map(vm) == -1) {
242         PrintError(vm, VCORE_NONE, "Could not initialize shadow map\n");
243         return -1;
244     }
245
246     v3_init_mem_hooks(vm);
247
248     if (v3_init_shdw_impl(vm) == -1) {
249         PrintError(vm, VCORE_NONE, "VM initialization error in shadow implementaion\n");
250         return -1;
251     }
252
253
254     v3_init_time_vm(vm);
255
256     v3_init_vm_debugging(vm);
257
258
259 #ifdef V3_CONFIG_SYMBIOTIC
260     v3_init_symbiotic_vm(vm);
261 #endif
262
263     v3_init_dev_mgr(vm);
264
265
266     // init SVM/VMX
267     switch (v3_mach_type) {
268 #ifdef V3_CONFIG_SVM
269         case V3_SVM_CPU:
270         case V3_SVM_REV3_CPU:
271             v3_init_svm_io_map(vm);
272             v3_init_svm_msr_map(vm);
273             v3_init_svm_exits(vm);
274             break;
275 #endif
276 #ifdef V3_CONFIG_VMX
277         case V3_VMX_CPU:
278         case V3_VMX_EPT_CPU:
279         case V3_VMX_EPT_UG_CPU:
280             v3_init_vmx_io_map(vm);
281             v3_init_vmx_msr_map(vm);
282             v3_init_vmx_exits(vm);
283             break;
284 #endif
285         default:
286             PrintError(vm, VCORE_NONE, "Invalid CPU Type 0x%x\n", v3_mach_type);
287             return -1;
288     }
289     
290     v3_register_hypercall(vm, GUEST_INFO_HCALL, info_hcall, NULL);
291
292     V3_Print(vm, VCORE_NONE, "GUEST_INFO_HCALL=%x\n", GUEST_INFO_HCALL);
293
294     return 0;
295 }
296
297
298 int v3_free_vm_internal(struct v3_vm_info * vm) {
299     extern v3_cpu_arch_t v3_mach_type;
300
301     v3_remove_hypercall(vm, GUEST_INFO_HCALL);
302
303
304
305 #ifdef V3_CONFIG_SYMBIOTIC
306     v3_deinit_symbiotic_vm(vm);
307 #endif
308
309     // init SVM/VMX
310     switch (v3_mach_type) {
311 #ifdef V3_CONFIG_SVM
312         case V3_SVM_CPU:
313         case V3_SVM_REV3_CPU:
314             v3_deinit_svm_io_map(vm);
315             v3_deinit_svm_msr_map(vm);
316             break;
317 #endif
318 #ifdef V3_CONFIG_VMX
319         case V3_VMX_CPU:
320         case V3_VMX_EPT_CPU:
321         case V3_VMX_EPT_UG_CPU:
322             v3_deinit_vmx_io_map(vm);
323             v3_deinit_vmx_msr_map(vm);
324             break;
325 #endif
326         default:
327             PrintError(vm, VCORE_NONE, "Invalid CPU Type 0x%x\n", v3_mach_type);
328             return -1;
329     }
330
331     v3_deinit_dev_mgr(vm);
332
333     v3_deinit_time_vm(vm);
334
335     v3_deinit_mem_hooks(vm);
336     v3_delete_mem_map(vm);
337     v3_deinit_shdw_impl(vm);
338
339     v3_deinit_ext_manager(vm);
340     v3_deinit_intr_routers(vm);
341     v3_deinit_host_events(vm);
342
343     v3_deinit_barrier(vm);
344
345     v3_deinit_cpuid_map(vm);
346     v3_deinit_msr_map(vm);
347     v3_deinit_io_map(vm);
348     v3_deinit_hypercall_map(vm);
349
350     v3_deinit_exit_hooks(vm);
351
352 #ifdef V3_CONFIG_TELEMETRY
353     v3_deinit_telemetry(vm);
354 #endif
355
356     v3_deinit_events(vm);
357
358     v3_fw_cfg_deinit(vm);
359
360
361     return 0;
362 }
363
364
365 int v3_init_core(struct guest_info * core) {
366     extern v3_cpu_arch_t v3_mach_type;
367     struct v3_vm_info * vm = core->vm_info;
368
369
370
371     /*
372      * Initialize the subsystem data strutures
373      */
374 #ifdef V3_CONFIG_TELEMETRY
375     v3_init_core_telemetry(core);
376 #endif
377
378     if (core->shdw_pg_mode == SHADOW_PAGING) {
379         v3_init_shdw_pg_state(core);
380     }
381
382     v3_init_time_core(core);
383     v3_init_intr_controllers(core);
384     v3_init_exception_state(core);
385
386     v3_init_decoder(core);
387
388
389 #ifdef V3_CONFIG_SYMBIOTIC
390     v3_init_symbiotic_core(core);
391 #endif
392
393     // init SVM/VMX
394
395
396     switch (v3_mach_type) {
397 #ifdef V3_CONFIG_SVM
398         case V3_SVM_CPU:
399         case V3_SVM_REV3_CPU:
400             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
401                 PrintError(vm, core, "Error in SVM initialization\n");
402                 return -1;
403             }
404             break;
405 #endif
406 #ifdef V3_CONFIG_VMX
407         case V3_VMX_CPU:
408         case V3_VMX_EPT_CPU:
409         case V3_VMX_EPT_UG_CPU:
410             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
411                 PrintError(vm, core, "Error in VMX initialization\n");
412                 return -1;
413             }
414             break;
415 #endif
416         default:
417             PrintError(vm, core, "Invalid CPU Type 0x%x\n", v3_mach_type);
418             return -1;
419     }
420     
421     v3_init_exit_hooks_core(core);
422
423
424     return 0;
425 }
426
427
428
429 int v3_free_core(struct guest_info * core) {
430     extern v3_cpu_arch_t v3_mach_type;
431
432     
433 #ifdef V3_CONFIG_SYMBIOTIC
434     v3_deinit_symbiotic_core(core);
435 #endif
436
437     v3_deinit_decoder(core);
438
439     v3_deinit_intr_controllers(core);
440     v3_deinit_time_core(core);
441
442     if (core->shdw_pg_mode == SHADOW_PAGING) {
443         v3_deinit_shdw_pg_state(core);
444     }
445
446     v3_free_passthrough_pts(core);
447
448 #ifdef V3_CONFIG_TELEMETRY
449     v3_deinit_core_telemetry(core);
450 #endif
451
452     switch (v3_mach_type) {
453 #ifdef V3_CONFIG_SVM
454         case V3_SVM_CPU:
455         case V3_SVM_REV3_CPU:
456             if (v3_deinit_svm_vmcb(core) == -1) {
457                 PrintError(VM_NONE,VCORE_NONE, "Error in SVM deinitialization\n");
458                 return -1;
459             }
460             break;
461 #endif
462 #ifdef V3_CONFIG_VMX
463         case V3_VMX_CPU:
464         case V3_VMX_EPT_CPU:
465         case V3_VMX_EPT_UG_CPU:
466             if (v3_deinit_vmx_vmcs(core) == -1) {
467                 PrintError(VM_NONE, VCORE_NONE, "Error in VMX initialization\n");
468                 return -1;
469             }
470             break;
471 #endif
472         default:
473             PrintError(core->vm_info, core, "Invalid CPU Type 0x%x\n", v3_mach_type);
474             return -1;
475     }
476
477     return 0;
478 }
479
480
481