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.


Context-based output infrastructure (V3_Print, etc) and modifications to use it
[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
358     return 0;
359 }
360
361
362 int v3_init_core(struct guest_info * core) {
363     extern v3_cpu_arch_t v3_mach_type;
364     struct v3_vm_info * vm = core->vm_info;
365
366
367
368     /*
369      * Initialize the subsystem data strutures
370      */
371 #ifdef V3_CONFIG_TELEMETRY
372     v3_init_core_telemetry(core);
373 #endif
374
375     if (core->shdw_pg_mode == SHADOW_PAGING) {
376         v3_init_shdw_pg_state(core);
377     }
378
379     v3_init_time_core(core);
380     v3_init_intr_controllers(core);
381     v3_init_exception_state(core);
382
383     v3_init_decoder(core);
384
385
386 #ifdef V3_CONFIG_SYMBIOTIC
387     v3_init_symbiotic_core(core);
388 #endif
389
390     // init SVM/VMX
391
392
393     switch (v3_mach_type) {
394 #ifdef V3_CONFIG_SVM
395         case V3_SVM_CPU:
396         case V3_SVM_REV3_CPU:
397             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
398                 PrintError(vm, core, "Error in SVM initialization\n");
399                 return -1;
400             }
401             break;
402 #endif
403 #ifdef V3_CONFIG_VMX
404         case V3_VMX_CPU:
405         case V3_VMX_EPT_CPU:
406         case V3_VMX_EPT_UG_CPU:
407             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
408                 PrintError(vm, core, "Error in VMX initialization\n");
409                 return -1;
410             }
411             break;
412 #endif
413         default:
414             PrintError(vm, core, "Invalid CPU Type 0x%x\n", v3_mach_type);
415             return -1;
416     }
417     
418     v3_init_exit_hooks_core(core);
419
420
421     return 0;
422 }
423
424
425
426 int v3_free_core(struct guest_info * core) {
427     extern v3_cpu_arch_t v3_mach_type;
428
429     
430 #ifdef V3_CONFIG_SYMBIOTIC
431     v3_deinit_symbiotic_core(core);
432 #endif
433
434     v3_deinit_decoder(core);
435
436     v3_deinit_intr_controllers(core);
437     v3_deinit_time_core(core);
438
439     if (core->shdw_pg_mode == SHADOW_PAGING) {
440         v3_deinit_shdw_pg_state(core);
441     }
442
443     v3_free_passthrough_pts(core);
444
445 #ifdef V3_CONFIG_TELEMETRY
446     v3_deinit_core_telemetry(core);
447 #endif
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_deinit_svm_vmcb(core) == -1) {
454                 PrintError(VM_NONE,VCORE_NONE, "Error in SVM deinitialization\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_deinit_vmx_vmcs(core) == -1) {
464                 PrintError(VM_NONE, VCORE_NONE, "Error in VMX initialization\n");
465                 return -1;
466             }
467             break;
468 #endif
469         default:
470             PrintError(core->vm_info, core, "Invalid CPU Type 0x%x\n", v3_mach_type);
471             return -1;
472     }
473
474     return 0;
475 }
476
477
478