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.


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