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 copyright tags
[palacios.git] / palacios / src / palacios / vmm_ctrl_regs.c
1 /* Northwestern University */
2 /* (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> */
3
4 #include <palacios/vmm_mem.h>
5 #include <palacios/vmm.h>
6 #include <palacios/vmcb.h>
7 #include <palacios/vmm_decoder.h>
8 #include <palacios/vm_guest_mem.h>
9 #include <palacios/vmm_ctrl_regs.h>
10
11
12
13 /* Segmentation is a problem here...
14  *
15  * When we get a memory operand, presumably we use the default segment (which is?) 
16  * unless an alternate segment was specfied in the prefix...
17  */
18
19
20 #ifndef DEBUG_CTRL_REGS
21 #undef PrintDebug
22 #define PrintDebug(fmt, args...)
23 #endif
24
25
26 // First Attempt = 494 lines
27 // current = 106 lines
28 int handle_cr0_write(struct guest_info * info) {
29   char instr[15];
30   int ret;
31   struct x86_instr dec_instr;
32
33   if (info->mem_mode == PHYSICAL_MEM) { 
34     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
35   } else { 
36     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
37   }
38
39   /* The IFetch will already have faulted in the necessary bytes for the full instruction
40     if (ret != 15) {
41     // I think we should inject a GPF into the guest
42     PrintError("Could not read instruction (ret=%d)\n", ret);
43     return -1;
44     }
45   */
46
47   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
48     PrintError("Could not decode instruction\n");
49     return -1;
50   }
51
52
53   if (opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
54     struct cr0_real *real_cr0  = (struct cr0_real*)&(info->ctrl_regs.cr0);
55     struct cr0_real *new_cr0 = (struct cr0_real *)(dec_instr.src_operand.operand);      
56     uchar_t new_cr0_val;
57
58     PrintDebug("LMSW\n");
59
60     new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
61     
62     PrintDebug("OperandVal = %x\n", new_cr0_val);
63
64     PrintDebug("Old CR0=%x\n", *real_cr0);      
65     *(uchar_t*)real_cr0 &= 0xf0;
66     *(uchar_t*)real_cr0 |= new_cr0_val;
67     PrintDebug("New CR0=%x\n", *real_cr0);      
68       
69
70     if (info->shdw_pg_mode == SHADOW_PAGING) {
71       struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
72       
73       PrintDebug(" Old Shadow CR0=%x\n", *shadow_cr0);  
74       *(uchar_t*)shadow_cr0 &= 0xf0;
75       *(uchar_t*)shadow_cr0 |= new_cr0_val;
76       PrintDebug("New Shadow CR0=%x\n", *shadow_cr0);   
77     }
78   } else if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
79     PrintDebug("MOV2CR0\n");
80
81     if (info->cpu_mode == LONG) {
82       // 64 bit registers
83     } else {
84       // 32 bit registers
85         struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
86         struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.src_operand.operand);
87
88         PrintDebug("OperandVal = %x, length=%d\n", *new_cr0, dec_instr.src_operand.size);
89
90
91         PrintDebug("Old CR0=%x\n", *real_cr0);
92         *real_cr0 = *new_cr0;
93         
94
95         if (info->shdw_pg_mode == SHADOW_PAGING) {
96           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
97           
98           PrintDebug("Old Shadow CR0=%x\n", *shadow_cr0);       
99           
100           real_cr0->et = 1;
101           
102           *shadow_cr0 = *new_cr0;
103           shadow_cr0->et = 1;
104           
105           if (get_mem_mode(info) == VIRTUAL_MEM) {
106             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
107             
108             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
109           } else  {
110             info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
111             real_cr0->pg = 1;
112           }
113           
114           PrintDebug("New Shadow CR0=%x\n",*shadow_cr0);
115         }
116         PrintDebug("New CR0=%x\n", *real_cr0);
117     }
118
119   } else if (opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
120     // CLTS
121     struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
122         
123     real_cr0->ts = 0;
124
125     if (info->shdw_pg_mode == SHADOW_PAGING) {
126       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
127       shadow_cr0->ts = 0;
128     }
129   } else {
130     PrintError("Unhandled opcode in handle_cr0_write\n");
131     return -1;
132   }
133
134   info->rip += dec_instr.instr_length;
135
136   return 0;
137 }
138
139
140 // First attempt = 253 lines
141 // current = 51 lines
142 int handle_cr0_read(struct guest_info * info) {
143   char instr[15];
144   int ret;
145   struct x86_instr dec_instr;
146
147   if (info->mem_mode == PHYSICAL_MEM) { 
148     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
149   } else { 
150     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
151   }
152
153   /* The IFetch will already have faulted in the necessary bytes for the full instruction
154      if (ret != 15) {
155      // I think we should inject a GPF into the guest
156      PrintError("Could not read instruction (ret=%d)\n", ret);
157      return -1;
158      }
159   */
160
161   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
162     PrintError("Could not decode instruction\n");
163     return -1;
164   }
165   
166   if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
167     struct cr0_32 * virt_cr0 = (struct cr0_32 *)(dec_instr.dst_operand.operand);
168     struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
169     
170     PrintDebug("MOVCR2\n");
171     PrintDebug("CR0 at 0x%x\n", real_cr0);
172
173     if (info->shdw_pg_mode == SHADOW_PAGING) {
174       *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
175     } else {
176       *virt_cr0 = *real_cr0;
177     }
178     
179     PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
180     PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
181   } else if (opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
182     struct cr0_real *real_cr0= (struct cr0_real*)&(info->ctrl_regs.cr0);
183     struct cr0_real *virt_cr0 = (struct cr0_real *)(dec_instr.dst_operand.operand);
184     char cr0_val = *(char*)real_cr0 & 0x0f;
185     
186     PrintDebug("SMSW\n");
187
188     PrintDebug("CR0 at 0x%x\n", real_cr0);
189
190     *(char *)virt_cr0 &= 0xf0;
191     *(char *)virt_cr0 |= cr0_val;
192     
193   } else {
194     PrintError("Unhandled opcode in handle_cr0_read\n");
195     return -1;
196   }
197
198   info->rip += dec_instr.instr_length;
199
200   return 0;
201 }
202
203
204
205 // First Attempt = 256 lines
206 // current = 65 lines
207 int handle_cr3_write(struct guest_info * info) {
208   int ret;
209   char instr[15];
210   struct x86_instr dec_instr;
211
212   if (info->mem_mode == PHYSICAL_MEM) { 
213     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
214   } else { 
215     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
216   }
217
218   /* The IFetch will already have faulted in the necessary bytes for the full instruction
219      if (ret != 15) {
220      // I think we should inject a GPF into the guest
221      PrintError("Could not read instruction (ret=%d)\n", ret);
222      return -1;
223      }
224   */
225
226   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
227     PrintError("Could not decode instruction\n");
228     return -1;
229   }
230
231   if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
232
233     PrintDebug("MOV2CR3\n");
234
235     PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
236
237     if (info->shdw_pg_mode == SHADOW_PAGING) {
238       struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);       
239       struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
240       struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
241       int cached = 0;
242       
243
244       PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
245                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
246       
247
248       cached = cache_page_tables32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
249
250       if (cached == -1) {
251         PrintError("CR3 Cache failed\n");
252         return -1;
253       } else if (cached == 0) {
254         addr_t shadow_pt;
255         
256         PrintDebug("New CR3 is different - flushing shadow page table\n");      
257         
258         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
259         
260         shadow_pt =  create_new_shadow_pt32();
261         
262         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);    
263       } else {
264         PrintDebug("Reusing cached shadow Page table\n");
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   info->rip += dec_instr.instr_length;
336
337   return 0;
338 }