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.


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