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.


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