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.


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