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.


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