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.


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