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.


f09bfb986c784bc5534e527ec5bd155480daeec2
[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 #include <palacios/vmm_direct_paging.h>
27 #include <palacios/svm.h>
28
29 #ifndef V3_CONFIG_DEBUG_CTRL_REGS
30 #undef PrintDebug
31 #define PrintDebug(fmt, args...)
32 #endif
33
34
35 static int handle_lmsw(struct guest_info * info, struct x86_instr * dec_instr);
36 static int handle_clts(struct guest_info * info, struct x86_instr * dec_instr);
37 static int handle_mov_to_cr0(struct guest_info * info, struct x86_instr * dec_instr);
38
39
40 // First Attempt = 494 lines
41 // current = 106 lines
42 int v3_handle_cr0_write(struct guest_info * info) {
43     uchar_t instr[15];
44     int ret;
45     struct x86_instr dec_instr;
46     
47     if (info->mem_mode == PHYSICAL_MEM) { 
48         ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
49     } else { 
50         ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
51     }
52     
53     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
54         PrintError(info->vm_info, info, "Could not decode instruction\n");
55         return -1;
56     }
57
58     
59     if (dec_instr.op_type == V3_OP_LMSW) {
60         if (handle_lmsw(info, &dec_instr) == -1) {
61             return -1;
62         }
63     } else if (dec_instr.op_type == V3_OP_MOV2CR) {
64         if (handle_mov_to_cr0(info, &dec_instr) == -1) {
65             return -1;
66         }
67     } else if (dec_instr.op_type == V3_OP_CLTS) {
68         if (handle_clts(info, &dec_instr) == -1) {
69             return -1;
70         }
71     } else {
72         PrintError(info->vm_info, info, "Unhandled opcode in handle_cr0_write\n");
73         return -1;
74     }
75     
76     info->rip += dec_instr.instr_length;
77     
78     return 0;
79 }
80
81
82
83
84 // The CR0 register only has flags in the low 32 bits
85 // The hardware does a format check to make sure the high bits are zero
86 // Because of this we can ignore the high 32 bits here
87 static int handle_mov_to_cr0(struct guest_info * info, struct x86_instr * dec_instr) {
88     // 32 bit registers
89     struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
90     struct cr0_32 * new_cr0 = (struct cr0_32 *)(dec_instr->src_operand.operand);
91     struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
92     uint_t paging_transition = 0;
93     
94     PrintDebug(info->vm_info, info, "MOV2CR0 (MODE=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
95     
96     PrintDebug(info->vm_info, info, "OperandVal = %x, length=%d\n", *(uint_t *)new_cr0, dec_instr->src_operand.size);
97     
98     PrintDebug(info->vm_info, info, "Old CR0=%x\n", *(uint_t *)shadow_cr0);
99     PrintDebug(info->vm_info, info, "Old Guest CR0=%x\n", *(uint_t *)guest_cr0);        
100     
101     
102     // We detect if this is a paging transition
103     if (guest_cr0->pg != new_cr0->pg) {
104         paging_transition = 1;
105     }  
106     
107     // Guest always sees the value they wrote
108     *guest_cr0 = *new_cr0;
109     
110     // This value must always be set to 1 
111     guest_cr0->et = 1;
112     
113     // Set the shadow register to catch non-virtualized flags
114     *shadow_cr0 = *guest_cr0;
115     
116     // Paging is always enabled
117     shadow_cr0->pg = 1;
118
119     if (guest_cr0->pg == 0) {
120         // If paging is not enabled by the guest, then we always enable write-protect to catch memory hooks
121         shadow_cr0->wp = 1;
122     }
123     
124     // Was there a paging transition
125     // Meaning we need to change the page tables
126     if (paging_transition) {
127         if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) {
128             
129             struct efer_64 * guest_efer  = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
130             struct efer_64 * shadow_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
131             
132             // Check long mode LME to set LME
133             if (guest_efer->lme == 1) {
134                 PrintDebug(info->vm_info, info, "Enabing Long Mode\n");
135                 guest_efer->lma = 1;
136                 
137                 shadow_efer->lma = 1;
138                 shadow_efer->lme = 1;
139                 
140                 PrintDebug(info->vm_info, info, "New EFER %p\n", (void *)*(addr_t *)(shadow_efer));
141             }
142             
143             PrintDebug(info->vm_info, info, "Activating Shadow Page Tables\n");
144             
145             if (v3_activate_shadow_pt(info) == -1) {
146                 PrintError(info->vm_info, info, "Failed to activate shadow page tables\n");
147                 return -1;
148             }
149         } else {
150
151             shadow_cr0->wp = 1;
152             
153             if (v3_activate_passthrough_pt(info) == -1) {
154                 PrintError(info->vm_info, info, "Failed to activate passthrough page tables\n");
155                 return -1;
156             }
157         }
158     }
159     
160     
161     PrintDebug(info->vm_info, info, "New Guest CR0=%x\n",*(uint_t *)guest_cr0);  
162     PrintDebug(info->vm_info, info, "New CR0=%x\n", *(uint_t *)shadow_cr0);
163     
164     return 0;
165 }
166
167
168
169
170 static int handle_clts(struct guest_info * info, struct x86_instr * dec_instr) {
171     // CLTS
172     struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
173     
174     real_cr0->ts = 0;
175     
176     if (info->shdw_pg_mode == SHADOW_PAGING) {
177         struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
178         guest_cr0->ts = 0;
179     }
180     return 0;
181 }
182
183
184 static int handle_lmsw(struct guest_info * info, struct x86_instr * dec_instr) {
185     struct cr0_real * real_cr0  = (struct cr0_real *)&(info->ctrl_regs.cr0);
186     // XED is a mess, and basically reverses the operand order for an LMSW
187     struct cr0_real * new_cr0 = (struct cr0_real *)(dec_instr->dst_operand.operand);    
188     uchar_t new_cr0_val;
189     
190     PrintDebug(info->vm_info, info, "LMSW\n");
191     
192     new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
193     
194     PrintDebug(info->vm_info, info, "OperandVal = %x\n", new_cr0_val);
195     
196     // We can just copy the new value through
197     // we don't need to virtualize the lower 4 bits
198     PrintDebug(info->vm_info, info, "Old CR0=%x\n", *(uint_t *)real_cr0);       
199     *(uchar_t*)real_cr0 &= 0xf0;
200     *(uchar_t*)real_cr0 |= new_cr0_val;
201     PrintDebug(info->vm_info, info, "New CR0=%x\n", *(uint_t *)real_cr0);       
202     
203     
204     // If Shadow paging is enabled we push the changes to the virtualized copy of cr0
205     if (info->shdw_pg_mode == SHADOW_PAGING) {
206         struct cr0_real * guest_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
207         
208         PrintDebug(info->vm_info, info, "Old Guest CR0=%x\n", *(uint_t *)guest_cr0);    
209         *(uchar_t*)guest_cr0 &= 0xf0;
210         *(uchar_t*)guest_cr0 |= new_cr0_val;
211         PrintDebug(info->vm_info, info, "New Guest CR0=%x\n", *(uint_t *)guest_cr0);    
212     }
213     return 0;
214 }
215
216
217
218
219
220 // First attempt = 253 lines
221 // current = 51 lines
222 int v3_handle_cr0_read(struct guest_info * info) {
223     uchar_t instr[15];
224     int ret;
225     struct x86_instr dec_instr;
226     
227     if (info->mem_mode == PHYSICAL_MEM) { 
228         ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
229     } else { 
230         ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
231     }
232     
233     
234     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
235         PrintError(info->vm_info, info, "Could not decode instruction\n");
236         return -1;
237     }
238     
239     if (dec_instr.op_type == V3_OP_MOVCR2) {
240         PrintDebug(info->vm_info, info, "MOVCR2 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
241
242         if ((v3_get_vm_cpu_mode(info) == LONG) || 
243             (v3_get_vm_cpu_mode(info) == LONG_32_COMPAT)) {
244             struct cr0_64 * dst_reg = (struct cr0_64 *)(dec_instr.dst_operand.operand);
245         
246             if (info->shdw_pg_mode == SHADOW_PAGING) {
247                 struct cr0_64 * guest_cr0 = (struct cr0_64 *)&(info->shdw_pg_state.guest_cr0);
248                 *dst_reg = *guest_cr0;
249             } else {
250                 struct cr0_64 * shadow_cr0 = (struct cr0_64 *)&(info->ctrl_regs.cr0);
251                 *dst_reg = *shadow_cr0;
252             }
253
254             PrintDebug(info->vm_info, info, "returned CR0: %p\n", (void *)*(addr_t *)dst_reg);
255         } else {
256             struct cr0_32 * dst_reg = (struct cr0_32 *)(dec_instr.dst_operand.operand);
257         
258             if (info->shdw_pg_mode == SHADOW_PAGING) {
259                 struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
260                 *dst_reg = *guest_cr0;
261             } else {
262                 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
263                 *dst_reg = *shadow_cr0;
264             }
265
266             PrintDebug(info->vm_info, info, "returned CR0: %x\n", *(uint_t*)dst_reg);
267         }
268
269     } else if (dec_instr.op_type == V3_OP_SMSW) {
270         struct cr0_real * shadow_cr0 = (struct cr0_real *)&(info->ctrl_regs.cr0);
271         struct cr0_real * dst_reg = (struct cr0_real *)(dec_instr.dst_operand.operand);
272         char cr0_val = *(char*)shadow_cr0 & 0x0f;
273         
274         PrintDebug(info->vm_info, info, "SMSW\n");
275         
276         // The lower 4 bits of the guest/shadow CR0 are mapped through
277         // We can treat nested and shadow paging the same here
278         *(char *)dst_reg &= 0xf0;
279         *(char *)dst_reg |= cr0_val;
280         
281     } else {
282         PrintError(info->vm_info, info, "Unhandled opcode in handle_cr0_read\n");
283         return -1;
284     }
285     
286     info->rip += dec_instr.instr_length;
287
288     return 0;
289 }
290
291
292
293
294 // First Attempt = 256 lines
295 // current = 65 lines
296 int v3_handle_cr3_write(struct guest_info * info) {
297     int ret;
298     uchar_t instr[15];
299     struct x86_instr dec_instr;
300     
301     if (info->mem_mode == PHYSICAL_MEM) { 
302         ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
303     } else { 
304         ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
305     }
306     
307     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
308         PrintError(info->vm_info, info, "Could not decode instruction\n");
309         return -1;
310     }
311     
312     if (dec_instr.op_type == V3_OP_MOV2CR) {
313         PrintDebug(info->vm_info, info, "MOV2CR3 (cpu_mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
314         
315         if (info->shdw_pg_mode == SHADOW_PAGING) {
316             PrintDebug(info->vm_info, info, "Old Shadow CR3=%p; Old Guest CR3=%p\n", 
317                        (void *)(addr_t)(info->ctrl_regs.cr3), 
318                        (void*)(addr_t)(info->shdw_pg_state.guest_cr3));
319             
320             
321             // We update the guest CR3    
322             if (info->cpu_mode == LONG) {
323                 struct cr3_64 * new_cr3 = (struct cr3_64 *)(dec_instr.src_operand.operand);
324                 struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
325                 *guest_cr3 = *new_cr3;
326             } else {
327                 struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
328                 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
329                 *guest_cr3 = *new_cr3;
330             }
331
332
333             // If Paging is enabled in the guest then we need to change the shadow page tables
334             if (info->mem_mode == VIRTUAL_MEM) {
335                 if (v3_activate_shadow_pt(info) == -1) {
336                     PrintError(info->vm_info, info, "Failed to activate 32 bit shadow page table\n");
337                     return -1;
338                 }
339             }
340             
341             PrintDebug(info->vm_info, info, "New Shadow CR3=%p; New Guest CR3=%p\n", 
342                        (void *)(addr_t)(info->ctrl_regs.cr3), 
343                        (void*)(addr_t)(info->shdw_pg_state.guest_cr3));
344             
345         } else if (info->shdw_pg_mode == NESTED_PAGING) {
346             
347             // This is just a passthrough operation which we probably don't need here
348             if (info->cpu_mode == LONG) {
349                 struct cr3_64 * new_cr3 = (struct cr3_64 *)(dec_instr.src_operand.operand);
350                 struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3);
351                 *guest_cr3 = *new_cr3;
352             } else {
353                 struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
354                 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
355                 *guest_cr3 = *new_cr3;
356             }
357             
358         }
359     } else {
360         PrintError(info->vm_info, info, "Unhandled opcode in handle_cr3_write\n");
361         return -1;
362     }
363     
364     info->rip += dec_instr.instr_length;
365     
366     return 0;
367 }
368
369
370
371 // first attempt = 156 lines
372 // current = 36 lines
373 int v3_handle_cr3_read(struct guest_info * info) {
374     uchar_t instr[15];
375     int ret;
376     struct x86_instr dec_instr;
377     
378     if (info->mem_mode == PHYSICAL_MEM) { 
379         ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
380     } else { 
381         ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
382     }
383     
384     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
385         PrintError(info->vm_info, info, "Could not decode instruction\n");
386         return -1;
387     }
388     
389     if (dec_instr.op_type == V3_OP_MOVCR2) {
390         PrintDebug(info->vm_info, info, "MOVCR32 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
391         
392         if (info->shdw_pg_mode == SHADOW_PAGING) {
393             
394             if ((v3_get_vm_cpu_mode(info) == LONG) || 
395                 (v3_get_vm_cpu_mode(info) == LONG_32_COMPAT)) {
396                 struct cr3_64 * dst_reg = (struct cr3_64 *)(dec_instr.dst_operand.operand);
397                 struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
398                 *dst_reg = *guest_cr3;
399             } else {
400                 struct cr3_32 * dst_reg = (struct cr3_32 *)(dec_instr.dst_operand.operand);
401                 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
402                 *dst_reg = *guest_cr3;
403             }
404             
405         } else if (info->shdw_pg_mode == NESTED_PAGING) {
406             
407             // This is just a passthrough operation which we probably don't need here
408             if ((v3_get_vm_cpu_mode(info) == LONG) || 
409                 (v3_get_vm_cpu_mode(info) == LONG_32_COMPAT)) {
410                 struct cr3_64 * dst_reg = (struct cr3_64 *)(dec_instr.dst_operand.operand);
411                 struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3);
412                 *dst_reg = *guest_cr3;
413             } else {
414                 struct cr3_32 * dst_reg = (struct cr3_32 *)(dec_instr.dst_operand.operand);
415                 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
416                 *dst_reg = *guest_cr3;
417             }
418         }
419         
420     } else {
421         PrintError(info->vm_info, info, "Unhandled opcode in handle_cr3_read\n");
422         return -1;
423     }
424     
425     info->rip += dec_instr.instr_length;
426     
427     return 0;
428 }
429
430
431 // We don't need to virtualize CR4, all we need is to detect the activation of PAE
432 int v3_handle_cr4_read(struct guest_info * info) {
433     PrintError(info->vm_info, info, "CR4 Read not handled\n");
434     // Do nothing...
435     return 0;
436 }
437
438 int v3_handle_cr4_write(struct guest_info * info) {
439     uchar_t instr[15];
440     int ret;
441     int flush_tlb=0;
442     struct x86_instr dec_instr;
443     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
444     
445     if (info->mem_mode == PHYSICAL_MEM) { 
446         ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
447     } else { 
448         ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
449     }
450     
451     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
452         PrintError(info->vm_info, info, "Could not decode instruction\n");
453         return -1;
454     }
455     
456     if (dec_instr.op_type != V3_OP_MOV2CR) {
457         PrintError(info->vm_info, info, "Invalid opcode in write to CR4\n");
458         return -1;
459     }
460     
461     // Check to see if we need to flush the tlb
462     
463
464     if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) { 
465         struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
466         struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
467         
468         // if pse, pge, or pae have changed while PG (in any mode) is on
469         // the side effect is a TLB flush, which means we need to
470         // toss the current shadow page tables too
471         //
472         // 
473         // TODO - PAE FLAG needs to be special cased
474         if ((cr4->pse != new_cr4->pse) || 
475             (cr4->pge != new_cr4->pge) || 
476             (cr4->pae != new_cr4->pae)) { 
477             PrintDebug(info->vm_info, info, "Handling PSE/PGE/PAE -> TLBFlush case, flag set\n");
478             flush_tlb = 1;
479             
480         }
481     }
482     
483
484     if ((cpu_mode == PROTECTED) || (cpu_mode == PROTECTED_PAE)) {
485         struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
486         struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
487         
488         PrintDebug(info->vm_info, info, "OperandVal = %x, length = %d\n", *(uint_t *)new_cr4, dec_instr.src_operand.size);
489         PrintDebug(info->vm_info, info, "Old CR4=%x\n", *(uint_t *)cr4);
490         
491         if ((info->shdw_pg_mode == SHADOW_PAGING)) { 
492             if (v3_get_vm_mem_mode(info) == PHYSICAL_MEM) {
493                 
494                 if ((cr4->pae == 0) && (new_cr4->pae == 1)) {
495                     PrintDebug(info->vm_info, info, "Creating PAE passthrough tables\n");
496                     
497                     // create 32 bit PAE direct map page table
498                     if (v3_reset_passthrough_pts(info) == -1) {
499                         PrintError(info->vm_info, info, "Could not create 32 bit PAE passthrough pages tables\n");
500                         return -1;
501                     }
502
503                     // reset cr3 to new page tables
504                     info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
505                     
506                 } else if ((cr4->pae == 1) && (new_cr4->pae == 0)) {
507                     // Create passthrough standard 32bit pagetables
508                     PrintError(info->vm_info, info, "Switching From PAE to Protected mode not supported\n");
509                     return -1;
510                 } 
511             }
512         }
513         
514         *cr4 = *new_cr4;
515         PrintDebug(info->vm_info, info, "New CR4=%x\n", *(uint_t *)cr4);
516         
517     } else if ((cpu_mode == LONG) || (cpu_mode == LONG_32_COMPAT)) {
518         struct cr4_64 * new_cr4 = (struct cr4_64 *)(dec_instr.src_operand.operand);
519         struct cr4_64 * cr4 = (struct cr4_64 *)&(info->ctrl_regs.cr4);
520         
521         PrintDebug(info->vm_info, info, "Old CR4=%p\n", (void *)*(addr_t *)cr4);
522         PrintDebug(info->vm_info, info, "New CR4=%p\n", (void *)*(addr_t *)new_cr4);
523         
524         if (new_cr4->pae == 0) {
525             // cannot turn off PAE in long mode GPF the guest
526             PrintError(info->vm_info, info, "Cannot disable PAE in long mode, should send GPF\n");
527             return -1;
528         }
529         
530         *cr4 = *new_cr4;
531         
532     } else {
533         PrintError(info->vm_info, info, "CR4 write not supported in CPU_MODE: %s\n", v3_cpu_mode_to_str(cpu_mode));
534         return -1;
535     }
536     
537     if (info->shdw_pg_mode == SHADOW_PAGING) {
538         if (flush_tlb) {
539             PrintDebug(info->vm_info, info, "Handling PSE/PGE/PAE -> TLBFlush (doing flush now!)\n");
540             if (v3_activate_shadow_pt(info) == -1) {
541                 PrintError(info->vm_info, info, "Failed to activate shadow page tables when emulating TLB flush in handling cr4 write\n");
542                 return -1;
543             }
544         }
545     }
546     
547     info->rip += dec_instr.instr_length;
548     return 0;
549 }
550
551
552 /*
553   The CR8 and APIC TPR interaction are kind of crazy.
554
555   CR8 mandates that the priority class is in bits 3:0
556
557   The interaction of CR8 and an actual APIC is somewhat implementation dependent, but
558   a basic current APIC has the priority class at 7:4 and the *subclass* at 3:0
559
560   The APIC TPR (both fields) can be written as the APIC register
561   A write to CR8 sets the priority class field, and should zero the subclass
562   A read from CR8 gets just the priority class field
563
564   In the apic_tpr storage location, we have:
565
566      zeros [class] [subclass]
567
568   Because of this, an APIC implementation should use apic_tpr to store its TPR
569   In fact, it *should* do this, otherwise its TPR may get out of sync with the architected TPR
570
571   On a CR8 read, we return just 
572
573      zeros 0000  [class]
574
575   On a CR8 write, we set the register to
576
577      zeros [class] 0000
578
579 */
580
581 int v3_handle_cr8_write(struct guest_info * info) {
582     int ret;
583     uchar_t instr[15];
584     struct x86_instr dec_instr;
585     
586     if (info->mem_mode == PHYSICAL_MEM) { 
587         ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
588     } else { 
589         ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
590     }
591     
592     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
593         PrintError(info->vm_info, info, "Could not decode instruction\n");
594         return -1;
595     }
596     
597     if (dec_instr.op_type == V3_OP_MOV2CR) {
598         PrintDebug(info->vm_info, info, "MOV2CR8 (cpu_mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
599         
600         if ((info->cpu_mode == LONG) ||
601             (info->cpu_mode == LONG_32_COMPAT)) {
602             uint64_t *val = (uint64_t *)(dec_instr.src_operand.operand);
603
604             info->ctrl_regs.apic_tpr = (*val & 0xf) << 4;
605
606             V3_Print(info->vm_info, info, "Write of CR8 sets apic_tpr to 0x%llx\n",info->ctrl_regs.apic_tpr);
607
608         }  else {
609             // probably should raise exception here
610         }
611     } else {
612         PrintError(info->vm_info, info, "Unhandled opcode in handle_cr8_write\n");
613         return -1;
614     }
615     
616     info->rip += dec_instr.instr_length;
617     
618     return 0;
619 }
620
621
622
623 int v3_handle_cr8_read(struct guest_info * info) {
624     uchar_t instr[15];
625     int ret;
626     struct x86_instr dec_instr;
627     
628     if (info->mem_mode == PHYSICAL_MEM) { 
629         ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
630     } else { 
631         ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
632     }
633     
634     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
635         PrintError(info->vm_info, info, "Could not decode instruction\n");
636         return -1;
637     }
638     
639     if (dec_instr.op_type == V3_OP_MOVCR2) {
640         PrintDebug(info->vm_info, info, "MOVCR82 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
641         
642         if ((info->cpu_mode == LONG) || 
643             (info->cpu_mode == LONG_32_COMPAT)) {
644             uint64_t *dst_reg = (uint64_t *)(dec_instr.dst_operand.operand);
645
646             *dst_reg = (info->ctrl_regs.apic_tpr >> 4) & 0xf;
647
648             V3_Print(info->vm_info, info, "Read of CR8 (apic_tpr) returns 0x%llx\n",*dst_reg);
649
650         } else {
651             // probably should raise exception
652         }
653             
654     } else {
655         PrintError(info->vm_info, info, "Unhandled opcode in handle_cr8_read\n");
656         return -1;
657     }
658     
659     info->rip += dec_instr.instr_length;
660     
661     return 0;
662 }
663
664
665 int v3_handle_efer_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
666     PrintDebug(core->vm_info, core, "EFER Read HI=%x LO=%x\n", core->shdw_pg_state.guest_efer.hi, core->shdw_pg_state.guest_efer.lo);
667     
668     dst->value = core->shdw_pg_state.guest_efer.value;
669     
670     return 0;
671 }
672
673
674 int v3_handle_efer_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
675     struct v3_msr *  vm_efer     = &(core->shdw_pg_state.guest_efer);
676     struct efer_64 * hw_efer     = (struct efer_64 *)&(core->ctrl_regs.efer);
677     struct efer_64   old_hw_efer = *((struct efer_64 *)&core->ctrl_regs.efer);
678     
679     PrintDebug(core->vm_info, core, "EFER Write HI=%x LO=%x\n", src.hi, src.lo);
680
681     // Set EFER value seen by guest if it reads EFER
682     vm_efer->value = src.value;
683
684     // Set EFER value seen by hardware while the guest is running
685     *(uint64_t *)hw_efer = src.value;
686
687     // We have gotten here either because we are using
688     // shadow paging, or we are using nested paging on SVM
689     // In the latter case, we don't need to do anything
690     // like the following
691     if (core->shdw_pg_mode == SHADOW_PAGING) { 
692       // Catch unsupported features
693       if ((old_hw_efer.lme == 1) && (hw_efer->lme == 0)) {
694         PrintError(core->vm_info, core, "Disabling long mode once it has been enabled is not supported\n");
695         return -1;
696       }
697       
698       // Set LME and LMA bits seen by hardware
699       if (old_hw_efer.lme == 0) {
700         // Long mode was not previously enabled, so the lme bit cannot
701         // be set yet. It will be set later when the guest sets CR0.PG
702         // to enable paging.
703         hw_efer->lme = 0;
704       } else {
705         // Long mode was previously enabled. Ensure LMA bit is set.
706         // VMX does not automatically set LMA, and this should not affect SVM.
707         hw_efer->lma = 1;
708       }
709     }
710       
711       
712     PrintDebug(core->vm_info, core, "RIP=%p\n", (void *)core->rip);
713     PrintDebug(core->vm_info, core, "New EFER value HW(hi=%p), VM(hi=%p)\n", (void *)*(uint64_t *)hw_efer, (void *)vm_efer->value); 
714
715
716     return 0;
717 }
718
719 int v3_handle_vm_cr_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
720     /* tell the guest that the BIOS disabled SVM, that way it doesn't get 
721      * confused by the fact that CPUID reports SVM as available but it still
722      * cannot be used 
723      */
724     dst->value = SVM_VM_CR_MSR_lock | SVM_VM_CR_MSR_svmdis;
725     PrintDebug(core->vm_info, core, "VM_CR Read HI=%x LO=%x\n", dst->hi, dst->lo);
726     return 0;
727 }
728
729 int v3_handle_vm_cr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
730     PrintDebug(core->vm_info, core, "VM_CR Write\n");
731     PrintDebug(core->vm_info, core, "VM_CR Write Values: HI=%x LO=%x\n", src.hi, src.lo);
732
733     /* writes to LOCK and SVMDIS are silently ignored (according to the spec), 
734      * other writes indicate the guest wants to use some feature we haven't
735      * implemented
736      */
737     if (src.value & ~(SVM_VM_CR_MSR_lock | SVM_VM_CR_MSR_svmdis)) {
738         PrintDebug(core->vm_info, core, "VM_CR write sets unsupported bits: HI=%x LO=%x\n", src.hi, src.lo);
739         return -1;
740     }
741     
742     return 0;
743 }