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.


minor fixes
[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 #ifndef DEBUG_CTRL_REGS
29 #undef PrintDebug
30 #define PrintDebug(fmt, args...)
31 #endif
32
33
34 static int handle_lmsw(struct guest_info * info, struct x86_instr * dec_instr);
35 static int handle_clts(struct guest_info * info, struct x86_instr * dec_instr);
36 static int handle_mov_to_cr0(struct guest_info * info, struct x86_instr * dec_instr);
37
38
39 // First Attempt = 494 lines
40 // current = 106 lines
41 int v3_handle_cr0_write(struct guest_info * info) {
42   uchar_t instr[15];
43   int ret;
44   struct x86_instr dec_instr;
45
46   if (info->mem_mode == PHYSICAL_MEM) { 
47     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
48   } else { 
49     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
50   }
51
52   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
53     PrintError("Could not decode instruction\n");
54     return -1;
55   }
56
57
58   if (dec_instr.op_type == V3_OP_LMSW) {
59     if (handle_lmsw(info, &dec_instr) == -1) {
60       return -1;
61     }
62   } else if (dec_instr.op_type == V3_OP_MOV2CR) {
63     if (handle_mov_to_cr0(info, &dec_instr) == -1) {
64       return -1;
65     }
66   } else if (dec_instr.op_type == V3_OP_CLTS) {
67     if (handle_clts(info, &dec_instr) == -1) {
68       return -1;
69     }
70   } else {
71     PrintError("Unhandled opcode in handle_cr0_write\n");
72     return -1;
73   }
74
75   info->rip += dec_instr.instr_length;
76
77   return 0;
78 }
79
80
81
82
83 // The CR0 register only has flags in the low 32 bits
84 // The hardware does a format check to make sure the high bits are zero
85 // Because of this we can ignore the high 32 bits here
86 static int handle_mov_to_cr0(struct guest_info * info, struct x86_instr * dec_instr) {
87   // 32 bit registers
88   struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
89   struct cr0_32 * new_cr0 = (struct cr0_32 *)(dec_instr->src_operand.operand);
90   struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
91   uint_t paging_transition = 0;
92
93   PrintDebug("MOV2CR0 (MODE=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
94   
95   PrintDebug("OperandVal = %x, length=%d\n", *(uint_t *)new_cr0, dec_instr->src_operand.size);
96   
97   PrintDebug("Old CR0=%x\n", *(uint_t *)shadow_cr0);
98   PrintDebug("Old Guest CR0=%x\n", *(uint_t *)guest_cr0);       
99
100
101   // We detect if this is a paging transition
102   if (guest_cr0->pg != new_cr0->pg) {
103     paging_transition = 1;
104   }  
105
106   // Guest always sees the value they wrote
107   *guest_cr0 = *new_cr0;
108
109   // This value must always be set to 1 
110   guest_cr0->et = 1;    
111
112   // Set the shadow register to catch non-virtualized flags
113   *shadow_cr0 = *guest_cr0;
114
115   // Paging is always enabled
116   shadow_cr0->pg = 1;  
117
118   // Was there a paging transition
119   // Meaning we need to change the page tables
120   if (paging_transition) {
121     if (v3_get_mem_mode(info) == VIRTUAL_MEM) {
122
123       struct efer_64 * guest_efer  = (struct efer_64 *)&(info->guest_efer);
124       struct efer_64 * shadow_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
125
126       // Check long mode LME to set LME
127       if (guest_efer->lme == 1) {
128         PrintDebug("Enabing Long Mode\n");
129         guest_efer->lma = 1;
130         
131         shadow_efer->lma = 1;
132         shadow_efer->lme = 1;
133
134         PrintDebug("New EFER %p\n", (void *)*(addr_t *)(shadow_efer));
135       }
136
137       PrintDebug("Activating Shadow Page Tables\n");
138       
139       if (v3_activate_shadow_pt(info) == -1) {
140         PrintError("Failed to activate shadow page tables\n");
141         return -1;
142       }
143     } else  {
144       
145       if (v3_activate_passthrough_pt(info) == -1) {
146         PrintError("Failed to activate passthrough page tables\n");
147         return -1;
148       }
149     }
150   }
151
152
153   PrintDebug("New Guest CR0=%x\n",*(uint_t *)guest_cr0);  
154   PrintDebug("New CR0=%x\n", *(uint_t *)shadow_cr0);
155
156   return 0;
157 }
158
159
160
161
162 static int handle_clts(struct guest_info * info, struct x86_instr * dec_instr) {
163   // CLTS
164   struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
165   
166   real_cr0->ts = 0;
167   
168   if (info->shdw_pg_mode == SHADOW_PAGING) {
169     struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
170     guest_cr0->ts = 0;
171   }
172   return 0;
173 }
174
175
176 static int handle_lmsw(struct guest_info * info, struct x86_instr * dec_instr) {
177  struct cr0_real * real_cr0  = (struct cr0_real*)&(info->ctrl_regs.cr0);
178  struct cr0_real * new_cr0 = (struct cr0_real *)(dec_instr->src_operand.operand);       
179  uchar_t new_cr0_val;
180  
181  PrintDebug("LMSW\n");
182  
183  new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
184  
185  PrintDebug("OperandVal = %x\n", new_cr0_val);
186  
187  // We can just copy the new value through
188  // we don't need to virtualize the lower 4 bits
189  PrintDebug("Old CR0=%x\n", *(uint_t *)real_cr0);       
190  *(uchar_t*)real_cr0 &= 0xf0;
191  *(uchar_t*)real_cr0 |= new_cr0_val;
192  PrintDebug("New CR0=%x\n", *(uint_t *)real_cr0);       
193  
194  
195  // If Shadow paging is enabled we push the changes to the virtualized copy of cr0
196  if (info->shdw_pg_mode == SHADOW_PAGING) {
197    struct cr0_real * guest_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
198    
199    PrintDebug("Old Guest CR0=%x\n", *(uint_t *)guest_cr0);      
200    *(uchar_t*)guest_cr0 &= 0xf0;
201    *(uchar_t*)guest_cr0 |= new_cr0_val;
202    PrintDebug("New Guest CR0=%x\n", *(uint_t *)guest_cr0);      
203  }
204  return 0;
205 }
206
207
208
209
210
211 // First attempt = 253 lines
212 // current = 51 lines
213 int v3_handle_cr0_read(struct guest_info * info) {
214   uchar_t instr[15];
215   int ret;
216   struct x86_instr dec_instr;
217
218   if (info->mem_mode == PHYSICAL_MEM) { 
219     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
220   } else { 
221     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
222   }
223
224
225   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
226     PrintError("Could not decode instruction\n");
227     return -1;
228   }
229   
230   if (dec_instr.op_type == V3_OP_MOVCR2) {
231     struct cr0_32 * dst_reg = (struct cr0_32 *)(dec_instr.dst_operand.operand);
232     struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
233
234     PrintDebug("MOVCR2 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
235
236     if (info->shdw_pg_mode == SHADOW_PAGING) {
237       struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
238       *dst_reg = *guest_cr0;
239     } else {
240       *dst_reg = *shadow_cr0;
241     }
242
243     PrintDebug("Shadow CR0: %x\n", *(uint_t*)shadow_cr0);    
244     PrintDebug("returned CR0: %x\n", *(uint_t*)dst_reg);
245   } else if (dec_instr.op_type == V3_OP_SMSW) {
246     struct cr0_real * shadow_cr0 = (struct cr0_real *)&(info->ctrl_regs.cr0);
247     struct cr0_real * dst_reg = (struct cr0_real *)(dec_instr.dst_operand.operand);
248     char cr0_val = *(char*)shadow_cr0 & 0x0f;
249     
250     PrintDebug("SMSW\n");
251
252     // The lower 4 bits of the guest/shadow CR0 are mapped through
253     // We can treat nested and shadow paging the same here
254     *(char *)dst_reg &= 0xf0;
255     *(char *)dst_reg |= cr0_val;
256     
257   } else {
258     PrintError("Unhandled opcode in handle_cr0_read\n");
259     return -1;
260   }
261
262   info->rip += dec_instr.instr_length;
263
264   return 0;
265 }
266
267
268
269
270 // First Attempt = 256 lines
271 // current = 65 lines
272 int v3_handle_cr3_write(struct guest_info * info) {
273   int ret;
274   uchar_t instr[15];
275   struct x86_instr dec_instr;
276
277   if (info->mem_mode == PHYSICAL_MEM) { 
278     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
279   } else { 
280     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
281   }
282
283   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
284     PrintError("Could not decode instruction\n");
285     return -1;
286   }
287
288   if (dec_instr.op_type == V3_OP_MOV2CR) {
289     PrintDebug("MOV2CR3 (cpu_mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
290
291     if (info->shdw_pg_mode == SHADOW_PAGING) {
292       PrintDebug("Old Shadow CR3=%p; Old Guest CR3=%p\n", 
293                  (void *)(addr_t)(info->ctrl_regs.cr3), 
294                  (void*)(addr_t)(info->shdw_pg_state.guest_cr3));
295       
296     
297       // We update the guest CR3    
298       if (info->cpu_mode == LONG) {
299         struct cr3_64 * new_cr3 = (struct cr3_64 *)(dec_instr.src_operand.operand);
300         struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
301         *guest_cr3 = *new_cr3;
302       } else {
303         struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
304         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
305         *guest_cr3 = *new_cr3;
306       }
307       
308       // If Paging is enabled in the guest then we need to change the shadow page tables
309       if (info->mem_mode == VIRTUAL_MEM) {
310         if (v3_activate_shadow_pt(info) == -1) {
311           PrintError("Failed to activate 32 bit shadow page table\n");
312           return -1;
313         }
314       } 
315  
316       PrintDebug("New Shadow CR3=%p; New Guest CR3=%p\n", 
317                  (void *)(addr_t)(info->ctrl_regs.cr3), 
318                  (void*)(addr_t)(info->shdw_pg_state.guest_cr3));
319       
320     } else if (info->shdw_pg_mode == NESTED_PAGING) {
321  
322      // This is just a passthrough operation which we probably don't need here
323       if (info->cpu_mode == LONG) {
324         struct cr3_64 * new_cr3 = (struct cr3_64 *)(dec_instr.src_operand.operand);
325         struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3);
326         *guest_cr3 = *new_cr3;
327       } else {
328         struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
329         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
330         *guest_cr3 = *new_cr3;
331       }
332
333     }
334   } else {
335     PrintError("Unhandled opcode in handle_cr3_write\n");
336     return -1;
337   }
338
339   info->rip += dec_instr.instr_length;
340
341   return 0;
342 }
343
344
345
346 // first attempt = 156 lines
347 // current = 36 lines
348 int v3_handle_cr3_read(struct guest_info * info) {
349   uchar_t instr[15];
350   int ret;
351   struct x86_instr dec_instr;
352
353   if (info->mem_mode == PHYSICAL_MEM) { 
354     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
355   } else { 
356     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
357   }
358
359   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
360     PrintError("Could not decode instruction\n");
361     return -1;
362   }
363
364   if (dec_instr.op_type == V3_OP_MOVCR2) {
365     PrintDebug("MOVCR32 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
366
367     if (info->shdw_pg_mode == SHADOW_PAGING) {
368
369       if ((v3_get_cpu_mode(info) == LONG) || 
370           (v3_get_cpu_mode(info) == LONG_32_COMPAT)) {
371         struct cr3_64 * dst_reg = (struct cr3_64 *)(dec_instr.dst_operand.operand);
372         struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
373         *dst_reg = *guest_cr3;
374       } else {
375         struct cr3_32 * dst_reg = (struct cr3_32 *)(dec_instr.dst_operand.operand);
376         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
377         *dst_reg = *guest_cr3;
378       }
379
380     } else if (info->shdw_pg_mode == NESTED_PAGING) {
381
382       // This is just a passthrough operation which we probably don't need here
383       if ((v3_get_cpu_mode(info) == LONG) || 
384           (v3_get_cpu_mode(info) == LONG_32_COMPAT)) {
385         struct cr3_64 * dst_reg = (struct cr3_64 *)(dec_instr.dst_operand.operand);
386         struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3);
387         *dst_reg = *guest_cr3;
388       } else {
389         struct cr3_32 * dst_reg = (struct cr3_32 *)(dec_instr.dst_operand.operand);
390         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
391         *dst_reg = *guest_cr3;
392       }
393     }
394
395   } else {
396     PrintError("Unhandled opcode in handle_cr3_read\n");
397     return -1;
398   }
399
400   info->rip += dec_instr.instr_length;
401
402   return 0;
403 }
404
405
406 // We don't need to virtualize CR4, all we need is to detect the activation of PAE
407 int v3_handle_cr4_read(struct guest_info * info) {
408   //  PrintError("CR4 Read not handled\n");
409   // Do nothing...
410   return 0;
411 }
412
413 int v3_handle_cr4_write(struct guest_info * info) {
414   uchar_t instr[15];
415   int ret;
416   struct x86_instr dec_instr;
417   v3_vm_cpu_mode_t cpu_mode = v3_get_cpu_mode(info);
418
419   if (info->mem_mode == PHYSICAL_MEM) { 
420     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
421   } else { 
422     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
423   }
424
425   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
426     PrintError("Could not decode instruction\n");
427     return -1;
428   }
429
430   if (dec_instr.op_type != V3_OP_MOV2CR) {
431     PrintError("Invalid opcode in write to CR4\n");
432     return -1;
433   }
434
435   if ((cpu_mode == PROTECTED) || (cpu_mode == PROTECTED_PAE)) {
436     struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
437     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
438     
439     PrintDebug("OperandVal = %x, length = %d\n", *(uint_t *)new_cr4, dec_instr.src_operand.size);
440     PrintDebug("Old CR4=%x\n", *(uint_t *)cr4);
441
442     if ((info->shdw_pg_mode == SHADOW_PAGING) && 
443         (v3_get_mem_mode(info) == PHYSICAL_MEM)) {
444
445       if ((cr4->pae == 0) && (new_cr4->pae == 1)) {
446         PrintDebug("Creating PAE passthrough tables\n");
447
448         // Delete the old 32 bit direct map page tables
449         delete_page_tables_32((pde32_t *)V3_VAddr((void *)(info->direct_map_pt)));
450
451         // create 32 bit PAE direct map page table
452         info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_32PAE(info));
453
454         // reset cr3 to new page tables
455         info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
456
457       } else if ((cr4->pae == 1) && (new_cr4->pae == 0)) {
458         // Create passthrough standard 32bit pagetables
459         return -1;
460       }
461     }
462
463     *cr4 = *new_cr4;
464     PrintDebug("New CR4=%x\n", *(uint_t *)cr4);
465
466   } else if ((cpu_mode == LONG) || (cpu_mode == LONG_32_COMPAT)) {
467     struct cr4_64 * new_cr4 = (struct cr4_64 *)(dec_instr.src_operand.operand);
468     struct cr4_64 * cr4 = (struct cr4_64 *)&(info->ctrl_regs.cr4);
469
470     PrintDebug("Old CR4=%p\n", (void *)*(addr_t *)cr4);
471     PrintDebug("New CR4=%p\n", (void *)*(addr_t *)new_cr4);
472
473     if (new_cr4->pae == 0) {
474       // cannot turn off PAE in long mode GPF the guest
475       PrintError("Cannot disable PAE in long mode, sending GPF\n");
476       return -1;
477     }
478
479     *cr4 = *new_cr4;
480
481   } else {
482     PrintError("CR4 write not supported in CPU_MODE: %s\n", v3_cpu_mode_to_str(cpu_mode));
483     return -1;
484   }
485
486   info->rip += dec_instr.instr_length;
487   return 0;
488 }
489
490
491 int v3_handle_efer_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
492   struct guest_info * info = (struct guest_info *)(priv_data);
493   PrintDebug("EFER Read HI=%x LO=%x\n", info->guest_efer.hi, info->guest_efer.lo);
494
495   dst->value = info->guest_efer.value;
496
497   info->rip += 2; // WRMSR/RDMSR are two byte operands
498   return 0;
499 }
500
501
502 int v3_handle_efer_write(uint_t msr, struct v3_msr src, void * priv_data) {
503   struct guest_info * info = (struct guest_info *)(priv_data);
504   //struct efer_64 * new_efer = (struct efer_64 *)&(src.value);
505   //  struct efer_64 * shadow_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
506   struct v3_msr * guest_efer = &(info->guest_efer);
507
508   PrintDebug("EFER Write\n");
509   PrintDebug("EFER Write Values: HI=%x LO=%x\n", src.hi, src.lo);
510   //PrintDebug("Old EFER=%p\n", (void *)*(addr_t*)(shadow_efer));
511
512   // We virtualize the guests efer to hide the SVME and LMA bits
513   guest_efer->value = src.value;
514
515         
516   // We have to handle long mode writes....
517
518   /* 
519      if ((info->shdw_pg_mode == SHADOW_PAGING) && 
520      (v3_get_mem_mode(info) == PHYSICAL_MEM)) {
521      
522      if ((shadow_efer->lme == 0) && (new_efer->lme == 1)) {
523      PrintDebug("Transition to longmode\n");
524      PrintDebug("Creating Passthrough 64 bit page tables\n");
525      
526      // Delete the old 32 bit direct map page tables
527      
528      PrintDebug("Deleting old PAE Page tables\n");
529      PrintError("JRL BUG?: Will the old page tables always be in PAE format??\n");
530      delete_page_tables_32PAE((pdpe32pae_t *)V3_VAddr((void *)(info->direct_map_pt)));
531      
532      // create 64 bit direct map page table
533      info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(info));
534      
535      // reset cr3 to new page tables
536      info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
537      
538      // We mark the Long Mode active  because we have paging enabled
539      // We do this in new_efer because we copy the msr in full below
540      // new_efer->lma = 1;
541      
542      } else if ((shadow_efer->lme == 1) && (new_efer->lme == 0)) {
543      // transition out of long mode
544      //((struct efer_64 *)&(info->guest_efer.value))->lme = 0;
545      //((struct efer_64 *)&(info->guest_efer.value))->lma = 0;
546      
547      return -1;
548      }
549      
550      // accept all changes to the efer, but make sure that the SVME bit is set... (SVM specific)
551      *shadow_efer = *new_efer;
552      shadow_efer->svme = 1;
553      
554      
555      
556      PrintDebug("New EFER=%p\n", (void *)*(addr_t *)(shadow_efer));
557      } else {
558      PrintError("Write to EFER in NESTED_PAGING or VIRTUAL_MEM mode not supported\n");
559      // Should probably just check for a long mode transition, and bomb out if it is
560      return -1;
561      }
562   */
563   info->rip += 2; // WRMSR/RDMSR are two byte operands
564
565   return 0;
566 }