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.


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