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.


hook F10 to state dumping
[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
29
30 v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
31     struct cr0_32 * cr0;
32     struct efer_64 * efer;
33     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
34     struct v3_segment * cs = &(info->segments.cs);
35     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
36
37     if (info->shdw_pg_mode == SHADOW_PAGING) {
38         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
39         efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
40     } else if (info->shdw_pg_mode == NESTED_PAGING) {
41         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
42         efer = (struct efer_64 *)&(guest_state->efer);
43     } else {
44         PrintError("Invalid Paging Mode...\n");
45         V3_ASSERT(0);
46         return -1;
47     }
48
49     if (cr0->pe == 0) {
50         return REAL;
51     } else if ((cr4->pae == 0) && (efer->lme == 0)) {
52         return PROTECTED;
53     } else if (efer->lme == 0) {
54         return PROTECTED_PAE;
55     } else if ((efer->lme == 1) && (cs->long_mode == 1)) {
56         return LONG;
57     } else {
58         // What about LONG_16_COMPAT???
59         return LONG_32_COMPAT;
60     }
61 }
62
63 // Get address width in bytes
64 uint_t v3_get_addr_width(struct guest_info * info) {
65     struct cr0_32 * cr0;
66     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
67     struct efer_64 * efer;
68     struct v3_segment * cs = &(info->segments.cs);
69     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
70
71     if (info->shdw_pg_mode == SHADOW_PAGING) {
72         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
73         efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
74     } else if (info->shdw_pg_mode == NESTED_PAGING) {
75         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
76         efer = (struct efer_64 *)&(guest_state->efer);
77     } else {
78         PrintError("Invalid Paging Mode...\n");
79         V3_ASSERT(0);
80         return -1;
81     }
82
83     if (cr0->pe == 0) {
84         return 2;
85     } else if ((cr4->pae == 0) && (efer->lme == 0)) {
86         return 4;
87     } else if (efer->lme == 0) {
88         return 4;
89     } else if ((efer->lme == 1) && (cs->long_mode == 1)) {
90         return 8;
91     } else {
92         // What about LONG_16_COMPAT???
93         return 4;
94     }
95 }
96
97
98 static const uchar_t REAL_STR[] = "Real";
99 static const uchar_t PROTECTED_STR[] = "Protected";
100 static const uchar_t PROTECTED_PAE_STR[] = "Protected+PAE";
101 static const uchar_t LONG_STR[] = "Long";
102 static const uchar_t LONG_32_COMPAT_STR[] = "32bit Compat";
103 static const uchar_t LONG_16_COMPAT_STR[] = "16bit Compat";
104
105 const uchar_t * v3_cpu_mode_to_str(v3_cpu_mode_t mode) {
106     switch (mode) {
107         case REAL:
108             return REAL_STR;
109         case PROTECTED:
110             return PROTECTED_STR;
111         case PROTECTED_PAE:
112             return PROTECTED_PAE_STR;
113         case LONG:
114             return LONG_STR;
115         case LONG_32_COMPAT:
116             return LONG_32_COMPAT_STR;
117         case LONG_16_COMPAT:
118             return LONG_16_COMPAT_STR;
119         default:
120             return NULL;
121     }
122 }
123
124 v3_mem_mode_t v3_get_vm_mem_mode(struct guest_info * info) {
125     struct cr0_32 * cr0;
126
127     if (info->shdw_pg_mode == SHADOW_PAGING) {
128         cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
129     } else if (info->shdw_pg_mode == NESTED_PAGING) {
130         cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
131     } else {
132         PrintError("Invalid Paging Mode...\n");
133         V3_ASSERT(0);
134         return -1;
135     }
136
137     if (cr0->pg == 0) {
138         return PHYSICAL_MEM;
139     } else {
140         return VIRTUAL_MEM;
141     }
142 }
143
144 static const uchar_t PHYS_MEM_STR[] = "Physical Memory";
145 static const uchar_t VIRT_MEM_STR[] = "Virtual Memory";
146
147 const uchar_t * v3_mem_mode_to_str(v3_mem_mode_t mode) {
148     switch (mode) {
149         case PHYSICAL_MEM:
150             return PHYS_MEM_STR;
151         case VIRTUAL_MEM:
152             return VIRT_MEM_STR;
153         default:
154             return NULL;
155     }
156 }
157
158
159 void v3_print_segments(struct guest_info * info) {
160     struct v3_segments * segs = &(info->segments);
161     int i = 0;
162     struct v3_segment * seg_ptr;
163
164     seg_ptr=(struct v3_segment *)segs;
165   
166     char *seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL};
167     PrintDebug("Segments\n");
168
169     for (i = 0; seg_names[i] != NULL; i++) {
170
171         PrintDebug("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, 
172                    (void *)(addr_t)seg_ptr[i].base, seg_ptr[i].limit,
173                    seg_ptr[i].long_mode, seg_ptr[i].db);
174
175     }
176
177 }
178
179
180 void v3_print_ctrl_regs(struct guest_info * info) {
181     struct v3_ctrl_regs * regs = &(info->ctrl_regs);
182     int i = 0;
183     v3_reg_t * reg_ptr;
184     char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", NULL};
185     vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(info->vmm_data);
186
187     reg_ptr = (v3_reg_t *)regs;
188
189     PrintDebug("32 bit Ctrl Regs:\n");
190
191     for (i = 0; reg_names[i] != NULL; i++) {
192         PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
193     }
194
195     PrintDebug("\tEFER=0x%p\n", (void*)(addr_t)(guest_state->efer));
196
197 }
198
199
200 void v3_print_guest_state(struct guest_info * info) {
201     addr_t linear_addr = 0; 
202
203     PrintDebug("RIP: %p\n", (void *)(addr_t)(info->rip));
204     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
205     PrintDebug("RIP Linear: %p\n", (void *)linear_addr);
206
207     v3_print_segments(info);
208     v3_print_ctrl_regs(info);
209
210     if (info->shdw_pg_mode == SHADOW_PAGING) {
211         PrintDebug("Shadow Paging Guest Registers:\n");
212         PrintDebug("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
213         PrintDebug("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
214         PrintDebug("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value));
215         // CR4
216     }
217     v3_print_GPRs(info);
218 }
219
220
221 #ifdef __V3_32BIT__
222 void v3_print_GPRs(struct guest_info * info) {
223     struct v3_gprs * regs = &(info->vm_regs);
224     int i = 0;
225     v3_reg_t * reg_ptr;
226     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
227
228     reg_ptr= (v3_reg_t *)regs;
229
230     PrintDebug("32 bit GPRs:\n");
231
232     for (i = 0; reg_names[i] != NULL; i++) {
233         PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
234     }
235 }
236 #elif __V3_64BIT__
237 void v3_print_GPRs(struct guest_info * info) {
238     struct v3_gprs * regs = &(info->vm_regs);
239     int i = 0;
240     v3_reg_t * reg_ptr;
241     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
242                            "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
243
244     reg_ptr= (v3_reg_t *)regs;
245
246     PrintDebug("64 bit GPRs:\n");
247
248     for (i = 0; reg_names[i] != NULL; i++) {
249         PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);  
250     }
251 }
252
253
254
255 #endif