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 symbiotic interface and a number of other small changes
[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     PrintDebug("Segments\n");
172
173     for (i = 0; seg_names[i] != NULL; i++) {
174
175         PrintDebug("\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     PrintDebug("32 bit Ctrl Regs:\n");
251
252     for (i = 0; reg_names[i] != NULL; i++) {
253         PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
254     }
255
256     PrintDebug("\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     PrintDebug("RIP: %p\n", (void *)(addr_t)(info->rip));
265     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
266     PrintDebug("RIP Linear: %p\n", (void *)linear_addr);
267
268     v3_print_segments(info);
269     v3_print_ctrl_regs(info);
270
271     if (info->shdw_pg_mode == SHADOW_PAGING) {
272         PrintDebug("Shadow Paging Guest Registers:\n");
273         PrintDebug("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
274         PrintDebug("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
275         PrintDebug("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value));
276         // CR4
277     }
278     v3_print_GPRs(info);
279 }
280
281
282 #ifdef __V3_32BIT__
283
284 void v3_print_GPRs(struct guest_info * info) {
285     struct v3_gprs * regs = &(info->vm_regs);
286     int i = 0;
287     v3_reg_t * reg_ptr;
288     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
289
290     reg_ptr= (v3_reg_t *)regs;
291
292     PrintDebug("32 bit GPRs:\n");
293
294     for (i = 0; reg_names[i] != NULL; i++) {
295         PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
296     }
297 }
298
299 #elif __V3_64BIT__
300
301 void v3_print_GPRs(struct guest_info * info) {
302     struct v3_gprs * regs = &(info->vm_regs);
303     int i = 0;
304     v3_reg_t * reg_ptr;
305     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
306                            "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
307
308     reg_ptr= (v3_reg_t *)regs;
309
310     PrintDebug("64 bit GPRs:\n");
311
312     for (i = 0; reg_names[i] != NULL; i++) {
313         PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
314     }
315 }
316
317 #endif