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