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 MSR hook framework
[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       PrintError("Long mode currently not handled\n");
100       return -1;
101     } else {
102       // 32 bit registers
103         struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
104         struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.src_operand.operand);
105
106         PrintDebug("OperandVal = %x, length=%d\n", *(uint_t *)new_cr0, dec_instr.src_operand.size);
107
108
109         PrintDebug("Old CR0=%x\n", *(uint_t *)real_cr0);
110         *real_cr0 = *new_cr0;
111         
112
113         if (info->shdw_pg_mode == SHADOW_PAGING) {
114           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
115           
116           PrintDebug("Old Shadow CR0=%x\n", *(uint_t *)shadow_cr0);     
117           
118           real_cr0->et = 1;
119           
120           *shadow_cr0 = *new_cr0;
121           shadow_cr0->et = 1;
122           
123           if (v3_get_mem_mode(info) == VIRTUAL_MEM) {
124             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
125             PrintDebug("Setting up Shadow Page Table\n");
126             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
127           } else  {
128             info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
129             real_cr0->pg = 1;
130           }
131           
132           PrintDebug("New Shadow CR0=%x\n",*(uint_t *)shadow_cr0);
133         }
134         PrintDebug("New CR0=%x\n", *(uint_t *)real_cr0);
135     }
136
137   } else if (v3_opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
138     // CLTS
139     struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
140         
141     real_cr0->ts = 0;
142
143     if (info->shdw_pg_mode == SHADOW_PAGING) {
144       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
145       shadow_cr0->ts = 0;
146     }
147   } else {
148     PrintError("Unhandled opcode in handle_cr0_write\n");
149     return -1;
150   }
151
152   info->rip += dec_instr.instr_length;
153
154   return 0;
155 }
156
157
158 // First attempt = 253 lines
159 // current = 51 lines
160 int v3_handle_cr0_read(struct guest_info * info) {
161   uchar_t instr[15];
162   int ret;
163   struct x86_instr dec_instr;
164
165   if (info->mem_mode == PHYSICAL_MEM) { 
166     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
167   } else { 
168     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
169   }
170
171   /* The IFetch will already have faulted in the necessary bytes for the full instruction
172      if (ret != 15) {
173      // I think we should inject a GPF into the guest
174      PrintError("Could not read instruction (ret=%d)\n", ret);
175      return -1;
176      }
177   */
178
179   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
180     PrintError("Could not decode instruction\n");
181     return -1;
182   }
183   
184   if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
185     struct cr0_32 * virt_cr0 = (struct cr0_32 *)(dec_instr.dst_operand.operand);
186     struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
187     
188     PrintDebug("MOVCR2\n");
189     PrintDebug("CR0 at 0x%p\n", (void *)real_cr0);
190
191     if (info->shdw_pg_mode == SHADOW_PAGING) {
192       *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
193     } else {
194       *virt_cr0 = *real_cr0;
195     }
196     
197     PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
198     PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
199   } else if (v3_opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
200     struct cr0_real *real_cr0= (struct cr0_real*)&(info->ctrl_regs.cr0);
201     struct cr0_real *virt_cr0 = (struct cr0_real *)(dec_instr.dst_operand.operand);
202     char cr0_val = *(char*)real_cr0 & 0x0f;
203     
204     PrintDebug("SMSW\n");
205
206     PrintDebug("CR0 at 0x%p\n", real_cr0);
207
208     *(char *)virt_cr0 &= 0xf0;
209     *(char *)virt_cr0 |= cr0_val;
210     
211   } else {
212     PrintError("Unhandled opcode in handle_cr0_read\n");
213     return -1;
214   }
215
216   info->rip += dec_instr.instr_length;
217
218   return 0;
219 }
220
221
222
223 // First Attempt = 256 lines
224 // current = 65 lines
225 int v3_handle_cr3_write(struct guest_info * info) {
226   int ret;
227   uchar_t instr[15];
228   struct x86_instr dec_instr;
229
230   if (info->mem_mode == PHYSICAL_MEM) { 
231     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
232   } else { 
233     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
234   }
235
236   /* The IFetch will already have faulted in the necessary bytes for the full instruction
237      if (ret != 15) {
238      // I think we should inject a GPF into the guest
239      PrintError("Could not read instruction (ret=%d)\n", ret);
240      return -1;
241      }
242   */
243
244   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
245     PrintError("Could not decode instruction\n");
246     return -1;
247   }
248
249   if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
250
251     PrintDebug("MOV2CR3\n");
252
253     PrintDebug("CR3 at 0x%p\n", &(info->ctrl_regs.cr3));
254
255     if (info->shdw_pg_mode == SHADOW_PAGING) {
256       struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);       
257       struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
258       struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
259       int cached = 0;
260       
261
262       PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
263                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
264       
265
266
267       cached = v3_cache_page_tables32(info, (addr_t)V3_PAddr((void *)(addr_t)CR3_TO_PDE32((void *)*(addr_t *)new_cr3)));
268         
269       if (cached == -1) {
270         PrintError("CR3 Cache failed\n");
271         return -1;
272       } else if (cached == 0) {
273         addr_t shadow_pt;
274         
275         if(info->mem_mode == VIRTUAL_MEM) {
276           PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 );
277           delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
278         }
279         
280         shadow_pt =  v3_create_new_shadow_pt32();
281         
282         shadow_cr3->pdt_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PD32_BASE_ADDR(shadow_pt));
283         PrintDebug( "Created new shadow page table %p\n", (void *)(addr_t)shadow_cr3->pdt_base_addr );
284         //PrintDebugPageTables( (pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3) );
285
286
287       } else {
288         PrintDebug("Reusing cached shadow Page table\n");
289       }
290       
291       
292       shadow_cr3->pwt = new_cr3->pwt;
293       shadow_cr3->pcd = new_cr3->pcd;
294       
295       // What the hell...
296       *guest_cr3 = *new_cr3;
297       
298       PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
299                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
300
301       if (info->mem_mode == VIRTUAL_MEM) {
302         // If we aren't in paged mode then we have to preserve the identity mapped CR3
303         info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
304       }
305     }
306   } else {
307     PrintError("Unhandled opcode in handle_cr3_write\n");
308     return -1;
309   }
310
311   info->rip += dec_instr.instr_length;
312
313   return 0;
314 }
315
316
317
318 // first attempt = 156 lines
319 // current = 36 lines
320 int v3_handle_cr3_read(struct guest_info * info) {
321   uchar_t instr[15];
322   int ret;
323   struct x86_instr dec_instr;
324
325   if (info->mem_mode == PHYSICAL_MEM) { 
326     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
327   } else { 
328     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
329   }
330
331   /* The IFetch will already have faulted in the necessary bytes for the full instruction
332      if (ret != 15) {
333      // I think we should inject a GPF into the guest
334      PrintError("Could not read instruction (ret=%d)\n", ret);
335      return -1;
336      }
337   */
338
339   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
340     PrintError("Could not decode instruction\n");
341     return -1;
342   }
343
344   if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
345     PrintDebug("MOVCR32\n");
346     struct cr3_32 * virt_cr3 = (struct cr3_32 *)(dec_instr.dst_operand.operand);
347
348     PrintDebug("CR3 at 0x%p\n", &(info->ctrl_regs.cr3));
349
350     if (info->shdw_pg_mode == SHADOW_PAGING) {
351       *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
352     } else {
353       *virt_cr3 = *(struct cr3_32 *)&(info->ctrl_regs.cr3);
354     }
355   } else {
356     PrintError("Unhandled opcode in handle_cr3_read\n");
357     return -1;
358   }
359
360   info->rip += dec_instr.instr_length;
361
362   return 0;
363 }
364
365 int v3_handle_cr4_read(struct guest_info * info) {
366   PrintError("CR4 Read not handled\n");
367   return -1;
368 }
369
370 int v3_handle_cr4_write(struct guest_info * info) {
371   uchar_t instr[15];
372   int ret;
373   struct x86_instr dec_instr;
374
375   if (info->mem_mode == PHYSICAL_MEM) { 
376     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
377   } else { 
378     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
379   }
380
381   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
382     PrintError("Could not decode instruction\n");
383     return -1;
384   }
385
386   if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) != 0) {
387     PrintError("Invalid opcode in write to CR4\n");
388     return -1;
389   }
390
391   if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PAE)) {
392     struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
393     struct cr4_32 * old_cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
394     
395     PrintDebug("OperandVal = %x, length = %d\n", *(uint_t *)new_cr4, dec_instr.src_operand.size);
396     PrintDebug("Old CR4=%x\n", *(uint_t *)old_cr4);
397
398
399
400
401     if ((info->shdw_pg_mode == SHADOW_PAGING) && 
402         (v3_get_mem_mode(info) == PHYSICAL_MEM)) {
403
404       if ((old_cr4->pae == 0) && (new_cr4->pae == 1)) {
405         // Create Passthrough PAE pagetables
406         PrintDebug("Creating PAE passthrough tables\n");
407         info->ctrl_regs.cr3 = (addr_t)V3_PAddr(create_passthrough_pts_PAE32(info));
408       } else if ((old_cr4->pae == 1) && (new_cr4->pae == 0)) {
409         // Create passthrough standard 32bit pagetables
410         return -1;
411       }
412     }
413
414     *old_cr4 = *new_cr4;
415     PrintDebug("New CR4=%x\n", *(uint_t *)old_cr4);
416
417   } else {
418     return -1;
419   }
420
421   info->rip += dec_instr.instr_length;
422   return 0;
423 }
424
425
426 int v3_handle_efer_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
427   PrintError("EFER Read not handled\n");
428   return -1;
429 }
430
431
432 int v3_handle_efer_write(uint_t msr, struct v3_msr src, void * priv_data) {
433   //  struct guest_info * info = (struct guest_info *)(priv_data);
434   PrintError("EFER Write not handled (rax=%p, rdx=%p)\n", 
435              (void *)(addr_t)(src.lo), 
436              (void *)(addr_t)(src.hi));
437   return -1;
438 }