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.


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