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.


working instruction emulation
[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 (dec_instr.op_type == V3_OP_LMSW) {
66   //  if (v3_opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
67
68     if (handle_lmsw(info, &dec_instr) == -1) {
69       return -1;
70     }
71
72     //  } else if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
73   } else if (dec_instr.op_type == V3_OP_MOV2CR) {
74     if (handle_mov_to_cr0(info, &dec_instr) == -1) {
75       return -1;
76     }
77
78     //  } else if (v3_opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
79   } else if (dec_instr.op_type == V3_OP_CLTS) {
80
81     if (handle_clts(info, &dec_instr) == -1) {
82       return -1;
83     }
84
85   } else {
86     PrintError("Unhandled opcode in handle_cr0_write\n");
87     return -1;
88   }
89
90   info->rip += dec_instr.instr_length;
91
92   return 0;
93 }
94
95
96
97
98 // The CR0 register only has flags in the low 32 bits
99 // The hardware does a format check to make sure the high bits are zero
100 // Because of this we can ignore the high 32 bits here
101 static int handle_mov_to_cr0(struct guest_info * info, struct x86_instr * dec_instr) {
102   // 32 bit registers
103   struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
104   struct cr0_32 * new_cr0 = (struct cr0_32 *)(dec_instr->src_operand.operand);
105   struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
106   uint_t paging_transition = 0;
107
108   PrintDebug("MOV2CR0 (MODE=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
109   
110   PrintDebug("OperandVal = %x, length=%d\n", *(uint_t *)new_cr0, dec_instr->src_operand.size);
111   
112   PrintDebug("Old CR0=%x\n", *(uint_t *)shadow_cr0);
113   PrintDebug("Old Guest CR0=%x\n", *(uint_t *)guest_cr0);       
114
115
116   // We detect if this is a paging transition
117   if (guest_cr0->pg != new_cr0->pg) {
118     paging_transition = 1;
119   }  
120
121   // Guest always sees the value they wrote
122   *guest_cr0 = *new_cr0;
123
124   // This value must always be set to 1 
125   guest_cr0->et = 1;    
126
127   // Set the shadow register to catch non-virtualized flags
128   *shadow_cr0 = *guest_cr0;
129
130   // Paging is always enabled
131   shadow_cr0->pg = 1;  
132
133   // Was there a paging transition
134   // Meaning we need to change the page tables
135   if (paging_transition) {
136     if (v3_get_mem_mode(info) == VIRTUAL_MEM) {
137
138       PrintDebug("Activating Shadow Page Tables\n");
139       
140       if (v3_activate_shadow_pt(info) == -1) {
141         PrintError("Failed to activate shadow page tables\n");
142         return -1;
143       }
144     } else  {
145       
146       if (v3_activate_passthrough_pt(info) == -1) {
147         PrintError("Failed to activate passthrough page tables\n");
148         return -1;
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 (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
231   if (dec_instr.op_type == V3_OP_MOVCR2) {
232     struct cr0_32 * dst_reg = (struct cr0_32 *)(dec_instr.dst_operand.operand);
233     struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
234
235     PrintDebug("MOVCR2 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
236
237     if (info->shdw_pg_mode == SHADOW_PAGING) {
238       struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
239       *dst_reg = *guest_cr0;
240     } else {
241       *dst_reg = *shadow_cr0;
242     }
243
244     PrintDebug("Shadow CR0: %x\n", *(uint_t*)shadow_cr0);    
245     PrintDebug("returned CR0: %x\n", *(uint_t*)dst_reg);
246     //  } else if (v3_opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
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 (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
291   if (dec_instr.op_type == V3_OP_MOV2CR) {
292     PrintDebug("MOV2CR3 (cpu_mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
293
294     if (info->shdw_pg_mode == SHADOW_PAGING) {
295       PrintDebug("Old Shadow CR3=%p; Old Guest CR3=%p\n", 
296                  (void *)(addr_t)(info->ctrl_regs.cr3), 
297                  (void*)(addr_t)(info->shdw_pg_state.guest_cr3));
298       
299     
300       // We update the guest CR3    
301       if (info->cpu_mode == LONG) {
302         struct cr3_64 * new_cr3 = (struct cr3_64 *)(dec_instr.src_operand.operand);
303         struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
304         *guest_cr3 = *new_cr3;
305       } else {
306         struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
307         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
308         *guest_cr3 = *new_cr3;
309       }
310       
311       // If Paging is enabled in the guest then we need to change the shadow page tables
312       if (info->mem_mode == VIRTUAL_MEM) {
313         if (v3_activate_shadow_pt(info) == -1) {
314           PrintError("Failed to activate 32 bit shadow page table\n");
315           return -1;
316         }
317       } 
318  
319       PrintDebug("New Shadow CR3=%p; New Guest CR3=%p\n", 
320                  (void *)(addr_t)(info->ctrl_regs.cr3), 
321                  (void*)(addr_t)(info->shdw_pg_state.guest_cr3));
322       
323     } else if (info->shdw_pg_mode == NESTED_PAGING) {
324  
325      // This is just a passthrough operation which we probably don't need here
326       if (info->cpu_mode == LONG) {
327         struct cr3_64 * new_cr3 = (struct cr3_64 *)(dec_instr.src_operand.operand);
328         struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3);
329         *guest_cr3 = *new_cr3;
330       } else {
331         struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
332         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
333         *guest_cr3 = *new_cr3;
334       }
335
336     }
337   } else {
338     PrintError("Unhandled opcode in handle_cr3_write\n");
339     return -1;
340   }
341
342   info->rip += dec_instr.instr_length;
343
344   return 0;
345 }
346
347
348
349 // first attempt = 156 lines
350 // current = 36 lines
351 int v3_handle_cr3_read(struct guest_info * info) {
352   uchar_t instr[15];
353   int ret;
354   struct x86_instr dec_instr;
355
356   if (info->mem_mode == PHYSICAL_MEM) { 
357     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
358   } else { 
359     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
360   }
361
362   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
363     PrintError("Could not decode instruction\n");
364     return -1;
365   }
366
367   //  if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
368   if (dec_instr.op_type == V3_OP_MOVCR2) {
369     PrintDebug("MOVCR32 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
370
371     if (info->shdw_pg_mode == SHADOW_PAGING) {
372
373       if (info->cpu_mode == LONG) {
374         struct cr3_64 * dst_reg = (struct cr3_64 *)(dec_instr.dst_operand.operand);
375         struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
376         *dst_reg = *guest_cr3;
377       } else {
378         struct cr3_32 * dst_reg = (struct cr3_32 *)(dec_instr.dst_operand.operand);
379         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
380         *dst_reg = *guest_cr3;
381       }
382
383     } else if (info->shdw_pg_mode == NESTED_PAGING) {
384
385       // This is just a passthrough operation which we probably don't need here
386       if (info->cpu_mode == LONG) {
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
420   if (info->mem_mode == PHYSICAL_MEM) { 
421     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
422   } else { 
423     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
424   }
425
426   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
427     PrintError("Could not decode instruction\n");
428     return -1;
429   }
430
431   //  if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) != 0) {
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 ((info->cpu_mode == PROTECTED) || (info->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 {
469     PrintError("CR4 write not supported in CPU_MODE: %d\n", info->cpu_mode);
470     return -1;
471   }
472
473   info->rip += dec_instr.instr_length;
474   return 0;
475 }
476
477
478 int v3_handle_efer_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
479   struct guest_info * info = (struct guest_info *)(priv_data);
480   PrintDebug("EFER Read\n");
481
482   dst->value = info->guest_efer.value;
483
484   info->rip += 2; // WRMSR/RDMSR are two byte operands
485   return 0;
486 }
487
488
489 int v3_handle_efer_write(uint_t msr, struct v3_msr src, void * priv_data) {
490   struct guest_info * info = (struct guest_info *)(priv_data);
491   struct efer_64 * new_efer = (struct efer_64 *)&(src.value);
492   struct efer_64 * shadow_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
493   struct v3_msr * guest_efer = &(info->guest_efer);
494
495   PrintDebug("EFER Write\n");
496   PrintDebug("Old EFER=%p\n", (void *)*(addr_t*)(shadow_efer));
497
498   // We virtualize the guests efer to hide the SVME and LMA bits
499   guest_efer->value = src.value;
500
501  
502   if ((info->shdw_pg_mode == SHADOW_PAGING) && 
503       (v3_get_mem_mode(info) == PHYSICAL_MEM)) {
504     
505     if ((shadow_efer->lme == 0) && (new_efer->lme == 1)) {
506       PrintDebug("Transition to longmode\n");
507       PrintDebug("Creating Passthrough 64 bit page tables\n");
508       
509       // Delete the old 32 bit direct map page tables
510       /* 
511        * JRL BUG? 
512        * Will these page tables always be in PAE format?? 
513        */
514       PrintDebug("Deleting old PAE Page tables\n");
515       PrintError("JRL BUG?: Will the old page tables always be in PAE format??\n");
516       delete_page_tables_32PAE((pdpe32pae_t *)V3_VAddr((void *)(info->direct_map_pt)));
517       
518       // create 64 bit direct map page table
519       info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(info));
520       
521       // reset cr3 to new page tables
522       info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
523       
524       // We mark the Long Mode active  because we have paging enabled
525       // We do this in new_efer because we copy the msr in full below
526       new_efer->lma = 1;
527       
528     } else if ((shadow_efer->lme == 1) && (new_efer->lme == 0)) {
529       // transition out of long mode
530       //((struct efer_64 *)&(info->guest_efer.value))->lme = 0;
531       //((struct efer_64 *)&(info->guest_efer.value))->lma = 0;
532       
533       return -1;
534     }
535
536     // accept all changes to the efer, but make sure that the SVME bit is set... (SVM specific)
537     *shadow_efer = *new_efer;
538     shadow_efer->svme = 1;
539     
540
541
542     PrintDebug("New EFER=%p\n", (void *)*(addr_t *)(shadow_efer));
543   } else {
544     PrintError("Write to EFER in NESTED_PAGING or VIRTUAL_MEM mode not supported\n");
545     // Should probably just check for a long mode transition, and bomb out if it is
546     return -1;
547   }
548
549   info->rip += 2; // WRMSR/RDMSR are two byte operands
550
551   return 0;
552 }