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.


Add swapping and pinning capability to Palacios
[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
346 #ifdef V3_CONFIG_SWAPPING
347     v3_deinit_swapping_vm(vm);
348 #endif
349
350     v3_delete_mem_map(vm);
351     v3_deinit_shdw_impl(vm);
352     v3_deinit_passthrough_paging(vm);
353     v3_deinit_nested_paging(vm);
354
355     v3_deinit_ext_manager(vm);
356     v3_deinit_intr_routers(vm);
357     v3_deinit_host_events(vm);
358
359     v3_deinit_barrier(vm);
360
361     v3_deinit_cpuid_map(vm);
362     v3_deinit_msr_map(vm);
363     v3_deinit_io_map(vm);
364     v3_deinit_hypercall_map(vm);
365
366     v3_deinit_exit_hooks(vm);
367
368 #ifdef V3_CONFIG_TELEMETRY
369     v3_deinit_telemetry(vm);
370 #endif
371
372     v3_deinit_events(vm);
373
374     v3_fw_cfg_deinit(vm);
375
376
377     return 0;
378 }
379
380
381 int v3_init_core(struct guest_info * core) {
382     extern v3_cpu_arch_t v3_mach_type;
383     struct v3_vm_info * vm = core->vm_info;
384
385
386
387     /*
388      * Initialize the subsystem data strutures
389      */
390 #ifdef V3_CONFIG_TELEMETRY
391     v3_init_core_telemetry(core);
392 #endif
393
394     if (core->shdw_pg_mode == SHADOW_PAGING) {
395         v3_init_passthrough_paging_core(core);
396         v3_init_shdw_pg_state(core);
397     } else {
398         //done later due to SVM/VMX differences 
399         //v3_init_nested_paging_core(core);
400     }
401
402     v3_init_time_core(core);
403     v3_init_intr_controllers(core);
404     v3_init_exception_state(core);
405
406     v3_init_decoder(core);
407
408
409 #ifdef V3_CONFIG_SYMBIOTIC
410     v3_init_symbiotic_core(core);
411 #endif
412
413     // init SVM/VMX
414
415
416     switch (v3_mach_type) {
417 #ifdef V3_CONFIG_SVM
418         case V3_SVM_CPU:
419         case V3_SVM_REV3_CPU:
420             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
421                 PrintError(vm, core, "Error in SVM initialization\n");
422                 return -1;
423             }
424             break;
425 #endif
426 #ifdef V3_CONFIG_VMX
427         case V3_VMX_CPU:
428         case V3_VMX_EPT_CPU:
429         case V3_VMX_EPT_UG_CPU:
430             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
431                 PrintError(vm, core, "Error in VMX initialization\n");
432                 return -1;
433             }
434             break;
435 #endif
436         default:
437             PrintError(vm, core, "Invalid CPU Type 0x%x\n", v3_mach_type);
438             return -1;
439     }
440     
441     v3_init_exit_hooks_core(core);
442
443
444     return 0;
445 }
446
447
448
449 int v3_free_core(struct guest_info * core) {
450     extern v3_cpu_arch_t v3_mach_type;
451
452     
453 #ifdef V3_CONFIG_SYMBIOTIC
454     v3_deinit_symbiotic_core(core);
455 #endif
456
457     v3_deinit_decoder(core);
458
459     v3_deinit_intr_controllers(core);
460     v3_deinit_time_core(core);
461
462     if (core->shdw_pg_mode == SHADOW_PAGING) {
463         v3_deinit_shdw_pg_state(core);
464         v3_deinit_passthrough_paging_core(core);
465    } else {
466         v3_deinit_nested_paging_core(core);
467     }
468
469     v3_free_passthrough_pts(core);
470
471 #ifdef V3_CONFIG_TELEMETRY
472     v3_deinit_core_telemetry(core);
473 #endif
474
475     switch (v3_mach_type) {
476 #ifdef V3_CONFIG_SVM
477         case V3_SVM_CPU:
478         case V3_SVM_REV3_CPU:
479             if (v3_deinit_svm_vmcb(core) == -1) {
480                 PrintError(VM_NONE,VCORE_NONE, "Error in SVM deinitialization\n");
481                 return -1;
482             }
483             break;
484 #endif
485 #ifdef V3_CONFIG_VMX
486         case V3_VMX_CPU:
487         case V3_VMX_EPT_CPU:
488         case V3_VMX_EPT_UG_CPU:
489             if (v3_deinit_vmx_vmcs(core) == -1) {
490                 PrintError(VM_NONE, VCORE_NONE, "Error in VMX initialization\n");
491                 return -1;
492             }
493             break;
494 #endif
495         default:
496             PrintError(core->vm_info, core, "Invalid CPU Type 0x%x\n", v3_mach_type);
497             return -1;
498     }
499
500     return 0;
501 }
502
503
504