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 configurable host OS thread support
[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_muxer.h>
32
33
34 v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
35     struct cr0_32 * cr0;
36     struct efer_64 * efer;
37     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
38     struct v3_segment * cs = &(info->segments.cs);
39     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
40
41     if (info->shdw_pg_mode == SHADOW_PAGING) {
42         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
43         efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
44     } else if (info->shdw_pg_mode == NESTED_PAGING) {
45         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
46         efer = (struct efer_64 *)&(guest_state->efer);
47     } else {
48         PrintError("Invalid Paging Mode...\n");
49         V3_ASSERT(0);
50         return -1;
51     }
52
53     if (cr0->pe == 0) {
54         return REAL;
55     } else if ((cr4->pae == 0) && (efer->lme == 0)) {
56         return PROTECTED;
57     } else if (efer->lme == 0) {
58         return PROTECTED_PAE;
59     } else if ((efer->lme == 1) && (cs->long_mode == 1)) {
60         return LONG;
61     } else {
62         // What about LONG_16_COMPAT???
63         return LONG_32_COMPAT;
64     }
65 }
66
67 // Get address width in bytes
68 uint_t v3_get_addr_width(struct guest_info * info) {
69     struct cr0_32 * cr0;
70     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
71     struct efer_64 * efer;
72     struct v3_segment * cs = &(info->segments.cs);
73     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
74
75     if (info->shdw_pg_mode == SHADOW_PAGING) {
76         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
77         efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
78     } else if (info->shdw_pg_mode == NESTED_PAGING) {
79         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
80         efer = (struct efer_64 *)&(guest_state->efer);
81     } else {
82         PrintError("Invalid Paging Mode...\n");
83         V3_ASSERT(0);
84         return -1;
85     }
86
87     if (cr0->pe == 0) {
88         return 2;
89     } else if ((cr4->pae == 0) && (efer->lme == 0)) {
90         return 4;
91     } else if (efer->lme == 0) {
92         return 4;
93     } else if ((efer->lme == 1) && (cs->long_mode == 1)) {
94         return 8;
95     } else {
96         // What about LONG_16_COMPAT???
97         return 4;
98     }
99 }
100
101
102 static const uchar_t REAL_STR[] = "Real";
103 static const uchar_t PROTECTED_STR[] = "Protected";
104 static const uchar_t PROTECTED_PAE_STR[] = "Protected+PAE";
105 static const uchar_t LONG_STR[] = "Long";
106 static const uchar_t LONG_32_COMPAT_STR[] = "32bit Compat";
107 static const uchar_t LONG_16_COMPAT_STR[] = "16bit Compat";
108
109 const uchar_t * v3_cpu_mode_to_str(v3_cpu_mode_t mode) {
110     switch (mode) {
111         case REAL:
112             return REAL_STR;
113         case PROTECTED:
114             return PROTECTED_STR;
115         case PROTECTED_PAE:
116             return PROTECTED_PAE_STR;
117         case LONG:
118             return LONG_STR;
119         case LONG_32_COMPAT:
120             return LONG_32_COMPAT_STR;
121         case LONG_16_COMPAT:
122             return LONG_16_COMPAT_STR;
123         default:
124             return NULL;
125     }
126 }
127
128 v3_mem_mode_t v3_get_vm_mem_mode(struct guest_info * info) {
129     struct cr0_32 * cr0;
130
131     if (info->shdw_pg_mode == SHADOW_PAGING) {
132         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
133     } else if (info->shdw_pg_mode == NESTED_PAGING) {
134         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
135     } else {
136         PrintError("Invalid Paging Mode...\n");
137         V3_ASSERT(0);
138         return -1;
139     }
140
141     if (cr0->pg == 0) {
142         return PHYSICAL_MEM;
143     } else {
144         return VIRTUAL_MEM;
145     }
146 }
147
148 static const uchar_t PHYS_MEM_STR[] = "Physical Memory";
149 static const uchar_t VIRT_MEM_STR[] = "Virtual Memory";
150
151 const uchar_t * v3_mem_mode_to_str(v3_mem_mode_t mode) {
152     switch (mode) {
153         case PHYSICAL_MEM:
154             return PHYS_MEM_STR;
155         case VIRTUAL_MEM:
156             return VIRT_MEM_STR;
157         default:
158             return NULL;
159     }
160 }
161
162
163 void v3_print_segments(struct v3_segments * segs) {
164     int i = 0;
165     struct v3_segment * seg_ptr;
166
167     seg_ptr=(struct v3_segment *)segs;
168   
169     char *seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL};
170     V3_Print("Segments\n");
171
172     for (i = 0; seg_names[i] != NULL; i++) {
173
174         V3_Print("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, 
175                    (void *)(addr_t)seg_ptr[i].base, seg_ptr[i].limit,
176                    seg_ptr[i].long_mode, seg_ptr[i].db);
177
178     }
179 }
180
181 //
182 // We don't handle those fancy 64 bit system segments...
183 //
184 int v3_translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg) {
185     struct v3_segment * gdt = &(info->segments.gdtr);
186     addr_t gdt_addr = 0;
187     uint16_t seg_offset = (selector & ~0x7);
188     addr_t seg_addr = 0;
189     struct gen_segment * gen_seg = NULL;
190     struct seg_selector sel;
191
192     memset(seg, 0, sizeof(struct v3_segment));
193
194     sel.value = selector;
195
196     if (sel.ti == 1) {
197         PrintError("LDT translations not supported\n");
198         return -1;
199     }
200
201     if (v3_gva_to_hva(info, gdt->base, &gdt_addr) == -1) {
202         PrintError("Unable to translate GDT address\n");
203         return -1;
204     }
205
206     seg_addr = gdt_addr + seg_offset;
207     gen_seg = (struct gen_segment *)seg_addr;
208
209     //translate
210     seg->selector = selector;
211
212     seg->limit = gen_seg->limit_hi;
213     seg->limit <<= 16;
214     seg->limit += gen_seg->limit_lo;
215
216     seg->base = gen_seg->base_hi;
217     seg->base <<= 24;
218     seg->base += gen_seg->base_lo;
219
220     if (gen_seg->granularity == 1) {
221         seg->limit <<= 12;
222         seg->limit |= 0xfff;
223     }
224
225     seg->type = gen_seg->type;
226     seg->system = gen_seg->system;
227     seg->dpl = gen_seg->dpl;
228     seg->present = gen_seg->present;
229     seg->avail = gen_seg->avail;
230     seg->long_mode = gen_seg->long_mode;
231     seg->db = gen_seg->db;
232     seg->granularity = gen_seg->granularity;
233     
234     return 0;
235 }
236
237
238
239
240 void v3_print_ctrl_regs(struct guest_info * info) {
241     struct v3_ctrl_regs * regs = &(info->ctrl_regs);
242     int i = 0;
243     v3_reg_t * reg_ptr;
244     char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", NULL};
245     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(info->vmm_data);
246
247     reg_ptr = (v3_reg_t *)regs;
248
249     V3_Print("32 bit Ctrl Regs:\n");
250
251     for (i = 0; reg_names[i] != NULL; i++) {
252         V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
253     }
254
255     V3_Print("\tEFER=0x%p\n", (void*)(addr_t)(guest_state->efer));
256
257 }
258
259
260 void v3_print_guest_state(struct guest_info * info) {
261     addr_t linear_addr = 0; 
262
263     V3_Print("RIP: %p\n", (void *)(addr_t)(info->rip));
264     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
265     V3_Print("RIP Linear: %p\n", (void *)linear_addr);
266
267     V3_Print("NumExits: %u\n", (uint32_t)info->num_exits);
268
269     v3_print_segments(&(info->segments));
270     v3_print_ctrl_regs(info);
271
272     if (info->shdw_pg_mode == SHADOW_PAGING) {
273         V3_Print("Shadow Paging Guest Registers:\n");
274         V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
275         V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
276         V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value));
277         // CR4
278     }
279     v3_print_GPRs(info);
280
281     v3_print_mem_map(info->vm_info);
282
283     v3_print_stack(info);
284 }
285
286
287 void v3_print_stack(struct guest_info * info) {
288     addr_t linear_addr = 0;
289     addr_t host_addr = 0;
290     int i = 0;
291     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
292
293
294     linear_addr = get_addr_linear(info, info->vm_regs.rsp, &(info->segments.ss));
295  
296     V3_Print("Stack  at %p:\n", (void *)linear_addr);
297    
298     if (info->mem_mode == PHYSICAL_MEM) {
299         if (v3_gpa_to_hva(info, linear_addr, &host_addr) == -1) {
300             PrintError("Could not translate Stack address\n");
301             return;
302         }
303     } else if (info->mem_mode == VIRTUAL_MEM) {
304         if (v3_gva_to_hva(info, linear_addr, &host_addr) == -1) {
305             PrintError("Could not translate Virtual Stack address\n");
306             return;
307         }
308     }
309     
310     V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr);
311  
312     // We start i at one because the current stack pointer points to an unused stack element
313     for (i = 0; i <= 24; i++) {
314         if (cpu_mode == LONG) {
315             V3_Print("\t%p\n", (void *)*(addr_t *)(host_addr + (i * 8)));
316         } else if (cpu_mode == REAL) {
317             V3_Print("Don't currently handle 16 bit stacks... \n");
318         } else {
319             // 32 bit stacks...
320             V3_Print("\t%.8x\n", *(uint32_t *)(host_addr + (i * 4)));
321         }
322     }
323
324 }    
325
326 #ifdef __V3_32BIT__
327
328 void v3_print_GPRs(struct guest_info * info) {
329     struct v3_gprs * regs = &(info->vm_regs);
330     int i = 0;
331     v3_reg_t * reg_ptr;
332     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
333
334     reg_ptr= (v3_reg_t *)regs;
335
336     V3_Print("32 bit GPRs:\n");
337
338     for (i = 0; reg_names[i] != NULL; i++) {
339         V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
340     }
341 }
342
343 #elif __V3_64BIT__
344
345 void v3_print_GPRs(struct guest_info * info) {
346     struct v3_gprs * regs = &(info->vm_regs);
347     int i = 0;
348     v3_reg_t * reg_ptr;
349     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
350                            "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
351
352     reg_ptr = (v3_reg_t *)regs;
353
354     V3_Print("64 bit GPRs:\n");
355
356     for (i = 0; reg_names[i] != NULL; i++) {
357         V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
358     }
359 }
360
361 #endif
362
363
364 #include <palacios/vmcs.h>
365 #include <palacios/vmcb.h>
366 static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_data) {
367     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
368     int cpu_valid = 0;
369
370     v3_print_guest_state(core);
371     
372     // init SVM/VMX
373 #ifdef CONFIG_SVM
374     if ((cpu_type == V3_SVM_CPU) || (cpu_type == V3_SVM_REV3_CPU)) {
375         cpu_valid = 1;
376         PrintDebugVMCB((vmcb_t *)(core->vmm_data));
377     }
378 #endif
379 #ifdef CONFIG_VMX
380     if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_CPU)) {
381         cpu_valid = 1;
382         v3_print_vmcs();
383     }
384 #endif
385     if (!cpu_valid) {
386         PrintError("Invalid CPU Type 0x%x\n", cpu_type);
387         return -1;
388     }
389     
390
391     return 0;
392 }
393
394
395 #ifdef CONFIG_SVM
396 #include <palacios/svm.h>
397 #include <palacios/svm_io.h>
398 #include <palacios/svm_msr.h>
399 #endif
400
401 #ifdef CONFIG_VMX
402 #include <palacios/vmx.h>
403 #include <palacios/vmx_io.h>
404 #include <palacios/vmx_msr.h>
405 #endif
406
407
408 int v3_init_vm(struct v3_vm_info * vm) {
409     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
410     int cpu_valid = 0;
411
412     if (v3_get_foreground_vm() == NULL) {
413         v3_set_foreground_vm(vm);
414     }
415
416 #ifdef CONFIG_TELEMETRY
417     v3_init_telemetry(vm);
418 #endif
419
420     v3_init_hypercall_map(vm);
421     v3_init_io_map(vm);
422     v3_init_msr_map(vm);
423     v3_init_cpuid_map(vm);
424     v3_init_host_events(vm);
425     v3_init_intr_routers(vm);
426
427     // Initialize the memory map
428     if (v3_init_mem_map(vm) == -1) {
429         PrintError("Could not initialize shadow map\n");
430         return -1;
431     }
432
433     v3_init_mem_hooks(vm);
434
435     if (v3_init_shdw_impl(vm) == -1) {
436         PrintError("VM initialization error in shadow implementaion\n");
437         return -1;
438     }
439
440
441
442 #ifdef CONFIG_SYMBIOTIC
443     v3_init_symbiotic_vm(vm);
444 #endif
445
446     v3_init_dev_mgr(vm);
447
448
449     // init SVM/VMX
450 #ifdef CONFIG_SVM
451     if ((cpu_type == V3_SVM_CPU) || (cpu_type == V3_SVM_REV3_CPU)) {
452         v3_init_svm_io_map(vm);
453         v3_init_svm_msr_map(vm);
454         cpu_valid = 1;
455     } 
456 #endif
457 #ifdef CONFIG_VMX
458     if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_CPU)) {
459         v3_init_vmx_io_map(vm);
460         v3_init_vmx_msr_map(vm);
461         cpu_valid = 1;
462     }
463 #endif
464     if (!cpu_valid) {
465         PrintError("Invalid CPU Type 0x%x\n", cpu_type);
466         return -1;
467     }
468     
469     v3_register_hypercall(vm, GUEST_INFO_HCALL, info_hcall, NULL);
470
471     V3_Print("GUEST_INFO_HCALL=%x\n", GUEST_INFO_HCALL);
472
473     return 0;
474 }
475
476 int v3_init_core(struct guest_info * core) {
477     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
478     struct v3_vm_info * vm = core->vm_info;
479
480     /*
481      * Initialize the subsystem data strutures
482      */
483 #ifdef CONFIG_TELEMETRY
484     v3_init_core_telemetry(core);
485 #endif
486
487     if (core->shdw_pg_mode == SHADOW_PAGING) {
488         v3_init_shdw_pg_state(core);
489     }
490
491     v3_init_time(core);
492     v3_init_intr_controllers(core);
493     v3_init_exception_state(core);
494
495     v3_init_decoder(core);
496
497
498 #ifdef CONFIG_SYMBIOTIC
499     v3_init_symbiotic_core(core);
500 #endif
501
502     // init SVM/VMX
503
504
505     switch (cpu_type) {
506 #ifdef CONFIG_SVM
507         case V3_SVM_CPU:
508         case V3_SVM_REV3_CPU:
509             if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
510                 PrintError("Error in SVM initialization\n");
511                 return -1;
512             }
513             break;
514 #endif
515 #ifdef CONFIG_VMX
516         case V3_VMX_CPU:
517         case V3_VMX_EPT_CPU:
518             if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
519                 PrintError("Error in VMX initialization\n");
520                 return -1;
521             }
522             break;
523 #endif
524         default:
525             PrintError("Invalid CPU Type 0x%x\n", cpu_type);
526             return -1;
527     }
528
529     return 0;
530 }