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