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.


Added RTC functionality (including interrupt injection) to nvram
[palacios.git] / palacios / src / palacios / vmm_ctrl_regs.c
1 #include <palacios/vmm_mem.h>
2 #include <palacios/vmm.h>
3 #include <palacios/vmcb.h>
4 #include <palacios/vmm_decoder.h>
5 #include <palacios/vm_guest_mem.h>
6 #include <palacios/vmm_ctrl_regs.h>
7
8
9
10 /* Segmentation is a problem here...
11  *
12  * When we get a memory operand, presumably we use the default segment (which is?) 
13  * unless an alternate segment was specfied in the prefix...
14  */
15
16
17 #ifndef DEBUG_CTRL_REGS
18 #undef PrintDebug
19 #define PrintDebug(fmt, args...)
20 #endif
21
22
23
24
25
26
27
28 int handle_cr0_write(struct guest_info * info) {
29   char instr[15];
30   int ret;
31   struct x86_instr dec_instr;
32
33   if (info->mem_mode == PHYSICAL_MEM) { 
34     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
35   } else { 
36     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
37   }
38
39   if (ret != 15) {
40     // I think we should inject a GPF into the guest
41     PrintError("Could not read instruction (ret=%d)\n", ret);
42     return -1;
43   }
44
45   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
46     PrintError("Could not decode instruction\n");
47     return -1;
48   }
49
50
51   if (opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
52     struct cr0_real *real_cr0  = (struct cr0_real*)&(info->ctrl_regs.cr0);
53     struct cr0_real *new_cr0 = (struct cr0_real *)(dec_instr.first_operand.operand);    
54     uchar_t new_cr0_val;
55
56     PrintDebug("LMSW\n");
57
58     new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
59     
60     PrintDebug("OperandVal = %x\n", new_cr0_val);
61
62     PrintDebug("Old CR0=%x\n", *real_cr0);      
63     *(uchar_t*)real_cr0 &= 0xf0;
64     *(uchar_t*)real_cr0 |= new_cr0_val;
65     PrintDebug("New CR0=%x\n", *real_cr0);      
66       
67
68     if (info->shdw_pg_mode == SHADOW_PAGING) {
69       struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
70       
71       PrintDebug(" Old Shadow CR0=%x\n", *shadow_cr0);  
72       *(uchar_t*)shadow_cr0 &= 0xf0;
73       *(uchar_t*)shadow_cr0 |= new_cr0_val;
74       PrintDebug("New Shadow CR0=%x\n", *shadow_cr0);   
75     }
76   } else if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
77     PrintDebug("MOV2CR0\n");
78
79     if (info->cpu_mode == LONG) {
80       // 64 bit registers
81     } else {
82       // 32 bit registers
83         struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
84         struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.second_operand.operand);
85
86         PrintDebug("OperandVal = %x, length=%d\n", *new_cr0, dec_instr.first_operand.size);
87
88
89         PrintDebug("Old CR0=%x\n", *real_cr0);
90         *real_cr0 = *new_cr0;
91         
92
93         if (info->shdw_pg_mode == SHADOW_PAGING) {
94           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
95           
96           PrintDebug("Old Shadow CR0=%x\n", *shadow_cr0);       
97           
98           real_cr0->et = 1;
99           
100           *shadow_cr0 = *new_cr0;
101           shadow_cr0->et = 1;
102           
103           if (get_mem_mode(info) == VIRTUAL_MEM) {
104             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
105             
106             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
107           } else  {
108             info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
109             real_cr0->pg = 1;
110           }
111           
112           PrintDebug("New Shadow CR0=%x\n",*shadow_cr0);
113         }
114         PrintDebug("New CR0=%x\n", *real_cr0);
115     }
116
117   } else if (opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
118     // CLTS
119     struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
120         
121     real_cr0->ts = 0;
122
123     if (info->shdw_pg_mode == SHADOW_PAGING) {
124       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
125       shadow_cr0->ts = 0;
126     }
127   }
128
129   info->rip += dec_instr.instr_length;
130
131   return 0;
132 }
133
134
135 int handle_cr0_read(struct guest_info * info) {
136   char instr[15];
137
138   switch (info->cpu_mode) { 
139
140   case REAL: 
141     {
142
143       int index = 0;
144       int ret;
145
146       PrintDebug("Real Mode read from CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
147       //PrintV3Segments(info);
148
149       // The real rip address is actually a combination of the rip + CS base 
150       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
151       if (ret != 15) {
152         // I think we should inject a GPF into the guest
153         PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
154         return -1;
155       }
156
157
158       while (is_prefix_byte(instr[index])) {
159         switch(instr[index]) {
160         case PREFIX_CS_OVERRIDE:
161         case PREFIX_SS_OVERRIDE:
162         case PREFIX_DS_OVERRIDE:
163         case PREFIX_ES_OVERRIDE:
164         case PREFIX_FS_OVERRIDE:
165         case PREFIX_GS_OVERRIDE:
166           PrintDebug("Segment Override!!\n");
167           return -1;
168           break;
169         default:
170           break;
171         }
172         index++; 
173       }
174
175       /*
176         while (is_prefix_byte(instr[index])) {
177         index++; 
178         }
179       */
180
181       if ((instr[index] == cr_access_byte) && 
182           (instr[index + 1] == smsw_byte) && 
183           (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
184
185         // SMSW (store machine status word)
186
187         addr_t first_operand;
188         addr_t second_operand;
189         struct cr0_real *cr0;
190         operand_type_t addr_type;
191         char cr0_val = 0;
192
193         index += 2;
194       
195         cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
196       
197       
198         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
199       
200         if (addr_type == MEM_OPERAND) {
201           addr_t host_addr;
202         
203           if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
204             // gpf the guest
205             PrintDebug("Could not convert guest physical address to host virtual address\n");
206             return -1;
207           }
208         
209           first_operand = host_addr;
210         } else {
211           // Register operand
212           // Should be ok??
213         }
214
215         cr0_val = *(char*)cr0 & 0x0f;
216
217         *(char *)first_operand &= 0xf0;
218         *(char *)first_operand |= cr0_val;
219
220         PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
221         info->rip += index;
222         PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
223         // success
224
225       } else if ((instr[index] == cr_access_byte) &&
226                  (instr[index+1] == mov_from_cr_byte)) {
227         /* Mov from CR0
228          * This can only take a 32 bit register argument in anything less than 64 bit mode.
229          */
230         addr_t first_operand;
231         addr_t second_operand;
232         operand_type_t addr_type;
233
234         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
235
236         index += 2;
237
238         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
239      
240         struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
241   
242         if (addr_type != REG_OPERAND) {
243           // invalid opcode to guest
244           PrintDebug("Invalid operand type in mov from CR0\n");
245           return -1;
246         }
247
248         if (info->shdw_pg_mode == SHADOW_PAGING) {
249           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
250         } else {
251           *virt_cr0 = *real_cr0;
252         }
253
254         PrintDebug("Returning CR0: %x\n", *virt_cr0);
255
256         info->rip += index;
257
258       } else {
259         PrintDebug("Unknown read instr from CR0\n");
260         return -1;
261       }
262
263     } 
264
265     break;
266
267   case PROTECTED:
268     {
269     
270       int index = 0;
271       int ret;
272
273       PrintDebug("Protected %s Mode read from CR0 at guest %s linear rip 0x%x\n", 
274                  info->mem_mode == VIRTUAL_MEM ? "Paged" : "",
275                  info->mem_mode == VIRTUAL_MEM ? "virtual" : "",
276                  get_addr_linear(info, info->rip, &(info->segments.cs)));
277
278       // We need to read the instruction, which is at CS:IP, but that 
279       // linear address is guest physical without PG and guest virtual with PG
280       if (info->cpu_mode == PHYSICAL_MEM) { 
281         // The real rip address is actually a combination of the rip + CS base 
282         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
283       } else { 
284         // The real rip address is actually a combination of the rip + CS base 
285         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
286       }
287
288
289       /*
290         PrintDebug("Instr (15 bytes) at %x:\n", instr);
291         PrintTraceMemDump((char*)instr, 15);
292       */
293
294       if (ret != 15) {
295         // I think we should inject a GPF into the guest
296         PrintDebug("Could not read Protected %s mode instruction (ret=%d)\n", 
297                    info->cpu_mode == VIRTUAL_MEM ? "Paged" : "", ret);
298         return -1;
299       }
300
301
302       while (is_prefix_byte(instr[index])) {
303         switch(instr[index]) {
304         case PREFIX_CS_OVERRIDE:
305         case PREFIX_SS_OVERRIDE:
306         case PREFIX_DS_OVERRIDE:
307         case PREFIX_ES_OVERRIDE:
308         case PREFIX_FS_OVERRIDE:
309         case PREFIX_GS_OVERRIDE:
310           PrintDebug("Segment Override!!\n");
311           return -1;
312           break;
313         default:
314           break;
315         }
316         index++; 
317       }
318
319
320       /*
321         while (is_prefix_byte(instr[index])) {
322         index++; 
323         }
324       */
325
326       if ((instr[index] == cr_access_byte) &&
327           (instr[index+1] == mov_from_cr_byte)) {
328         
329         // MOV from CR0 to register
330
331         addr_t first_operand;
332         addr_t second_operand;
333         operand_type_t addr_type;
334         struct cr0_32 * virt_cr0;
335         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
336
337         index += 2;
338
339         addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
340
341         if (addr_type != REG_OPERAND) {
342           PrintDebug("Invalid operand type in mov from CR0\n");
343           return -1;
344         }
345       
346         virt_cr0 = (struct cr0_32 *)first_operand;
347
348         if (info->shdw_pg_mode == SHADOW_PAGING) {
349           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
350           
351           if (info->mem_mode == PHYSICAL_MEM) {
352             virt_cr0->pg = 0; // clear the pg bit because guest doesn't think it's on
353           }
354           
355         } else {
356           *virt_cr0 = *real_cr0;
357         }
358
359           PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
360           PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
361       
362         info->rip += index;
363
364       } else { 
365         PrintDebug("Unknown read instruction from CR0\n");
366         return -1;
367       }
368     }
369     break;
370
371   case PROTECTED_PAE:
372     PrintDebug("Protected PAE Mode read to CR0 is UNIMPLEMENTED\n");
373     return -1;
374
375   case LONG:
376     PrintDebug("Protected Long Mode read to CR0 is UNIMPLEMENTED\n");
377     return -1;
378
379
380   default:
381     {
382       PrintDebug("Unknown Mode read from CR0 (info->cpu_mode=0x%x)\n",info->cpu_mode);
383       return -1;
384     }
385     break;
386   }
387
388
389   return 0;
390 }
391
392
393
394
395 int handle_cr3_write(struct guest_info * info) {
396   if (info->cpu_mode == REAL) {
397     // WHAT THE HELL DOES THIS EVEN MEAN?????
398
399     int index = 0;
400     int ret;
401     char instr[15];
402
403     PrintDebug("Real Mode Write to CR3.\n");
404     // We need to read the instruction, which is at CS:IP, but that 
405     // linear address is guest physical without PG and guest virtual with PG
406
407     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
408
409     if (ret != 15) {
410       PrintDebug("Could not read instruction (ret=%d)\n", ret);
411       return -1;
412     }
413
414     while (is_prefix_byte(instr[index])) {
415       switch(instr[index]) {
416       case PREFIX_CS_OVERRIDE:
417       case PREFIX_SS_OVERRIDE:
418       case PREFIX_DS_OVERRIDE:
419       case PREFIX_ES_OVERRIDE:
420       case PREFIX_FS_OVERRIDE:
421       case PREFIX_GS_OVERRIDE:
422         PrintDebug("Segment Override!!\n");
423         return -1;
424         break;
425       default:
426         break;
427       }
428       index++; 
429     }
430     
431
432     if ((instr[index] == cr_access_byte) && 
433         (instr[index + 1] == mov_to_cr_byte)) {
434
435       addr_t first_operand;
436       addr_t second_operand;
437       struct cr3_32 * new_cr3;
438       //      struct cr3_32 * real_cr3;
439       operand_type_t addr_type;
440
441       index += 2;
442
443       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
444
445       if (addr_type != REG_OPERAND) {
446         /* Mov to CR3 can only be a 32 bit register */
447         return -1;
448       }
449
450       new_cr3 = (struct cr3_32 *)first_operand;
451
452       if (info->shdw_pg_mode == SHADOW_PAGING) {
453         int flushed=0;
454         addr_t shadow_pt;
455         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
456         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
457
458         /*
459
460           if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) {
461             PrintDebug("Shadow Page Table\n");
462             PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
463           }
464         */
465
466         /* Delete the current Page Tables */
467         if (!CR3_32_SAME_BASE(new_cr3,guest_cr3)) { 
468           PrintDebug("New CR3 is different - flushing shadow page table\n");
469           delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
470           flushed=1;
471         } else {
472           PrintDebug("New CR3 (0x%x) has same base as previous CR3 (0x%x) - reusing shadow page table\n", *((uint_t*)new_cr3), *((uint_t*)guest_cr3));
473         }
474
475         PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
476                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
477
478
479         *guest_cr3 = *new_cr3;
480
481
482         if (flushed) { 
483           // Something like this
484           shadow_pt =  create_new_shadow_pt32(info);
485           //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
486         } else {
487           shadow_pt = shadow_cr3->pdt_base_addr<<12;
488         }
489
490         /* Copy Various flags */
491         *shadow_cr3 = *new_cr3;
492
493         /*
494         {
495           addr_t tmp_addr;
496           guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr);
497           PrintDebug("Guest PD\n");
498           PrintPD32((pde32_t *)tmp_addr);
499
500         }
501         */
502
503         
504         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
505
506         PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
507                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
508
509       }
510       info->rip += index;
511
512     } else {
513       PrintDebug("Unknown Instruction\n");
514       PrintTraceMemDump(instr,15);
515       return -1;
516     }
517
518
519
520   } else if (info->cpu_mode == PROTECTED) {
521     int index = 0;
522     int ret;
523     char instr[15];
524
525     PrintDebug("Protected %s mode write to CR3 at %s 0x%x\n",
526                info->cpu_mode==PROTECTED ? "" : "Paged", 
527                info->cpu_mode==PROTECTED ? "guest physical" : "guest virtual",
528                get_addr_linear(info,info->rip,&(info->segments.cs)));
529
530     // We need to read the instruction, which is at CS:IP, but that 
531     // linear address is guest physical without PG and guest virtual with PG
532     if (info->mem_mode == PHYSICAL_MEM) { 
533       // The real rip address is actually a combination of the rip + CS base 
534       //PrintDebug("Writing Guest CR3 Write (Physical Address)\n");
535       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
536     } else { 
537       //PrintDebug("Writing Guest CR3 Write (Virtual Address)\n");
538       // The real rip address is actually a combination of the rip + CS base 
539       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
540     }
541
542     if (ret != 15) {
543       PrintDebug("Could not read instruction (ret=%d)\n", ret);
544       return -1;
545     }
546
547     while (is_prefix_byte(instr[index])) {
548       switch(instr[index]) {
549       case PREFIX_CS_OVERRIDE:
550       case PREFIX_SS_OVERRIDE:
551       case PREFIX_DS_OVERRIDE:
552       case PREFIX_ES_OVERRIDE:
553       case PREFIX_FS_OVERRIDE:
554       case PREFIX_GS_OVERRIDE:
555         PrintDebug("Segment Override!!\n");
556         return -1;
557         break;
558       default:
559         break;
560       }
561       index++; 
562     }
563     
564     /*    
565           while (is_prefix_byte(instr[index])) {
566           index++;
567           }
568     */
569
570     if ((instr[index] == cr_access_byte) && 
571         (instr[index + 1] == mov_to_cr_byte)) {
572
573       addr_t first_operand;
574       addr_t second_operand;
575       struct cr3_32 * new_cr3;
576       //      struct cr3_32 * real_cr3;
577       operand_type_t addr_type;
578
579       index += 2;
580
581       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
582
583       if (addr_type != REG_OPERAND) {
584         /* Mov to CR3 can only be a 32 bit register */
585         return -1;
586       }
587
588       new_cr3 = (struct cr3_32 *)first_operand;
589
590       if (info->shdw_pg_mode == SHADOW_PAGING) {
591         int flushed=0;
592         addr_t shadow_pt;
593         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
594         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
595
596
597         /*
598           if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) {
599             PrintDebug("Shadow Page Table\n");
600             PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
601           }
602         */
603
604         /* Delete the current Page Tables */
605         if (!CR3_32_SAME_BASE(guest_cr3,new_cr3)) { 
606           PrintDebug("New CR3 is different - flushing shadow page table\n");
607           delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
608           flushed=1;
609         } else {
610           PrintDebug("New CR3 (0x%x) has same base as previous CR3 (0x%x) - reusing shadow page table\n",*((uint_t*)new_cr3), *((uint_t*)guest_cr3));
611         }
612
613         PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
614                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
615
616
617         *guest_cr3 = *new_cr3;
618
619         if (flushed) { 
620           // Something like this
621           shadow_pt =  create_new_shadow_pt32(info);
622           //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
623         } else {
624           shadow_pt =shadow_cr3->pdt_base_addr << 12;
625         }
626
627
628         /* Copy Various flags */
629         *shadow_cr3 = *new_cr3;
630
631         /*
632         {
633           addr_t tmp_addr;
634           guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr);
635           PrintDebug("Guest PD\n");
636           PrintPD32((pde32_t *)tmp_addr);
637
638         }
639         */
640
641         
642         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
643
644         PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
645                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
646
647
648
649         if (info->mem_mode == VIRTUAL_MEM) {
650           // If we aren't in paged mode then we have to preserve the identity mapped CR3
651           info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
652         }
653       }
654
655       info->rip += index;
656
657     } else {
658       PrintDebug("Unknown Instruction\n");
659       PrintTraceMemDump(instr,15);
660       return -1;
661     }
662   } else {
663     PrintDebug("Invalid operating Mode (0x%x)\n", info->cpu_mode);
664     return -1;
665   }
666
667   return 0;
668 }
669
670
671
672
673 int handle_cr3_read(struct guest_info * info) {
674
675   if (info->cpu_mode == REAL) {
676     char instr[15];
677     int ret;
678     int index = 0;
679     addr_t linear_addr = 0;
680
681     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
682
683     
684     //PrintDebug("RIP Linear: %x\n", linear_addr);
685     //PrintV3Segments(info);
686     
687     ret = read_guest_pa_memory(info, linear_addr, 15, instr);
688
689     if (ret != 15) {
690       PrintDebug("Could not read instruction (ret=%d)\n", ret);
691       return -1;
692     }
693     
694     while (is_prefix_byte(instr[index])) {
695       switch(instr[index]) {
696       case PREFIX_CS_OVERRIDE:
697       case PREFIX_SS_OVERRIDE:
698       case PREFIX_DS_OVERRIDE:
699       case PREFIX_ES_OVERRIDE:
700       case PREFIX_FS_OVERRIDE:
701       case PREFIX_GS_OVERRIDE:
702         PrintDebug("Segment Override!!\n");
703         return -1;
704         break;
705       default:
706         break;
707       }
708       index++; 
709     }
710
711
712     if ((instr[index] == cr_access_byte) && 
713         (instr[index + 1] == mov_from_cr_byte)) {
714       addr_t first_operand;
715       addr_t second_operand;
716       struct cr3_32 * virt_cr3;
717       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
718       operand_type_t addr_type;
719
720       index += 2;
721
722       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
723
724       if (addr_type != REG_OPERAND) {
725         /* Mov to CR3 can only be a 32 bit register */
726         return -1;
727       }
728
729       virt_cr3 = (struct cr3_32 *)first_operand;
730
731       if (info->shdw_pg_mode == SHADOW_PAGING) {
732         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
733       } else {
734         *virt_cr3 = *real_cr3;
735       }
736       
737       info->rip += index;
738     } else {
739       PrintDebug("Unknown Instruction\n");
740       PrintTraceMemDump(instr,15);
741       return -1;
742     }
743
744
745     return 0;
746   } else if (info->cpu_mode == PROTECTED) {
747
748     int index = 0;
749     int ret;
750     char instr[15];
751
752    
753     // We need to read the instruction, which is at CS:IP, but that 
754     // linear address is guest physical without PG and guest virtual with PG
755     if (info->cpu_mode == PHYSICAL_MEM) { 
756       // The real rip address is actually a combination of the rip + CS base 
757       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
758     } else { 
759       // The real rip address is actually a combination of the rip + CS base 
760       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
761     }
762
763     if (ret != 15) {
764       PrintDebug("Could not read instruction (ret=%d)\n", ret);
765       return -1;
766     }
767     
768     while (is_prefix_byte(instr[index])) {
769       switch(instr[index]) {
770       case PREFIX_CS_OVERRIDE:
771       case PREFIX_SS_OVERRIDE:
772       case PREFIX_DS_OVERRIDE:
773       case PREFIX_ES_OVERRIDE:
774       case PREFIX_FS_OVERRIDE:
775       case PREFIX_GS_OVERRIDE:
776         PrintDebug("Segment Override!!\n");
777         return -1;
778         break;
779       default:
780         break;
781       }
782       index++; 
783     }
784
785     /*
786       while (is_prefix_byte(instr[index])) {
787       index++;
788       }
789     */
790
791     if ((instr[index] == cr_access_byte) && 
792         (instr[index + 1] == mov_from_cr_byte)) {
793       addr_t first_operand;
794       addr_t second_operand;
795       struct cr3_32 * virt_cr3;
796       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
797       operand_type_t addr_type;
798
799       index += 2;
800
801       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
802
803       if (addr_type != REG_OPERAND) {
804         /* Mov to CR3 can only be a 32 bit register */
805         return -1;
806       }
807
808       virt_cr3 = (struct cr3_32 *)first_operand;
809
810       if (info->shdw_pg_mode == SHADOW_PAGING) {
811         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
812       } else {
813         *virt_cr3 = *real_cr3;
814       }
815       
816       info->rip += index;
817     } else {
818       PrintDebug("Unknown Instruction\n");
819       PrintTraceMemDump(instr,15);
820       return -1;
821     }
822   } else {
823     PrintDebug("Invalid operating Mode (0x%x), control registers follow\n", info->cpu_mode);
824     PrintV3CtrlRegs(info);
825     return -1;
826   }
827
828   return 0;
829 }