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.


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