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 emulator
[palacios.git] / palacios / src / palacios / vmm_ctrl_regs.c
1 #include <palacios/vmm_mem.h>
2 #include <palacios/vmm.h>
3 #include <palacios/vmcb.h>
4 #include <palacios/vmm_decoder.h>
5 #include <palacios/vm_guest_mem.h>
6 #include <palacios/vmm_ctrl_regs.h>
7
8
9
10 /* Segmentation is a problem here...
11  *
12  * When we get a memory operand, presumably we use the default segment (which is?) 
13  * unless an alternate segment was specfied in the prefix...
14  */
15
16
17 #ifndef DEBUG_CTRL_REGS
18 #undef PrintDebug
19 #define PrintDebug(fmt, args...)
20 #endif
21
22
23 // Set to 1 if CR3 reload with same value shall not
24 // force a shadow page table flush
25 // It makes windows loading MUCH faster. 
26 // Note that this optimization appears to fail with a 2.6 linux kernel
27 #define CR3_RELOAD_OPTIMIZATION 0
28
29
30
31
32
33
34
35 // First Attempt = 494 lines
36 // current = 106 lines
37 int handle_cr0_write(struct guest_info * info) {
38   char instr[15];
39   int ret;
40   struct x86_instr dec_instr;
41
42   if (info->mem_mode == PHYSICAL_MEM) { 
43     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
44   } else { 
45     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
46   }
47
48   /* The IFetch will already have faulted in the necessary bytes for the full instruction
49     if (ret != 15) {
50     // I think we should inject a GPF into the guest
51     PrintError("Could not read instruction (ret=%d)\n", ret);
52     return -1;
53     }
54   */
55
56   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
57     PrintError("Could not decode instruction\n");
58     return -1;
59   }
60
61
62   if (opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
63     struct cr0_real *real_cr0  = (struct cr0_real*)&(info->ctrl_regs.cr0);
64     struct cr0_real *new_cr0 = (struct cr0_real *)(dec_instr.src_operand.operand);      
65     uchar_t new_cr0_val;
66
67     PrintDebug("LMSW\n");
68
69     new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
70     
71     PrintDebug("OperandVal = %x\n", new_cr0_val);
72
73     PrintDebug("Old CR0=%x\n", *real_cr0);      
74     *(uchar_t*)real_cr0 &= 0xf0;
75     *(uchar_t*)real_cr0 |= new_cr0_val;
76     PrintDebug("New CR0=%x\n", *real_cr0);      
77       
78
79     if (info->shdw_pg_mode == SHADOW_PAGING) {
80       struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
81       
82       PrintDebug(" Old Shadow CR0=%x\n", *shadow_cr0);  
83       *(uchar_t*)shadow_cr0 &= 0xf0;
84       *(uchar_t*)shadow_cr0 |= new_cr0_val;
85       PrintDebug("New Shadow CR0=%x\n", *shadow_cr0);   
86     }
87   } else if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
88     PrintDebug("MOV2CR0\n");
89
90     if (info->cpu_mode == LONG) {
91       // 64 bit registers
92     } else {
93       // 32 bit registers
94         struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
95         struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.src_operand.operand);
96
97         PrintDebug("OperandVal = %x, length=%d\n", *new_cr0, dec_instr_src_operand.size);
98
99
100         PrintDebug("Old CR0=%x\n", *real_cr0);
101         *real_cr0 = *new_cr0;
102         
103
104         if (info->shdw_pg_mode == SHADOW_PAGING) {
105           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
106           
107           PrintDebug("Old Shadow CR0=%x\n", *shadow_cr0);       
108           
109           real_cr0->et = 1;
110           
111           *shadow_cr0 = *new_cr0;
112           shadow_cr0->et = 1;
113           
114           if (get_mem_mode(info) == VIRTUAL_MEM) {
115             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
116             
117             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
118           } else  {
119             info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
120             real_cr0->pg = 1;
121           }
122           
123           PrintDebug("New Shadow CR0=%x\n",*shadow_cr0);
124         }
125         PrintDebug("New CR0=%x\n", *real_cr0);
126     }
127
128   } else if (opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
129     // CLTS
130     struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
131         
132     real_cr0->ts = 0;
133
134     if (info->shdw_pg_mode == SHADOW_PAGING) {
135       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
136       shadow_cr0->ts = 0;
137     }
138   } else {
139     PrintError("Unhandled opcode in handle_cr0_write\n");
140     return -1;
141   }
142
143   info->rip += dec_instr.instr_length;
144
145   return 0;
146 }
147
148
149 // First attempt = 253 lines
150 // current = 51 lines
151 int handle_cr0_read(struct guest_info * info) {
152   char instr[15];
153   int ret;
154   struct x86_instr dec_instr;
155
156   if (info->mem_mode == PHYSICAL_MEM) { 
157     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
158   } else { 
159     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
160   }
161
162   /* The IFetch will already have faulted in the necessary bytes for the full instruction
163      if (ret != 15) {
164      // I think we should inject a GPF into the guest
165      PrintError("Could not read instruction (ret=%d)\n", ret);
166      return -1;
167      }
168   */
169
170   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
171     PrintError("Could not decode instruction\n");
172     return -1;
173   }
174   
175   if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
176     struct cr0_32 * virt_cr0 = (struct cr0_32 *)(dec_instr.dst_operand.operand);
177     struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
178     
179     PrintDebug("MOVCR2\n");
180     PrintDebug("CR0 at 0x%x\n", real_cr0);
181
182     if (info->shdw_pg_mode == SHADOW_PAGING) {
183       *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
184     } else {
185       *virt_cr0 = *real_cr0;
186     }
187     
188     PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
189     PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
190   } else if (opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
191     struct cr0_real *real_cr0= (struct cr0_real*)&(info->ctrl_regs.cr0);
192     struct cr0_real *virt_cr0 = (struct cr0_real *)(dec_instr.dst_operand.operand);
193     char cr0_val = *(char*)real_cr0 & 0x0f;
194     
195     PrintDebug("SMSW\n");
196
197     PrintDebug("CR0 at 0x%x\n", real_cr0);
198
199     *(char *)virt_cr0 &= 0xf0;
200     *(char *)virt_cr0 |= cr0_val;
201     
202   } else {
203     PrintError("Unhandled opcode in handle_cr0_read\n");
204     return -1;
205   }
206
207   info->rip += dec_instr.instr_length;
208
209   return 0;
210 }
211
212
213
214 // First Attemp = 256 lines
215 // current = 65 lines
216 int handle_cr3_write(struct guest_info * info) {
217   int ret;
218   char instr[15];
219   struct x86_instr dec_instr;
220
221   if (info->mem_mode == PHYSICAL_MEM) { 
222     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
223   } else { 
224     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
225   }
226
227   /* The IFetch will already have faulted in the necessary bytes for the full instruction
228      if (ret != 15) {
229      // I think we should inject a GPF into the guest
230      PrintError("Could not read instruction (ret=%d)\n", ret);
231      return -1;
232      }
233   */
234
235   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
236     PrintError("Could not decode instruction\n");
237     return -1;
238   }
239
240   if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
241
242     PrintDebug("MOV2CR3\n");
243
244     PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
245
246     if (info->shdw_pg_mode == SHADOW_PAGING) {
247       struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);       
248       struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
249       struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
250       
251       PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
252                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
253       
254       if (!CR3_RELOAD_OPTIMIZATION || !CR3_32_SAME_BASE(new_cr3, guest_cr3)) { 
255         addr_t shadow_pt;
256
257         
258         PrintDebug("New CR3 is different - flushing shadow page table\n");      
259         
260         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
261         
262         shadow_pt =  create_new_shadow_pt32();
263         
264         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);    
265       } 
266       
267       shadow_cr3->pwt = new_cr3->pwt;
268       shadow_cr3->pcd = new_cr3->pcd;
269       
270       // What the hell...
271       *guest_cr3 = *new_cr3;
272       
273       PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
274                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
275
276       if (info->mem_mode == VIRTUAL_MEM) {
277         // If we aren't in paged mode then we have to preserve the identity mapped CR3
278         info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
279       }
280     }
281   } else {
282     PrintError("Unhandled opcode in handle_cr3_write\n");
283     return -1;
284   }
285
286   info->rip += dec_instr.instr_length;
287
288   return 0;
289 }
290
291
292
293 // first attempt = 156 lines
294 // current = 36 lines
295 int handle_cr3_read(struct guest_info * info) {
296   char instr[15];
297   int ret;
298   struct x86_instr dec_instr;
299
300   if (info->mem_mode == PHYSICAL_MEM) { 
301     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
302   } else { 
303     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
304   }
305
306   /* The IFetch will already have faulted in the necessary bytes for the full instruction
307      if (ret != 15) {
308      // I think we should inject a GPF into the guest
309      PrintError("Could not read instruction (ret=%d)\n", ret);
310      return -1;
311      }
312   */
313
314   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
315     PrintError("Could not decode instruction\n");
316     return -1;
317   }
318
319   if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
320     PrintDebug("MOVCR32\n");
321     struct cr3_32 * virt_cr3 = (struct cr3_32 *)(dec_instr.dst_operand.operand);
322
323     PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
324
325     if (info->shdw_pg_mode == SHADOW_PAGING) {
326       *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
327     } else {
328       *virt_cr3 = *(struct cr3_32 *)&(info->ctrl_regs.cr3);
329     }
330   } else {
331     PrintError("Unhandled opcode in handle_cr3_read\n");
332     return -1;
333   }
334
335
336   info->rip += dec_instr.instr_length;
337
338   return 0;
339 }