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.


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