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.


added event hooking framework
[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("Invalid Paging Mode...\n");
52         V3_ASSERT(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("Invalid Paging Mode...\n");
86         V3_ASSERT(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("Invalid Paging Mode...\n");
140         V3_ASSERT(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("************** 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("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 #endif
215
216
217 int v3_init_vm(struct v3_vm_info * vm) {
218     extern v3_cpu_arch_t v3_mach_type;
219
220     v3_init_events(vm);
221
222 #ifdef V3_CONFIG_TELEMETRY
223     v3_init_telemetry(vm);
224 #endif
225
226     v3_init_exit_hooks(vm);
227     v3_init_hypercall_map(vm);
228     v3_init_io_map(vm);
229     v3_init_msr_map(vm);
230     v3_init_cpuid_map(vm);
231     v3_init_host_events(vm);
232
233     v3_init_intr_routers(vm);
234     v3_init_ext_manager(vm);
235
236     v3_init_barrier(vm);
237
238     // Initialize the memory map
239     if (v3_init_mem_map(vm) == -1) {
240         PrintError("Could not initialize shadow map\n");
241         return -1;
242     }
243
244     v3_init_mem_hooks(vm);
245
246     if (v3_init_shdw_impl(vm) == -1) {
247         PrintError("VM initialization error in shadow implementaion\n");
248         return -1;
249     }
250
251
252     v3_init_time_vm(vm);
253
254     v3_init_vm_debugging(vm);
255
256
257 #ifdef V3_CONFIG_SYMBIOTIC
258     v3_init_symbiotic_vm(vm);
259 #endif
260
261     v3_init_dev_mgr(vm);
262
263
264     // init SVM/VMX
265     switch (v3_mach_type) {
266 #ifdef V3_CONFIG_SVM
267         case V3_SVM_CPU:
268         case V3_SVM_REV3_CPU:
269             v3_init_svm_io_map(vm);
270             v3_init_svm_msr_map(vm);
271             v3_init_svm_exits(vm);
272             break;
273 #endif
274 #ifdef V3_CONFIG_VMX
275         case V3_VMX_CPU:
276         case V3_VMX_EPT_CPU:
277         case V3_VMX_EPT_UG_CPU:
278             v3_init_vmx_io_map(vm);
279             v3_init_vmx_msr_map(vm);
280             break;
281 #endif
282         default:
283             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
284             return -1;
285     }
286     
287     v3_register_hypercall(vm, GUEST_INFO_HCALL, info_hcall, NULL);
288
289     V3_Print("GUEST_INFO_HCALL=%x\n", GUEST_INFO_HCALL);
290
291     return 0;
292 }
293
294
295 int v3_free_vm_internal(struct v3_vm_info * vm) {
296     extern v3_cpu_arch_t v3_mach_type;
297
298     v3_remove_hypercall(vm, GUEST_INFO_HCALL);
299
300
301
302 #ifdef V3_CONFIG_SYMBIOTIC
303     v3_deinit_symbiotic_vm(vm);
304 #endif
305
306     // init SVM/VMX
307     switch (v3_mach_type) {
308 #ifdef V3_CONFIG_SVM
309         case V3_SVM_CPU:
310         case V3_SVM_REV3_CPU:
311             v3_deinit_svm_io_map(vm);
312             v3_deinit_svm_msr_map(vm);
313             break;
314 #endif
315 #ifdef V3_CONFIG_VMX
316         case V3_VMX_CPU:
317         case V3_VMX_EPT_CPU:
318         case V3_VMX_EPT_UG_CPU:
319             v3_deinit_vmx_io_map(vm);
320             v3_deinit_vmx_msr_map(vm);
321             break;
322 #endif
323         default:
324             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
325             return -1;
326     }
327
328     v3_deinit_dev_mgr(vm);
329
330     v3_deinit_time_vm(vm);
331
332     v3_deinit_mem_hooks(vm);
333     v3_delete_mem_map(vm);
334     v3_deinit_shdw_impl(vm);
335
336     v3_deinit_ext_manager(vm);
337     v3_deinit_intr_routers(vm);
338     v3_deinit_host_events(vm);
339
340     v3_deinit_barrier(vm);
341
342     v3_deinit_cpuid_map(vm);
343     v3_deinit_msr_map(vm);
344     v3_deinit_io_map(vm);
345     v3_deinit_hypercall_map(vm);
346
347     v3_deinit_exit_hooks(vm);
348
349 #ifdef V3_CONFIG_TELEMETRY
350     v3_deinit_telemetry(vm);
351 #endif
352
353     v3_deinit_events(vm);
354
355
356     return 0;
357 }
358
359
360 int v3_init_core(struct guest_info * core) {
361     extern v3_cpu_arch_t v3_mach_type;
362     struct v3_vm_info * vm = core->vm_info;
363
364
365
366     /*
367      * Initialize the subsystem data strutures
368      */
369 #ifdef V3_CONFIG_TELEMETRY
370     v3_init_core_telemetry(core);
371 #endif
372
373     if (core->shdw_pg_mode == SHADOW_PAGING) {
374         v3_init_shdw_pg_state(core);
375     }
376
377     v3_init_time_core(core);
378     v3_init_intr_controllers(core);
379     v3_init_exception_state(core);
380
381     v3_init_decoder(core);
382
383
384 #ifdef V3_CONFIG_SYMBIOTIC
385     v3_init_symbiotic_core(core);
386 #endif
387
388     // init SVM/VMX
389
390
391     switch (v3_mach_type) {
392 #ifdef V3_CONFIG_SVM
393         case V3_SVM_CPU:
394         case V3_SVM_REV3_CPU:
395             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
396                 PrintError("Error in SVM initialization\n");
397                 return -1;
398             }
399             break;
400 #endif
401 #ifdef V3_CONFIG_VMX
402         case V3_VMX_CPU:
403         case V3_VMX_EPT_CPU:
404         case V3_VMX_EPT_UG_CPU:
405             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
406                 PrintError("Error in VMX initialization\n");
407                 return -1;
408             }
409             break;
410 #endif
411         default:
412             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
413             return -1;
414     }
415     
416     v3_init_exit_hooks_core(core);
417
418
419     return 0;
420 }
421
422
423
424 int v3_free_core(struct guest_info * core) {
425     extern v3_cpu_arch_t v3_mach_type;
426
427     
428 #ifdef V3_CONFIG_SYMBIOTIC
429     v3_deinit_symbiotic_core(core);
430 #endif
431
432     v3_deinit_decoder(core);
433
434     v3_deinit_intr_controllers(core);
435     v3_deinit_time_core(core);
436
437     if (core->shdw_pg_mode == SHADOW_PAGING) {
438         v3_deinit_shdw_pg_state(core);
439     }
440
441     v3_free_passthrough_pts(core);
442
443 #ifdef V3_CONFIG_TELEMETRY
444     v3_deinit_core_telemetry(core);
445 #endif
446
447     switch (v3_mach_type) {
448 #ifdef V3_CONFIG_SVM
449         case V3_SVM_CPU:
450         case V3_SVM_REV3_CPU:
451             if (v3_deinit_svm_vmcb(core) == -1) {
452                 PrintError("Error in SVM initialization\n");
453                 return -1;
454             }
455             break;
456 #endif
457 #ifdef V3_CONFIG_VMX
458         case V3_VMX_CPU:
459         case V3_VMX_EPT_CPU:
460         case V3_VMX_EPT_UG_CPU:
461             if (v3_deinit_vmx_vmcs(core) == -1) {
462                 PrintError("Error in VMX initialization\n");
463                 return -1;
464             }
465             break;
466 #endif
467         default:
468             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
469             return -1;
470     }
471
472     return 0;
473 }
474
475
476