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.


44673cb0403337e7ff68160bbb35637a92499da5
[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
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 guest_info * info) {
164     struct v3_segments * segs = &(info->segments);
165     int i = 0;
166     struct v3_segment * seg_ptr;
167
168     seg_ptr=(struct v3_segment *)segs;
169   
170     char *seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL};
171     V3_Print("Segments\n");
172
173     for (i = 0; seg_names[i] != NULL; i++) {
174
175         V3_Print("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, 
176                    (void *)(addr_t)seg_ptr[i].base, seg_ptr[i].limit,
177                    seg_ptr[i].long_mode, seg_ptr[i].db);
178
179     }
180 }
181
182 //
183 // We don't handle those fancy 64 bit system segments...
184 //
185 int v3_translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg) {
186     struct v3_segment * gdt = &(info->segments.gdtr);
187     addr_t gdt_addr = 0;
188     uint16_t seg_offset = (selector & ~0x7);
189     addr_t seg_addr = 0;
190     struct gen_segment * gen_seg = NULL;
191     struct seg_selector sel;
192
193     memset(seg, 0, sizeof(struct v3_segment));
194
195     sel.value = selector;
196
197     if (sel.ti == 1) {
198         PrintError("LDT translations not supported\n");
199         return -1;
200     }
201
202     if (guest_va_to_host_va(info, gdt->base, &gdt_addr) == -1) {
203         PrintError("Unable to translate GDT address\n");
204         return -1;
205     }
206
207     seg_addr = gdt_addr + seg_offset;
208     gen_seg = (struct gen_segment *)seg_addr;
209
210     //translate
211     seg->selector = selector;
212
213     seg->limit = gen_seg->limit_hi;
214     seg->limit <<= 16;
215     seg->limit += gen_seg->limit_lo;
216
217     seg->base = gen_seg->base_hi;
218     seg->base <<= 24;
219     seg->base += gen_seg->base_lo;
220
221     if (gen_seg->granularity == 1) {
222         seg->limit <<= 12;
223         seg->limit |= 0xfff;
224     }
225
226     seg->type = gen_seg->type;
227     seg->system = gen_seg->system;
228     seg->dpl = gen_seg->dpl;
229     seg->present = gen_seg->present;
230     seg->avail = gen_seg->avail;
231     seg->long_mode = gen_seg->long_mode;
232     seg->db = gen_seg->db;
233     seg->granularity = gen_seg->granularity;
234     
235     return 0;
236 }
237
238
239
240
241 void v3_print_ctrl_regs(struct guest_info * info) {
242     struct v3_ctrl_regs * regs = &(info->ctrl_regs);
243     int i = 0;
244     v3_reg_t * reg_ptr;
245     char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", NULL};
246     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(info->vmm_data);
247
248     reg_ptr = (v3_reg_t *)regs;
249
250     V3_Print("32 bit Ctrl Regs:\n");
251
252     for (i = 0; reg_names[i] != NULL; i++) {
253         V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
254     }
255
256     V3_Print("\tEFER=0x%p\n", (void*)(addr_t)(guest_state->efer));
257
258 }
259
260
261 void v3_print_guest_state(struct guest_info * info) {
262     addr_t linear_addr = 0; 
263
264     V3_Print("RIP: %p\n", (void *)(addr_t)(info->rip));
265     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
266     V3_Print("RIP Linear: %p\n", (void *)linear_addr);
267
268     V3_Print("NumExits: %u\n", (uint32_t)info->num_exits);
269
270     v3_print_segments(info);
271     v3_print_ctrl_regs(info);
272
273     if (info->shdw_pg_mode == SHADOW_PAGING) {
274         V3_Print("Shadow Paging Guest Registers:\n");
275         V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
276         V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
277         V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value));
278         // CR4
279     }
280     v3_print_GPRs(info);
281
282     v3_print_stack(info);
283 }
284
285
286 void v3_print_stack(struct guest_info * info) {
287     addr_t linear_addr = 0;
288     addr_t host_addr = 0;
289     int i = 0;
290     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
291
292
293     linear_addr = get_addr_linear(info, info->vm_regs.rsp, &(info->segments.ss));
294  
295     V3_Print("Stack  at %p:\n", (void *)linear_addr);
296    
297     if (info->mem_mode == PHYSICAL_MEM) {
298         if (guest_pa_to_host_va(info, linear_addr, &host_addr) == -1) {
299             PrintError("Could not translate Stack address\n");
300             return;
301         }
302     } else if (info->mem_mode == VIRTUAL_MEM) {
303         if (guest_va_to_host_va(info, linear_addr, &host_addr) == -1) {
304             PrintError("Could not translate Virtual Stack address\n");
305             return;
306         }
307     }
308     
309     V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr);
310  
311     // We start i at one because the current stack pointer points to an unused stack element
312     for (i = 0; i <= 24; i++) {
313         if (cpu_mode == LONG) {
314             V3_Print("\t%p\n", (void *)*(uint64_t *)(host_addr + (i * 8)));
315         } else if (cpu_mode == REAL) {
316             V3_Print("Don't currently handle 16 bit stacks... \n");
317         } else {
318             // 32 bit stacks...
319             V3_Print("\t%.8x\n", *(uint32_t *)(host_addr + (i * 4)));
320         }
321     }
322
323 }    
324
325 #ifdef __V3_32BIT__
326
327 void v3_print_GPRs(struct guest_info * info) {
328     struct v3_gprs * regs = &(info->vm_regs);
329     int i = 0;
330     v3_reg_t * reg_ptr;
331     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
332
333     reg_ptr= (v3_reg_t *)regs;
334
335     V3_Print("32 bit GPRs:\n");
336
337     for (i = 0; reg_names[i] != NULL; i++) {
338         V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
339     }
340 }
341
342 #elif __V3_64BIT__
343
344 void v3_print_GPRs(struct guest_info * info) {
345     struct v3_gprs * regs = &(info->vm_regs);
346     int i = 0;
347     v3_reg_t * reg_ptr;
348     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
349                            "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
350
351     reg_ptr = (v3_reg_t *)regs;
352
353     V3_Print("64 bit GPRs:\n");
354
355     for (i = 0; reg_names[i] != NULL; i++) {
356         V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
357     }
358 }
359
360 #endif