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 and additions to direct paging (nested and passthrough)
[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     if (v3_init_passthrough_paging(vm) == -1) {
254         PrintError(vm, VCORE_NONE, "VM initialization error in passthrough paging\n");
255         return -1;
256     }
257
258     if (v3_init_nested_paging(vm) == -1) {
259         PrintError(vm, VCORE_NONE, "VM initialization error in nested paging\n");
260         return -1;
261     }
262
263     v3_init_time_vm(vm);
264
265     v3_init_vm_debugging(vm);
266
267
268 #ifdef V3_CONFIG_SYMBIOTIC
269     v3_init_symbiotic_vm(vm);
270 #endif
271
272     v3_init_dev_mgr(vm);
273
274
275     // init SVM/VMX
276     switch (v3_mach_type) {
277 #ifdef V3_CONFIG_SVM
278         case V3_SVM_CPU:
279         case V3_SVM_REV3_CPU:
280             v3_init_svm_io_map(vm);
281             v3_init_svm_msr_map(vm);
282             v3_init_svm_exits(vm);
283             break;
284 #endif
285 #ifdef V3_CONFIG_VMX
286         case V3_VMX_CPU:
287         case V3_VMX_EPT_CPU:
288         case V3_VMX_EPT_UG_CPU:
289             v3_init_vmx_io_map(vm);
290             v3_init_vmx_msr_map(vm);
291             v3_init_vmx_exits(vm);
292             break;
293 #endif
294         default:
295             PrintError(vm, VCORE_NONE, "Invalid CPU Type 0x%x\n", v3_mach_type);
296             return -1;
297     }
298     
299     v3_register_hypercall(vm, GUEST_INFO_HCALL, info_hcall, NULL);
300
301     V3_Print(vm, VCORE_NONE, "GUEST_INFO_HCALL=%x\n", GUEST_INFO_HCALL);
302
303     return 0;
304 }
305
306
307 int v3_free_vm_internal(struct v3_vm_info * vm) {
308     extern v3_cpu_arch_t v3_mach_type;
309
310     v3_remove_hypercall(vm, GUEST_INFO_HCALL);
311
312
313
314 #ifdef V3_CONFIG_SYMBIOTIC
315     v3_deinit_symbiotic_vm(vm);
316 #endif
317
318     // init SVM/VMX
319     switch (v3_mach_type) {
320 #ifdef V3_CONFIG_SVM
321         case V3_SVM_CPU:
322         case V3_SVM_REV3_CPU:
323             v3_deinit_svm_io_map(vm);
324             v3_deinit_svm_msr_map(vm);
325             break;
326 #endif
327 #ifdef V3_CONFIG_VMX
328         case V3_VMX_CPU:
329         case V3_VMX_EPT_CPU:
330         case V3_VMX_EPT_UG_CPU:
331             v3_deinit_vmx_io_map(vm);
332             v3_deinit_vmx_msr_map(vm);
333             break;
334 #endif
335         default:
336             PrintError(vm, VCORE_NONE, "Invalid CPU Type 0x%x\n", v3_mach_type);
337             return -1;
338     }
339
340     v3_deinit_dev_mgr(vm);
341
342     v3_deinit_time_vm(vm);
343
344     v3_deinit_mem_hooks(vm);
345     v3_delete_mem_map(vm);
346     v3_deinit_shdw_impl(vm);
347     v3_deinit_passthrough_paging(vm);
348     v3_deinit_nested_paging(vm);
349
350     v3_deinit_ext_manager(vm);
351     v3_deinit_intr_routers(vm);
352     v3_deinit_host_events(vm);
353
354     v3_deinit_barrier(vm);
355
356     v3_deinit_cpuid_map(vm);
357     v3_deinit_msr_map(vm);
358     v3_deinit_io_map(vm);
359     v3_deinit_hypercall_map(vm);
360
361     v3_deinit_exit_hooks(vm);
362
363 #ifdef V3_CONFIG_TELEMETRY
364     v3_deinit_telemetry(vm);
365 #endif
366
367     v3_deinit_events(vm);
368
369     v3_fw_cfg_deinit(vm);
370
371
372     return 0;
373 }
374
375
376 int v3_init_core(struct guest_info * core) {
377     extern v3_cpu_arch_t v3_mach_type;
378     struct v3_vm_info * vm = core->vm_info;
379
380
381
382     /*
383      * Initialize the subsystem data strutures
384      */
385 #ifdef V3_CONFIG_TELEMETRY
386     v3_init_core_telemetry(core);
387 #endif
388
389     if (core->shdw_pg_mode == SHADOW_PAGING) {
390         v3_init_passthrough_paging_core(core);
391         v3_init_shdw_pg_state(core);
392     } else {
393         //done later due to SVM/VMX differences 
394         //v3_init_nested_paging_core(core);
395     }
396
397     v3_init_time_core(core);
398     v3_init_intr_controllers(core);
399     v3_init_exception_state(core);
400
401     v3_init_decoder(core);
402
403
404 #ifdef V3_CONFIG_SYMBIOTIC
405     v3_init_symbiotic_core(core);
406 #endif
407
408     // init SVM/VMX
409
410
411     switch (v3_mach_type) {
412 #ifdef V3_CONFIG_SVM
413         case V3_SVM_CPU:
414         case V3_SVM_REV3_CPU:
415             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
416                 PrintError(vm, core, "Error in SVM initialization\n");
417                 return -1;
418             }
419             break;
420 #endif
421 #ifdef V3_CONFIG_VMX
422         case V3_VMX_CPU:
423         case V3_VMX_EPT_CPU:
424         case V3_VMX_EPT_UG_CPU:
425             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
426                 PrintError(vm, core, "Error in VMX initialization\n");
427                 return -1;
428             }
429             break;
430 #endif
431         default:
432             PrintError(vm, core, "Invalid CPU Type 0x%x\n", v3_mach_type);
433             return -1;
434     }
435     
436     v3_init_exit_hooks_core(core);
437
438
439     return 0;
440 }
441
442
443
444 int v3_free_core(struct guest_info * core) {
445     extern v3_cpu_arch_t v3_mach_type;
446
447     
448 #ifdef V3_CONFIG_SYMBIOTIC
449     v3_deinit_symbiotic_core(core);
450 #endif
451
452     v3_deinit_decoder(core);
453
454     v3_deinit_intr_controllers(core);
455     v3_deinit_time_core(core);
456
457     if (core->shdw_pg_mode == SHADOW_PAGING) {
458         v3_deinit_shdw_pg_state(core);
459         v3_deinit_passthrough_paging_core(core);
460    } else {
461         v3_deinit_nested_paging_core(core);
462     }
463
464     v3_free_passthrough_pts(core);
465
466 #ifdef V3_CONFIG_TELEMETRY
467     v3_deinit_core_telemetry(core);
468 #endif
469
470     switch (v3_mach_type) {
471 #ifdef V3_CONFIG_SVM
472         case V3_SVM_CPU:
473         case V3_SVM_REV3_CPU:
474             if (v3_deinit_svm_vmcb(core) == -1) {
475                 PrintError(VM_NONE,VCORE_NONE, "Error in SVM deinitialization\n");
476                 return -1;
477             }
478             break;
479 #endif
480 #ifdef V3_CONFIG_VMX
481         case V3_VMX_CPU:
482         case V3_VMX_EPT_CPU:
483         case V3_VMX_EPT_UG_CPU:
484             if (v3_deinit_vmx_vmcs(core) == -1) {
485                 PrintError(VM_NONE, VCORE_NONE, "Error in VMX initialization\n");
486                 return -1;
487             }
488             break;
489 #endif
490         default:
491             PrintError(core->vm_info, core, "Invalid CPU Type 0x%x\n", v3_mach_type);
492             return -1;
493     }
494
495     return 0;
496 }
497
498
499