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.


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