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.


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