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.


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