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.


some nested paging fixes
[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       PrintV3Segments(info);
33
34       // The real rip address is actually a combination of the rip + CS base 
35       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
36       if (ret != 15) {
37         // I think we should inject a GPF into the guest
38         PrintDebug("Could not read instruction (ret=%d)\n", ret);
39         return -1;
40       }
41
42       while (is_prefix_byte(instr[index])) {
43         switch(instr[index]) {
44         case PREFIX_CS_OVERRIDE:
45         case PREFIX_SS_OVERRIDE:
46         case PREFIX_DS_OVERRIDE:
47         case PREFIX_ES_OVERRIDE:
48         case PREFIX_FS_OVERRIDE:
49         case PREFIX_GS_OVERRIDE:
50           PrintDebug("Segment Override!!\n");
51           return -1;
52           break;
53         default:
54           break;
55         }
56         index++; 
57       }
58
59       if ((instr[index] == cr_access_byte) && 
60           (instr[index + 1] == lmsw_byte) && 
61           (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
62  
63         addr_t first_operand;
64         addr_t second_operand;
65         struct cr0_real *real_cr0;
66         struct cr0_real *new_cr0;
67         operand_type_t addr_type;
68         char new_cr0_val = 0;
69         // LMSW
70         // decode mod/RM
71         index += 2;
72  
73         real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
74
75         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
76
77
78         if (addr_type == REG_OPERAND) {
79           new_cr0 = (struct cr0_real *)first_operand;
80         } else if (addr_type == MEM_OPERAND) {
81           addr_t host_addr;
82
83           if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
84             // gpf the guest
85             return -1;
86           }
87
88           new_cr0 = (struct cr0_real *)host_addr;
89         } else {
90
91           // error... don't know what to do
92           return -1;
93         }
94                  
95         if ((new_cr0->pe == 1) && (real_cr0->pe == 0)) {
96           info->cpu_mode = PROTECTED;
97         } else if ((new_cr0->pe == 0) && (real_cr0->pe == 1)) {
98           info->cpu_mode = REAL;
99         }
100       
101         new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
102
103
104         if (info->shdw_pg_mode == SHADOW_PAGING) {
105           struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
106
107           PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
108           /* struct cr0_real is only 4 bits wide, 
109            * so we can overwrite the real_cr0 without worrying about the shadow fields
110            */
111           *(char*)real_cr0 &= 0xf0;
112           *(char*)real_cr0 |= new_cr0_val;
113         
114           *(char*)shadow_cr0 &= 0xf0;
115           *(char*)shadow_cr0 |= new_cr0_val;
116
117
118           PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
119         } else {
120           PrintDebug("Old CR0=%x\n", *real_cr0);        
121           // for now we just pass through....
122           *(char*)real_cr0 &= 0xf0;
123           *(char*)real_cr0 |= new_cr0_val;
124
125           PrintDebug("New CR0=%x\n", *real_cr0);        
126         }
127
128
129         info->rip += index;
130
131       } else if ((instr[index] == cr_access_byte) && 
132                  (instr[index + 1] == clts_byte)) {
133         // CLTS
134         PrintDebug("CLTS unhandled in CR0 write\n");
135         return -1;
136
137       } else if ((instr[index] == cr_access_byte) && 
138                  (instr[index + 1] = mov_to_cr_byte)) {
139         addr_t first_operand;
140         addr_t second_operand;
141         struct cr0_32 *real_cr0;
142         struct cr0_32 *new_cr0;
143         operand_type_t addr_type;
144      
145       
146         index += 2;
147  
148         real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
149
150         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
151
152         if (addr_type != REG_OPERAND) {
153           PrintDebug("Moving to CR0 from non-register operand in CR0 write\n");
154           /* Mov to CR0 Can only be a 32 bit register */
155           // FIX ME
156           return -1;
157         }
158
159         new_cr0 = (struct cr0_32 *)first_operand;
160
161         if (new_cr0->pe == 1) {
162           PrintDebug("Entering Protected Mode\n");
163           info->cpu_mode = PROTECTED;
164         }
165
166         if (new_cr0->pe == 0) { 
167           PrintDebug("Entering Real Mode\n");
168           info->cpu_mode = REAL;
169         }
170           
171
172
173         if ((new_cr0->pg == 1) && (new_cr0->pe == 1)) {
174           PrintDebug("Paging is already turned on in switch to protected mode in CR0 write\n");
175
176           // Actually This appears to be Ok. 
177           // Why shouldn't windows be allowed to switch to real mode whenever it wants to modify its page tables?
178
179           info->mem_mode = VIRTUAL_MEM;
180
181           // GPF the guest??
182           //  return -1;
183         } else if ((new_cr0->pg == 1) && (new_cr0->pe == 0)) {
184           PrintDebug("Will the madness Never End??\n");
185           return -1;
186         }
187         
188
189         if (info->shdw_pg_mode == SHADOW_PAGING) {
190           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
191         
192           PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
193           *real_cr0 = *new_cr0;
194           real_cr0->pg = 1;
195           real_cr0->et = 1;
196
197           *shadow_cr0 = *new_cr0;
198           shadow_cr0->et = 1;
199
200           // Setup the page tables...???
201           if (info->mem_mode == VIRTUAL_MEM) {
202             // If we aren't in paged mode then we have to preserve the identity mapped CR3
203             info->ctrl_regs.cr3 = *(addr_t*)&(info->shdw_pg_state.shadow_cr3);
204           }
205
206           PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
207         } else {
208           PrintDebug("Old CR0=%x\n", *real_cr0);        
209           *real_cr0 = *new_cr0;
210           PrintDebug("New CR0=%x\n", *real_cr0);        
211         }
212
213         info->rip += index;
214
215       } else {
216         PrintDebug("Unsupported Instruction\n");
217         // unsupported instruction, UD the guest
218         return -1;
219       }
220
221     } 
222     break;
223  
224   case PROTECTED: 
225     {
226
227       int index = 0;
228       int ret;
229
230       PrintDebug("Protected %s Mode write to CR0 at guest %s linear rip 0x%x\n", 
231                  info->mem_mode == VIRTUAL_MEM ? "Paged" : "",
232                  info->mem_mode == VIRTUAL_MEM ? "virtual" : "",
233                  get_addr_linear(info, info->rip, &(info->segments.cs)));
234
235       // OK, now we will read the instruction
236       // The only difference between PROTECTED and PROTECTED_PG is whether we read
237       // from guest_pa or guest_va
238       if (info->mem_mode == PHYSICAL_MEM) { 
239         // The real rip address is actually a combination of the rip + CS base 
240         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
241       } else { 
242         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
243       }
244         
245
246       if (ret != 15) {
247         // I think we should inject a GPF into the guest
248         PrintDebug("Could not read instruction (ret=%d)\n", ret);
249         return -1;
250       }
251
252
253       while (is_prefix_byte(instr[index])) {
254         switch(instr[index]) {
255         case PREFIX_CS_OVERRIDE:
256         case PREFIX_SS_OVERRIDE:
257         case PREFIX_DS_OVERRIDE:
258         case PREFIX_ES_OVERRIDE:
259         case PREFIX_FS_OVERRIDE:
260         case PREFIX_GS_OVERRIDE:
261           PrintDebug("Segment Override!!\n");
262           return -1;
263           break;
264         default:
265           break;
266         }
267         index++; 
268       }
269
270       /*
271         while (is_prefix_byte(instr[index])) {
272         index++; 
273         }
274       */
275
276       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
277
278       struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
279
280       if ((instr[index] == cr_access_byte) && 
281           (instr[index + 1] == mov_to_cr_byte)) {
282
283         // MOV to CR0
284     
285         addr_t first_operand;
286         addr_t second_operand;
287         struct cr0_32 *new_cr0;
288         operand_type_t addr_type;
289
290         index += 2;
291  
292         PrintDebug("MovToCR0 instr:\n");
293         PrintTraceMemDump(instr, 15);
294         PrintDebug("EAX=%x\n", *(uint_t*)&(info->vm_regs.rax));
295
296         addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
297
298         if (addr_type != REG_OPERAND) {
299           PrintDebug("Non-register operand in write to CR0\n");
300           return -1;
301         }
302
303         new_cr0 = (struct cr0_32 *)first_operand;
304
305         PrintDebug("first operand=%x\n", *(uint_t *)first_operand);
306
307         if (info->shdw_pg_mode == SHADOW_PAGING) {
308           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
309
310           if (new_cr0->pg == 1){
311             // This should be new_cr0->pg && !(old_cr->pg), right?
312             // and then a case for turning paging off?
313
314             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
315
316             info->mem_mode = VIRTUAL_MEM;
317           
318             *shadow_cr0 = *new_cr0;
319             *real_cr0 = *new_cr0;
320             shadow_cr0->et = 1;
321             real_cr0->et = 1;
322
323             //
324             // Activate Shadow Paging
325             //
326             PrintDebug("Turning on paging in the guest\n");
327
328             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
329           
330
331           } else if (new_cr0->pe == 0) {
332             info->cpu_mode = REAL;
333             info->mem_mode = PHYSICAL_MEM;
334             PrintDebug("Entering Real Mode\n");
335
336             PrintV3CtrlRegs(info);
337             // reinstate the identity mapped paged tables
338             // But keep the shadow tables around to handle TLB issues.... UGH...
339             //info->shdw_pg_state.shadow_cr3 &= 0x00000fff;
340             //info->shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(info) & ~0xfff);
341
342             //info->ctrl_regs.cr3 = info->shdw_pg_state.shadow_cr3;
343             info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
344
345             *shadow_cr0 = *new_cr0;
346             *real_cr0 = *new_cr0;
347             real_cr0->pg = 1;
348             shadow_cr0->et = 1;
349             real_cr0->et = 1;
350
351             PrintV3CtrlRegs(info);
352
353           }
354
355
356         } else {
357           if (new_cr0->pg == 1) {
358             info->mem_mode = VIRTUAL_MEM;
359           } else if (new_cr0->pg == 0) {
360             info->cpu_mode = REAL;
361             info->mem_mode = PHYSICAL_MEM;
362           }
363
364           *real_cr0 = *new_cr0;
365         }
366
367         info->rip += index;
368       } else if ((instr[index] == cr_access_byte) &&
369                  (instr[index + 1] == lmsw_byte) &&
370                  (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
371         addr_t first_operand;
372         addr_t second_operand;
373         struct cr0_real *real_cr0;
374         struct cr0_real *new_cr0;
375         operand_type_t addr_type;
376         char new_cr0_val = 0;
377
378         index += 2;
379
380         real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
381
382         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
383
384         if (addr_type == REG_OPERAND) {
385           new_cr0 = (struct cr0_real *)first_operand;
386         } else if (addr_type == MEM_OPERAND) {
387           addr_t host_addr;
388           // check segment descriptors....
389
390           /* TODO, TODO, TODO: Lookup segment overrides */
391           struct v3_segment *lmsw_segment = &(info->segments.ds);
392
393           if (info->mem_mode == PHYSICAL_MEM) {
394             if (guest_pa_to_host_va(info, get_addr_linear(info, first_operand, lmsw_segment), &host_addr) == -1) {
395               return -1;
396             }
397           } else {
398             if (guest_va_to_host_va(info, get_addr_linear(info, first_operand, lmsw_segment), &host_addr) == -1) {
399               return -1;
400             }
401           }
402
403           new_cr0 = (struct cr0_real *)host_addr;
404         } else {
405           return -1;
406         }
407
408         
409         if (new_cr0->pe == 0) {
410           // According to the intel manual this it is illegal to use 
411           // lmsw to turn _off_ Protected mode
412           PrintDebug("Cannot switch to real mode with LMSW, unclear what to do\n");
413           return -1;
414         }
415
416         new_cr0_val = (*(char *)(new_cr0)) & 0x0f;
417
418
419         if (info->shdw_pg_mode == SHADOW_PAGING) {
420           struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
421
422           PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
423           /* struct cr0_real is only 4 bits wide, 
424            * so we can overwrite the real_cr0 without worrying about the shadow fields
425            */
426           *(char*)real_cr0 &= 0xf0;
427           *(char*)real_cr0 |= new_cr0_val;
428         
429           *(char*)shadow_cr0 &= 0xf0;
430           *(char*)shadow_cr0 |= new_cr0_val;
431
432
433           PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
434         } else {
435           PrintDebug("Old CR0=%x\n", *real_cr0);        
436           // for now we just pass through....
437           *(char*)real_cr0 &= 0xf0;
438           *(char*)real_cr0 |= new_cr0_val;
439
440           PrintDebug("New CR0=%x\n", *real_cr0);
441         }
442
443         info->rip += index;
444
445
446       } else if ((instr[index] == 0x0f) &&
447                  (instr[index + 1] == 0x06)) { 
448         // CLTS instruction
449         PrintDebug("CLTS instruction - clearing TS flag of real and shadow CR0\n");
450         shadow_cr0->ts = 0;
451         real_cr0->ts = 0;
452         
453         index+=2;
454         
455         info->rip+=index;
456
457       } else {
458         PrintDebug("Unkown instruction: \n");
459         SerialMemDump(instr,15);
460         return -1;
461       }
462     }
463     break;
464     
465   case PROTECTED_PAE:
466     PrintDebug("Protected PAE Mode write to CR0 is UNIMPLEMENTED\n");
467     return -1;
468
469   case LONG:
470     PrintDebug("Protected Long Mode write to CR0 is UNIMPLEMENTED\n");
471     return -1;
472
473   default: 
474     {
475       PrintDebug("Unknown Mode write to CR0 (info->cpu_mode=0x%x\n)",info->cpu_mode);
476       return -1;
477     }
478     break;
479
480   }
481
482   return 0;
483 }
484
485
486 int handle_cr0_read(struct guest_info * info) {
487   char instr[15];
488
489   switch (info->cpu_mode) { 
490
491   case REAL: 
492     {
493
494       int index = 0;
495       int ret;
496
497       PrintDebug("Real Mode read from CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
498       PrintV3Segments(info);
499
500       // The real rip address is actually a combination of the rip + CS base 
501       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
502       if (ret != 15) {
503         // I think we should inject a GPF into the guest
504         PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
505         return -1;
506       }
507
508
509       while (is_prefix_byte(instr[index])) {
510         switch(instr[index]) {
511         case PREFIX_CS_OVERRIDE:
512         case PREFIX_SS_OVERRIDE:
513         case PREFIX_DS_OVERRIDE:
514         case PREFIX_ES_OVERRIDE:
515         case PREFIX_FS_OVERRIDE:
516         case PREFIX_GS_OVERRIDE:
517           PrintDebug("Segment Override!!\n");
518           return -1;
519           break;
520         default:
521           break;
522         }
523         index++; 
524       }
525
526       /*
527         while (is_prefix_byte(instr[index])) {
528         index++; 
529         }
530       */
531
532       if ((instr[index] == cr_access_byte) && 
533           (instr[index + 1] == smsw_byte) && 
534           (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
535
536         // SMSW (store machine status word)
537
538         addr_t first_operand;
539         addr_t second_operand;
540         struct cr0_real *cr0;
541         operand_type_t addr_type;
542         char cr0_val = 0;
543
544         index += 2;
545       
546         cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
547       
548       
549         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
550       
551         if (addr_type == MEM_OPERAND) {
552           addr_t host_addr;
553         
554           if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
555             // gpf the guest
556             PrintDebug("Could not convert guest physical address to host virtual address\n");
557             return -1;
558           }
559         
560           first_operand = host_addr;
561         } else {
562           // Register operand
563           // Should be ok??
564         }
565
566         cr0_val = *(char*)cr0 & 0x0f;
567
568         *(char *)first_operand &= 0xf0;
569         *(char *)first_operand |= cr0_val;
570
571         PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
572         info->rip += index;
573         PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
574         // success
575
576       } else if ((instr[index] == cr_access_byte) &&
577                  (instr[index+1] == mov_from_cr_byte)) {
578         /* Mov from CR0
579          * This can only take a 32 bit register argument in anything less than 64 bit mode.
580          */
581         addr_t first_operand;
582         addr_t second_operand;
583         operand_type_t addr_type;
584
585         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
586
587         index += 2;
588
589         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
590      
591         struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
592   
593         if (addr_type != REG_OPERAND) {
594           // invalid opcode to guest
595           PrintDebug("Invalid operand type in mov from CR0\n");
596           return -1;
597         }
598
599         if (info->shdw_pg_mode == SHADOW_PAGING) {
600           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
601         } else {
602           *virt_cr0 = *real_cr0;
603         }
604
605         info->rip += index;
606
607       } else {
608         PrintDebug("Unknown read instr from CR0\n");
609         return -1;
610       }
611
612     } 
613
614     break;
615
616   case PROTECTED:
617     {
618     
619       int index = 0;
620       int ret;
621
622       PrintDebug("Protected %s Mode read from CR0 at guest %s linear rip 0x%x\n", 
623                  info->mem_mode == VIRTUAL_MEM ? "Paged" : "",
624                  info->mem_mode == VIRTUAL_MEM ? "virtual" : "",
625                  get_addr_linear(info, info->rip, &(info->segments.cs)));
626
627       // We need to read the instruction, which is at CS:IP, but that 
628       // linear address is guest physical without PG and guest virtual with PG
629       if (info->cpu_mode == PHYSICAL_MEM) { 
630         // The real rip address is actually a combination of the rip + CS base 
631         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
632       } else { 
633         // The real rip address is actually a combination of the rip + CS base 
634         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
635       }
636
637
638       PrintDebug("Instr (15 bytes) at %x:\n", instr);
639       PrintTraceMemDump((char*)instr, 15);
640
641       if (ret != 15) {
642         // I think we should inject a GPF into the guest
643         PrintDebug("Could not read Protected %s mode instruction (ret=%d)\n", 
644                    info->cpu_mode == VIRTUAL_MEM ? "Paged" : "", ret);
645         return -1;
646       }
647
648
649       while (is_prefix_byte(instr[index])) {
650         switch(instr[index]) {
651         case PREFIX_CS_OVERRIDE:
652         case PREFIX_SS_OVERRIDE:
653         case PREFIX_DS_OVERRIDE:
654         case PREFIX_ES_OVERRIDE:
655         case PREFIX_FS_OVERRIDE:
656         case PREFIX_GS_OVERRIDE:
657           PrintDebug("Segment Override!!\n");
658           return -1;
659           break;
660         default:
661           break;
662         }
663         index++; 
664       }
665
666
667       /*
668         while (is_prefix_byte(instr[index])) {
669         index++; 
670         }
671       */
672
673       if ((instr[index] == cr_access_byte) &&
674           (instr[index+1] == mov_from_cr_byte)) {
675         
676         // MOV from CR0 to register
677
678         addr_t first_operand;
679         addr_t second_operand;
680         operand_type_t addr_type;
681         struct cr0_32 * virt_cr0;
682         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
683
684         index += 2;
685
686         addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
687
688         if (addr_type != REG_OPERAND) {
689           PrintDebug("Invalid operand type in mov from CR0\n");
690           return -1;
691         }
692       
693         virt_cr0 = (struct cr0_32 *)first_operand;
694
695         if (info->shdw_pg_mode == SHADOW_PAGING) {
696           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
697           
698           if (info->mem_mode == PHYSICAL_MEM) {
699             virt_cr0->pg = 0; // clear the pg bit because guest doesn't think it's on
700           }
701           
702         } else {
703           *virt_cr0 = *real_cr0;
704         }
705
706           PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
707           PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
708       
709         info->rip += index;
710
711       } else { 
712         PrintDebug("Unknown read instruction from CR0\n");
713         return -1;
714       }
715     }
716     break;
717
718   case PROTECTED_PAE:
719     PrintDebug("Protected PAE Mode read to CR0 is UNIMPLEMENTED\n");
720     return -1;
721
722   case LONG:
723     PrintDebug("Protected Long Mode read to CR0 is UNIMPLEMENTED\n");
724     return -1;
725
726
727   default:
728     {
729       PrintDebug("Unknown Mode read from CR0 (info->cpu_mode=0x%x)\n",info->cpu_mode);
730       return -1;
731     }
732     break;
733   }
734
735
736   return 0;
737 }
738
739
740
741
742 int handle_cr3_write(struct guest_info * info) {
743   if (info->cpu_mode == REAL) {
744     // WHAT THE HELL DOES THIS EVEN MEAN?????
745
746     int index = 0;
747     int ret;
748     char instr[15];
749
750     PrintDebug("Real Mode Write to CR3??? What the fuck???\n");
751     // We need to read the instruction, which is at CS:IP, but that 
752     // linear address is guest physical without PG and guest virtual with PG
753
754     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
755
756     if (ret != 15) {
757       PrintDebug("Could not read instruction (ret=%d)\n", ret);
758       return -1;
759     }
760
761     while (is_prefix_byte(instr[index])) {
762       switch(instr[index]) {
763       case PREFIX_CS_OVERRIDE:
764       case PREFIX_SS_OVERRIDE:
765       case PREFIX_DS_OVERRIDE:
766       case PREFIX_ES_OVERRIDE:
767       case PREFIX_FS_OVERRIDE:
768       case PREFIX_GS_OVERRIDE:
769         PrintDebug("Segment Override!!\n");
770         return -1;
771         break;
772       default:
773         break;
774       }
775       index++; 
776     }
777     
778
779     if ((instr[index] == cr_access_byte) && 
780         (instr[index + 1] == mov_to_cr_byte)) {
781
782       addr_t first_operand;
783       addr_t second_operand;
784       struct cr3_32 * new_cr3;
785       //      struct cr3_32 * real_cr3;
786       operand_type_t addr_type;
787
788       index += 2;
789
790       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
791
792       if (addr_type != REG_OPERAND) {
793         /* Mov to CR3 can only be a 32 bit register */
794         return -1;
795       }
796
797       new_cr3 = (struct cr3_32 *)first_operand;
798
799       if (info->shdw_pg_mode == SHADOW_PAGING) {
800         addr_t shadow_pt;
801         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
802         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
803
804         /*
805
806           if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) {
807             PrintDebug("Shadow Page Table\n");
808             PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
809           }
810         */
811
812         /* Delete the current Page Tables */
813         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
814
815         PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
816                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
817
818
819         *guest_cr3 = *new_cr3;
820
821
822
823         // Something like this
824         shadow_pt =  create_new_shadow_pt32(info);
825         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
826
827         /* Copy Various flags */
828         *shadow_cr3 = *new_cr3;
829
830         /*
831         {
832           addr_t tmp_addr;
833           guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr);
834           PrintDebug("Guest PD\n");
835           PrintPD32((pde32_t *)tmp_addr);
836
837         }
838         */
839
840         
841         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
842
843         PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
844                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
845
846
847
848
849       }
850       info->rip += index;
851
852     } else {
853       PrintDebug("Unknown Instruction\n");
854       SerialMemDump(instr,15);
855       return -1;
856     }
857
858
859
860   } else if (info->cpu_mode == PROTECTED) {
861     int index = 0;
862     int ret;
863     char instr[15];
864
865     PrintDebug("Protected %s mode write to CR3 at %s 0x%x\n",
866                info->cpu_mode==PROTECTED ? "" : "Paged", 
867                info->cpu_mode==PROTECTED ? "guest physical" : "guest virtual",
868                get_addr_linear(info,info->rip,&(info->segments.cs)));
869
870     // We need to read the instruction, which is at CS:IP, but that 
871     // linear address is guest physical without PG and guest virtual with PG
872     if (info->mem_mode == PHYSICAL_MEM) { 
873       // The real rip address is actually a combination of the rip + CS base 
874       PrintDebug("Writing Guest CR3 Write (Physical Address)\n");
875       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
876     } else { 
877       PrintDebug("Writing Guest CR3 Write (Virtual Address)\n");
878       // The real rip address is actually a combination of the rip + CS base 
879       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
880     }
881
882     if (ret != 15) {
883       PrintDebug("Could not read instruction (ret=%d)\n", ret);
884       return -1;
885     }
886
887     while (is_prefix_byte(instr[index])) {
888       switch(instr[index]) {
889       case PREFIX_CS_OVERRIDE:
890       case PREFIX_SS_OVERRIDE:
891       case PREFIX_DS_OVERRIDE:
892       case PREFIX_ES_OVERRIDE:
893       case PREFIX_FS_OVERRIDE:
894       case PREFIX_GS_OVERRIDE:
895         PrintDebug("Segment Override!!\n");
896         return -1;
897         break;
898       default:
899         break;
900       }
901       index++; 
902     }
903     
904     /*    
905           while (is_prefix_byte(instr[index])) {
906           index++;
907           }
908     */
909
910     if ((instr[index] == cr_access_byte) && 
911         (instr[index + 1] == mov_to_cr_byte)) {
912
913       addr_t first_operand;
914       addr_t second_operand;
915       struct cr3_32 * new_cr3;
916       //      struct cr3_32 * real_cr3;
917       operand_type_t addr_type;
918
919       index += 2;
920
921       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
922
923       if (addr_type != REG_OPERAND) {
924         /* Mov to CR3 can only be a 32 bit register */
925         return -1;
926       }
927
928       new_cr3 = (struct cr3_32 *)first_operand;
929
930       if (info->shdw_pg_mode == SHADOW_PAGING) {
931         addr_t shadow_pt;
932         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
933         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
934
935
936         /*
937           if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) {
938             PrintDebug("Shadow Page Table\n");
939             PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
940           }
941         */
942
943         /* Delete the current Page Tables */
944         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
945
946         PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
947                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
948
949
950         *guest_cr3 = *new_cr3;
951
952
953
954         // Something like this
955         shadow_pt =  create_new_shadow_pt32(info);
956         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
957
958         /* Copy Various flags */
959         *shadow_cr3 = *new_cr3;
960
961         /*
962         {
963           addr_t tmp_addr;
964           guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr);
965           PrintDebug("Guest PD\n");
966           PrintPD32((pde32_t *)tmp_addr);
967
968         }
969         */
970
971         
972         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
973
974         PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
975                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
976
977
978
979         if (info->mem_mode == VIRTUAL_MEM) {
980           // If we aren't in paged mode then we have to preserve the identity mapped CR3
981           info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
982         }
983       }
984
985       info->rip += index;
986
987     } else {
988       PrintDebug("Unknown Instruction\n");
989       SerialMemDump(instr,15);
990       return -1;
991     }
992   } else {
993     PrintDebug("Invalid operating Mode (0x%x)\n", info->cpu_mode);
994     return -1;
995   }
996
997   return 0;
998 }
999
1000
1001
1002
1003 int handle_cr3_read(struct guest_info * info) {
1004
1005   if (info->cpu_mode == REAL) {
1006     char instr[15];
1007     int ret;
1008     int index = 0;
1009     addr_t linear_addr = 0;
1010
1011     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
1012
1013     
1014     PrintDebug("RIP Linear: %x\n", linear_addr);
1015     PrintV3Segments(info);
1016     
1017     ret = read_guest_pa_memory(info, linear_addr, 15, instr);
1018
1019     if (ret != 15) {
1020       PrintDebug("Could not read instruction (ret=%d)\n", ret);
1021       return -1;
1022     }
1023     
1024     while (is_prefix_byte(instr[index])) {
1025       switch(instr[index]) {
1026       case PREFIX_CS_OVERRIDE:
1027       case PREFIX_SS_OVERRIDE:
1028       case PREFIX_DS_OVERRIDE:
1029       case PREFIX_ES_OVERRIDE:
1030       case PREFIX_FS_OVERRIDE:
1031       case PREFIX_GS_OVERRIDE:
1032         PrintDebug("Segment Override!!\n");
1033         return -1;
1034         break;
1035       default:
1036         break;
1037       }
1038       index++; 
1039     }
1040
1041
1042     if ((instr[index] == cr_access_byte) && 
1043         (instr[index + 1] == mov_from_cr_byte)) {
1044       addr_t first_operand;
1045       addr_t second_operand;
1046       struct cr3_32 * virt_cr3;
1047       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
1048       operand_type_t addr_type;
1049
1050       index += 2;
1051
1052       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
1053
1054       if (addr_type != REG_OPERAND) {
1055         /* Mov to CR3 can only be a 32 bit register */
1056         return -1;
1057       }
1058
1059       virt_cr3 = (struct cr3_32 *)first_operand;
1060
1061       if (info->shdw_pg_mode == SHADOW_PAGING) {
1062         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
1063       } else {
1064         *virt_cr3 = *real_cr3;
1065       }
1066       
1067       info->rip += index;
1068     } else {
1069       PrintDebug("Unknown Instruction\n");
1070       SerialMemDump(instr,15);
1071       return -1;
1072     }
1073
1074
1075     return 0;
1076   } else if (info->cpu_mode == PROTECTED) {
1077
1078     int index = 0;
1079     int ret;
1080     char instr[15];
1081
1082    
1083     // We need to read the instruction, which is at CS:IP, but that 
1084     // linear address is guest physical without PG and guest virtual with PG
1085     if (info->cpu_mode == PHYSICAL_MEM) { 
1086       // The real rip address is actually a combination of the rip + CS base 
1087       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
1088     } else { 
1089       // The real rip address is actually a combination of the rip + CS base 
1090       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
1091     }
1092
1093     if (ret != 15) {
1094       PrintDebug("Could not read instruction (ret=%d)\n", ret);
1095       return -1;
1096     }
1097     
1098     while (is_prefix_byte(instr[index])) {
1099       switch(instr[index]) {
1100       case PREFIX_CS_OVERRIDE:
1101       case PREFIX_SS_OVERRIDE:
1102       case PREFIX_DS_OVERRIDE:
1103       case PREFIX_ES_OVERRIDE:
1104       case PREFIX_FS_OVERRIDE:
1105       case PREFIX_GS_OVERRIDE:
1106         PrintDebug("Segment Override!!\n");
1107         return -1;
1108         break;
1109       default:
1110         break;
1111       }
1112       index++; 
1113     }
1114
1115     /*
1116       while (is_prefix_byte(instr[index])) {
1117       index++;
1118       }
1119     */
1120
1121     if ((instr[index] == cr_access_byte) && 
1122         (instr[index + 1] == mov_from_cr_byte)) {
1123       addr_t first_operand;
1124       addr_t second_operand;
1125       struct cr3_32 * virt_cr3;
1126       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
1127       operand_type_t addr_type;
1128
1129       index += 2;
1130
1131       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
1132
1133       if (addr_type != REG_OPERAND) {
1134         /* Mov to CR3 can only be a 32 bit register */
1135         return -1;
1136       }
1137
1138       virt_cr3 = (struct cr3_32 *)first_operand;
1139
1140       if (info->shdw_pg_mode == SHADOW_PAGING) {
1141         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
1142       } else {
1143         *virt_cr3 = *real_cr3;
1144       }
1145       
1146       info->rip += index;
1147     } else {
1148       PrintDebug("Unknown Instruction\n");
1149       SerialMemDump(instr,15);
1150       return -1;
1151     }
1152   } else {
1153     PrintDebug("Invalid operating Mode (0x%x), control registers follow\n", info->cpu_mode);
1154     PrintV3CtrlRegs(info);
1155     return -1;
1156   }
1157
1158   return 0;
1159 }