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 cleanup for Palacios extensions, add per-core data to extensions
[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_ext_manager(vm);
333     v3_deinit_intr_routers(vm);
334     v3_deinit_host_events(vm);
335
336     v3_deinit_barrier(vm);
337
338     v3_deinit_cpuid_map(vm);
339     v3_deinit_msr_map(vm);
340     v3_deinit_io_map(vm);
341     v3_deinit_hypercall_map(vm);
342
343 #ifdef V3_CONFIG_TELEMETRY
344     v3_deinit_telemetry(vm);
345 #endif
346
347
348
349     return 0;
350 }
351
352
353 int v3_init_core(struct guest_info * core) {
354     extern v3_cpu_arch_t v3_mach_type;
355     struct v3_vm_info * vm = core->vm_info;
356
357
358
359     /*
360      * Initialize the subsystem data strutures
361      */
362 #ifdef V3_CONFIG_TELEMETRY
363     v3_init_core_telemetry(core);
364 #endif
365
366     if (core->shdw_pg_mode == SHADOW_PAGING) {
367         v3_init_shdw_pg_state(core);
368     }
369
370     v3_init_time_core(core);
371     v3_init_intr_controllers(core);
372     v3_init_exception_state(core);
373
374     v3_init_decoder(core);
375
376
377 #ifdef V3_CONFIG_SYMBIOTIC
378     v3_init_symbiotic_core(core);
379 #endif
380
381     // init SVM/VMX
382
383
384     switch (v3_mach_type) {
385 #ifdef V3_CONFIG_SVM
386         case V3_SVM_CPU:
387         case V3_SVM_REV3_CPU:
388             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
389                 PrintError("Error in SVM initialization\n");
390                 return -1;
391             }
392             break;
393 #endif
394 #ifdef V3_CONFIG_VMX
395         case V3_VMX_CPU:
396         case V3_VMX_EPT_CPU:
397         case V3_VMX_EPT_UG_CPU:
398             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
399                 PrintError("Error in VMX initialization\n");
400                 return -1;
401             }
402             break;
403 #endif
404         default:
405             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
406             return -1;
407     }
408
409     return 0;
410 }
411
412
413
414 int v3_free_core(struct guest_info * core) {
415     extern v3_cpu_arch_t v3_mach_type;
416
417     
418 #ifdef V3_CONFIG_SYMBIOTIC
419     v3_deinit_symbiotic_core(core);
420 #endif
421
422     v3_deinit_decoder(core);
423
424     v3_deinit_intr_controllers(core);
425     v3_deinit_time_core(core);
426
427     if (core->shdw_pg_mode == SHADOW_PAGING) {
428         v3_deinit_shdw_pg_state(core);
429     }
430
431     v3_free_passthrough_pts(core);
432
433 #ifdef V3_CONFIG_TELEMETRY
434     v3_deinit_core_telemetry(core);
435 #endif
436
437     switch (v3_mach_type) {
438 #ifdef V3_CONFIG_SVM
439         case V3_SVM_CPU:
440         case V3_SVM_REV3_CPU:
441             if (v3_deinit_svm_vmcb(core) == -1) {
442                 PrintError("Error in SVM initialization\n");
443                 return -1;
444             }
445             break;
446 #endif
447 #ifdef V3_CONFIG_VMX
448         case V3_VMX_CPU:
449         case V3_VMX_EPT_CPU:
450         case V3_VMX_EPT_UG_CPU:
451             if (v3_deinit_vmx_vmcs(core) == -1) {
452                 PrintError("Error in VMX initialization\n");
453                 return -1;
454             }
455             break;
456 #endif
457         default:
458             PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
459             return -1;
460     }
461
462     return 0;
463 }
464
465
466