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.


changed debug output to be more granular
[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         /*
293           PrintDebug("MovToCR0 instr:\n");
294           PrintTraceMemDump(instr, 15);
295           PrintDebug("EAX=%x\n", *(uint_t*)&(info->vm_regs.rax));
296         */
297         addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
298
299         if (addr_type != REG_OPERAND) {
300           PrintDebug("Non-register operand in write to CR0\n");
301           return -1;
302         }
303
304         new_cr0 = (struct cr0_32 *)first_operand;
305
306         //PrintDebug("first operand=%x\n", *(uint_t *)first_operand);
307
308         if (info->shdw_pg_mode == SHADOW_PAGING) {
309           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
310
311           if (new_cr0->pg == 1){
312             // This should be new_cr0->pg && !(old_cr->pg), right?
313             // and then a case for turning paging off?
314
315             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
316
317             info->mem_mode = VIRTUAL_MEM;
318           
319             *shadow_cr0 = *new_cr0;
320             *real_cr0 = *new_cr0;
321             shadow_cr0->et = 1;
322             real_cr0->et = 1;
323
324             //
325             // Activate Shadow Paging
326             //
327             PrintDebug("Turning on paging in the guest\n");
328
329             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
330           
331
332           } else if (new_cr0->pe == 0) {
333             info->cpu_mode = REAL;
334             info->mem_mode = PHYSICAL_MEM;
335             PrintDebug("Entering Real Mode\n");
336
337             //PrintV3CtrlRegs(info);
338             // reinstate the identity mapped paged tables
339             // But keep the shadow tables around to handle TLB issues.... UGH...
340             //info->shdw_pg_state.shadow_cr3 &= 0x00000fff;
341             //info->shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(info) & ~0xfff);
342
343             //info->ctrl_regs.cr3 = info->shdw_pg_state.shadow_cr3;
344             info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
345
346             *shadow_cr0 = *new_cr0;
347             *real_cr0 = *new_cr0;
348             real_cr0->pg = 1;
349             shadow_cr0->et = 1;
350             real_cr0->et = 1;
351
352             //PrintV3CtrlRegs(info);
353
354           }
355
356
357         } else {
358           if (new_cr0->pg == 1) {
359             info->mem_mode = VIRTUAL_MEM;
360           } else if (new_cr0->pg == 0) {
361             info->cpu_mode = REAL;
362             info->mem_mode = PHYSICAL_MEM;
363           }
364
365           *real_cr0 = *new_cr0;
366         }
367
368         info->rip += index;
369       } else if ((instr[index] == cr_access_byte) &&
370                  (instr[index + 1] == lmsw_byte) &&
371                  (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
372         addr_t first_operand;
373         addr_t second_operand;
374         struct cr0_real *real_cr0;
375         struct cr0_real *new_cr0;
376         operand_type_t addr_type;
377         char new_cr0_val = 0;
378
379         index += 2;
380
381         real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
382
383         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
384
385         if (addr_type == REG_OPERAND) {
386           new_cr0 = (struct cr0_real *)first_operand;
387         } else if (addr_type == MEM_OPERAND) {
388           addr_t host_addr;
389           // check segment descriptors....
390
391           /* TODO, TODO, TODO: Lookup segment overrides */
392           struct v3_segment *lmsw_segment = &(info->segments.ds);
393
394           if (info->mem_mode == PHYSICAL_MEM) {
395             if (guest_pa_to_host_va(info, get_addr_linear(info, first_operand, lmsw_segment), &host_addr) == -1) {
396               return -1;
397             }
398           } else {
399             if (guest_va_to_host_va(info, get_addr_linear(info, first_operand, lmsw_segment), &host_addr) == -1) {
400               return -1;
401             }
402           }
403
404           new_cr0 = (struct cr0_real *)host_addr;
405         } else {
406           return -1;
407         }
408
409         
410         if (new_cr0->pe == 0) {
411           // According to the intel manual this it is illegal to use 
412           // lmsw to turn _off_ Protected mode
413           PrintDebug("Cannot switch to real mode with LMSW, unclear what to do\n");
414           return -1;
415         }
416
417         new_cr0_val = (*(char *)(new_cr0)) & 0x0f;
418
419
420         if (info->shdw_pg_mode == SHADOW_PAGING) {
421           struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
422
423           PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
424           /* struct cr0_real is only 4 bits wide, 
425            * so we can overwrite the real_cr0 without worrying about the shadow fields
426            */
427           *(char*)real_cr0 &= 0xf0;
428           *(char*)real_cr0 |= new_cr0_val;
429         
430           *(char*)shadow_cr0 &= 0xf0;
431           *(char*)shadow_cr0 |= new_cr0_val;
432
433
434           PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
435         } else {
436           PrintDebug("Old CR0=%x\n", *real_cr0);        
437           // for now we just pass through....
438           *(char*)real_cr0 &= 0xf0;
439           *(char*)real_cr0 |= new_cr0_val;
440
441           PrintDebug("New CR0=%x\n", *real_cr0);
442         }
443
444         info->rip += index;
445
446
447       } else if ((instr[index] == 0x0f) &&
448                  (instr[index + 1] == 0x06)) { 
449         // CLTS instruction
450         PrintDebug("CLTS instruction - clearing TS flag of real and shadow CR0\n");
451         shadow_cr0->ts = 0;
452         real_cr0->ts = 0;
453         
454         index+=2;
455         
456         info->rip+=index;
457
458       } else {
459         PrintDebug("Unkown instruction: \n");
460         SerialMemDump(instr,15);
461         return -1;
462       }
463     }
464     break;
465     
466   case PROTECTED_PAE:
467     PrintDebug("Protected PAE Mode write to CR0 is UNIMPLEMENTED\n");
468     return -1;
469
470   case LONG:
471     PrintDebug("Protected Long Mode write to CR0 is UNIMPLEMENTED\n");
472     return -1;
473
474   default: 
475     {
476       PrintDebug("Unknown Mode write to CR0 (info->cpu_mode=0x%x\n)",info->cpu_mode);
477       return -1;
478     }
479     break;
480
481   }
482
483   return 0;
484 }
485
486
487 int handle_cr0_read(struct guest_info * info) {
488   char instr[15];
489
490   switch (info->cpu_mode) { 
491
492   case REAL: 
493     {
494
495       int index = 0;
496       int ret;
497
498       PrintDebug("Real Mode read from CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
499       //PrintV3Segments(info);
500
501       // The real rip address is actually a combination of the rip + CS base 
502       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
503       if (ret != 15) {
504         // I think we should inject a GPF into the guest
505         PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
506         return -1;
507       }
508
509
510       while (is_prefix_byte(instr[index])) {
511         switch(instr[index]) {
512         case PREFIX_CS_OVERRIDE:
513         case PREFIX_SS_OVERRIDE:
514         case PREFIX_DS_OVERRIDE:
515         case PREFIX_ES_OVERRIDE:
516         case PREFIX_FS_OVERRIDE:
517         case PREFIX_GS_OVERRIDE:
518           PrintDebug("Segment Override!!\n");
519           return -1;
520           break;
521         default:
522           break;
523         }
524         index++; 
525       }
526
527       /*
528         while (is_prefix_byte(instr[index])) {
529         index++; 
530         }
531       */
532
533       if ((instr[index] == cr_access_byte) && 
534           (instr[index + 1] == smsw_byte) && 
535           (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
536
537         // SMSW (store machine status word)
538
539         addr_t first_operand;
540         addr_t second_operand;
541         struct cr0_real *cr0;
542         operand_type_t addr_type;
543         char cr0_val = 0;
544
545         index += 2;
546       
547         cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
548       
549       
550         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
551       
552         if (addr_type == MEM_OPERAND) {
553           addr_t host_addr;
554         
555           if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
556             // gpf the guest
557             PrintDebug("Could not convert guest physical address to host virtual address\n");
558             return -1;
559           }
560         
561           first_operand = host_addr;
562         } else {
563           // Register operand
564           // Should be ok??
565         }
566
567         cr0_val = *(char*)cr0 & 0x0f;
568
569         *(char *)first_operand &= 0xf0;
570         *(char *)first_operand |= cr0_val;
571
572         PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
573         info->rip += index;
574         PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
575         // success
576
577       } else if ((instr[index] == cr_access_byte) &&
578                  (instr[index+1] == mov_from_cr_byte)) {
579         /* Mov from CR0
580          * This can only take a 32 bit register argument in anything less than 64 bit mode.
581          */
582         addr_t first_operand;
583         addr_t second_operand;
584         operand_type_t addr_type;
585
586         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
587
588         index += 2;
589
590         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
591      
592         struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
593   
594         if (addr_type != REG_OPERAND) {
595           // invalid opcode to guest
596           PrintDebug("Invalid operand type in mov from CR0\n");
597           return -1;
598         }
599
600         if (info->shdw_pg_mode == SHADOW_PAGING) {
601           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
602         } else {
603           *virt_cr0 = *real_cr0;
604         }
605
606         info->rip += index;
607
608       } else {
609         PrintDebug("Unknown read instr from CR0\n");
610         return -1;
611       }
612
613     } 
614
615     break;
616
617   case PROTECTED:
618     {
619     
620       int index = 0;
621       int ret;
622
623       PrintDebug("Protected %s Mode read from CR0 at guest %s linear rip 0x%x\n", 
624                  info->mem_mode == VIRTUAL_MEM ? "Paged" : "",
625                  info->mem_mode == VIRTUAL_MEM ? "virtual" : "",
626                  get_addr_linear(info, info->rip, &(info->segments.cs)));
627
628       // We need to read the instruction, which is at CS:IP, but that 
629       // linear address is guest physical without PG and guest virtual with PG
630       if (info->cpu_mode == PHYSICAL_MEM) { 
631         // The real rip address is actually a combination of the rip + CS base 
632         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
633       } else { 
634         // The real rip address is actually a combination of the rip + CS base 
635         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
636       }
637
638
639       /*
640         PrintDebug("Instr (15 bytes) at %x:\n", instr);
641         PrintTraceMemDump((char*)instr, 15);
642       */
643
644       if (ret != 15) {
645         // I think we should inject a GPF into the guest
646         PrintDebug("Could not read Protected %s mode instruction (ret=%d)\n", 
647                    info->cpu_mode == VIRTUAL_MEM ? "Paged" : "", ret);
648         return -1;
649       }
650
651
652       while (is_prefix_byte(instr[index])) {
653         switch(instr[index]) {
654         case PREFIX_CS_OVERRIDE:
655         case PREFIX_SS_OVERRIDE:
656         case PREFIX_DS_OVERRIDE:
657         case PREFIX_ES_OVERRIDE:
658         case PREFIX_FS_OVERRIDE:
659         case PREFIX_GS_OVERRIDE:
660           PrintDebug("Segment Override!!\n");
661           return -1;
662           break;
663         default:
664           break;
665         }
666         index++; 
667       }
668
669
670       /*
671         while (is_prefix_byte(instr[index])) {
672         index++; 
673         }
674       */
675
676       if ((instr[index] == cr_access_byte) &&
677           (instr[index+1] == mov_from_cr_byte)) {
678         
679         // MOV from CR0 to register
680
681         addr_t first_operand;
682         addr_t second_operand;
683         operand_type_t addr_type;
684         struct cr0_32 * virt_cr0;
685         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
686
687         index += 2;
688
689         addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
690
691         if (addr_type != REG_OPERAND) {
692           PrintDebug("Invalid operand type in mov from CR0\n");
693           return -1;
694         }
695       
696         virt_cr0 = (struct cr0_32 *)first_operand;
697
698         if (info->shdw_pg_mode == SHADOW_PAGING) {
699           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
700           
701           if (info->mem_mode == PHYSICAL_MEM) {
702             virt_cr0->pg = 0; // clear the pg bit because guest doesn't think it's on
703           }
704           
705         } else {
706           *virt_cr0 = *real_cr0;
707         }
708
709           PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
710           PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
711       
712         info->rip += index;
713
714       } else { 
715         PrintDebug("Unknown read instruction from CR0\n");
716         return -1;
717       }
718     }
719     break;
720
721   case PROTECTED_PAE:
722     PrintDebug("Protected PAE Mode read to CR0 is UNIMPLEMENTED\n");
723     return -1;
724
725   case LONG:
726     PrintDebug("Protected Long Mode read to CR0 is UNIMPLEMENTED\n");
727     return -1;
728
729
730   default:
731     {
732       PrintDebug("Unknown Mode read from CR0 (info->cpu_mode=0x%x)\n",info->cpu_mode);
733       return -1;
734     }
735     break;
736   }
737
738
739   return 0;
740 }
741
742
743
744
745 int handle_cr3_write(struct guest_info * info) {
746   if (info->cpu_mode == REAL) {
747     // WHAT THE HELL DOES THIS EVEN MEAN?????
748
749     int index = 0;
750     int ret;
751     char instr[15];
752
753     PrintDebug("Real Mode Write to CR3.\n");
754     // We need to read the instruction, which is at CS:IP, but that 
755     // linear address is guest physical without PG and guest virtual with PG
756
757     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
758
759     if (ret != 15) {
760       PrintDebug("Could not read instruction (ret=%d)\n", ret);
761       return -1;
762     }
763
764     while (is_prefix_byte(instr[index])) {
765       switch(instr[index]) {
766       case PREFIX_CS_OVERRIDE:
767       case PREFIX_SS_OVERRIDE:
768       case PREFIX_DS_OVERRIDE:
769       case PREFIX_ES_OVERRIDE:
770       case PREFIX_FS_OVERRIDE:
771       case PREFIX_GS_OVERRIDE:
772         PrintDebug("Segment Override!!\n");
773         return -1;
774         break;
775       default:
776         break;
777       }
778       index++; 
779     }
780     
781
782     if ((instr[index] == cr_access_byte) && 
783         (instr[index + 1] == mov_to_cr_byte)) {
784
785       addr_t first_operand;
786       addr_t second_operand;
787       struct cr3_32 * new_cr3;
788       //      struct cr3_32 * real_cr3;
789       operand_type_t addr_type;
790
791       index += 2;
792
793       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
794
795       if (addr_type != REG_OPERAND) {
796         /* Mov to CR3 can only be a 32 bit register */
797         return -1;
798       }
799
800       new_cr3 = (struct cr3_32 *)first_operand;
801
802       if (info->shdw_pg_mode == SHADOW_PAGING) {
803         addr_t shadow_pt;
804         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
805         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
806
807         /*
808
809           if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) {
810             PrintDebug("Shadow Page Table\n");
811             PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
812           }
813         */
814
815         /* Delete the current Page Tables */
816         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
817
818         PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
819                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
820
821
822         *guest_cr3 = *new_cr3;
823
824
825
826         // Something like this
827         shadow_pt =  create_new_shadow_pt32(info);
828         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
829
830         /* Copy Various flags */
831         *shadow_cr3 = *new_cr3;
832
833         /*
834         {
835           addr_t tmp_addr;
836           guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr);
837           PrintDebug("Guest PD\n");
838           PrintPD32((pde32_t *)tmp_addr);
839
840         }
841         */
842
843         
844         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
845
846         PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
847                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
848
849
850
851
852       }
853       info->rip += index;
854
855     } else {
856       PrintDebug("Unknown Instruction\n");
857       SerialMemDump(instr,15);
858       return -1;
859     }
860
861
862
863   } else if (info->cpu_mode == PROTECTED) {
864     int index = 0;
865     int ret;
866     char instr[15];
867
868     PrintDebug("Protected %s mode write to CR3 at %s 0x%x\n",
869                info->cpu_mode==PROTECTED ? "" : "Paged", 
870                info->cpu_mode==PROTECTED ? "guest physical" : "guest virtual",
871                get_addr_linear(info,info->rip,&(info->segments.cs)));
872
873     // We need to read the instruction, which is at CS:IP, but that 
874     // linear address is guest physical without PG and guest virtual with PG
875     if (info->mem_mode == PHYSICAL_MEM) { 
876       // The real rip address is actually a combination of the rip + CS base 
877       //PrintDebug("Writing Guest CR3 Write (Physical Address)\n");
878       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
879     } else { 
880       //PrintDebug("Writing Guest CR3 Write (Virtual Address)\n");
881       // The real rip address is actually a combination of the rip + CS base 
882       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
883     }
884
885     if (ret != 15) {
886       PrintDebug("Could not read instruction (ret=%d)\n", ret);
887       return -1;
888     }
889
890     while (is_prefix_byte(instr[index])) {
891       switch(instr[index]) {
892       case PREFIX_CS_OVERRIDE:
893       case PREFIX_SS_OVERRIDE:
894       case PREFIX_DS_OVERRIDE:
895       case PREFIX_ES_OVERRIDE:
896       case PREFIX_FS_OVERRIDE:
897       case PREFIX_GS_OVERRIDE:
898         PrintDebug("Segment Override!!\n");
899         return -1;
900         break;
901       default:
902         break;
903       }
904       index++; 
905     }
906     
907     /*    
908           while (is_prefix_byte(instr[index])) {
909           index++;
910           }
911     */
912
913     if ((instr[index] == cr_access_byte) && 
914         (instr[index + 1] == mov_to_cr_byte)) {
915
916       addr_t first_operand;
917       addr_t second_operand;
918       struct cr3_32 * new_cr3;
919       //      struct cr3_32 * real_cr3;
920       operand_type_t addr_type;
921
922       index += 2;
923
924       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
925
926       if (addr_type != REG_OPERAND) {
927         /* Mov to CR3 can only be a 32 bit register */
928         return -1;
929       }
930
931       new_cr3 = (struct cr3_32 *)first_operand;
932
933       if (info->shdw_pg_mode == SHADOW_PAGING) {
934         addr_t shadow_pt;
935         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
936         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
937
938
939         /*
940           if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) {
941             PrintDebug("Shadow Page Table\n");
942             PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
943           }
944         */
945
946         /* Delete the current Page Tables */
947         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
948
949         PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
950                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
951
952
953         *guest_cr3 = *new_cr3;
954
955
956
957         // Something like this
958         shadow_pt =  create_new_shadow_pt32(info);
959         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
960
961         /* Copy Various flags */
962         *shadow_cr3 = *new_cr3;
963
964         /*
965         {
966           addr_t tmp_addr;
967           guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr);
968           PrintDebug("Guest PD\n");
969           PrintPD32((pde32_t *)tmp_addr);
970
971         }
972         */
973
974         
975         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
976
977         PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
978                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
979
980
981
982         if (info->mem_mode == VIRTUAL_MEM) {
983           // If we aren't in paged mode then we have to preserve the identity mapped CR3
984           info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
985         }
986       }
987
988       info->rip += index;
989
990     } else {
991       PrintDebug("Unknown Instruction\n");
992       SerialMemDump(instr,15);
993       return -1;
994     }
995   } else {
996     PrintDebug("Invalid operating Mode (0x%x)\n", info->cpu_mode);
997     return -1;
998   }
999
1000   return 0;
1001 }
1002
1003
1004
1005
1006 int handle_cr3_read(struct guest_info * info) {
1007
1008   if (info->cpu_mode == REAL) {
1009     char instr[15];
1010     int ret;
1011     int index = 0;
1012     addr_t linear_addr = 0;
1013
1014     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
1015
1016     
1017     //PrintDebug("RIP Linear: %x\n", linear_addr);
1018     //PrintV3Segments(info);
1019     
1020     ret = read_guest_pa_memory(info, linear_addr, 15, instr);
1021
1022     if (ret != 15) {
1023       PrintDebug("Could not read instruction (ret=%d)\n", ret);
1024       return -1;
1025     }
1026     
1027     while (is_prefix_byte(instr[index])) {
1028       switch(instr[index]) {
1029       case PREFIX_CS_OVERRIDE:
1030       case PREFIX_SS_OVERRIDE:
1031       case PREFIX_DS_OVERRIDE:
1032       case PREFIX_ES_OVERRIDE:
1033       case PREFIX_FS_OVERRIDE:
1034       case PREFIX_GS_OVERRIDE:
1035         PrintDebug("Segment Override!!\n");
1036         return -1;
1037         break;
1038       default:
1039         break;
1040       }
1041       index++; 
1042     }
1043
1044
1045     if ((instr[index] == cr_access_byte) && 
1046         (instr[index + 1] == mov_from_cr_byte)) {
1047       addr_t first_operand;
1048       addr_t second_operand;
1049       struct cr3_32 * virt_cr3;
1050       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
1051       operand_type_t addr_type;
1052
1053       index += 2;
1054
1055       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
1056
1057       if (addr_type != REG_OPERAND) {
1058         /* Mov to CR3 can only be a 32 bit register */
1059         return -1;
1060       }
1061
1062       virt_cr3 = (struct cr3_32 *)first_operand;
1063
1064       if (info->shdw_pg_mode == SHADOW_PAGING) {
1065         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
1066       } else {
1067         *virt_cr3 = *real_cr3;
1068       }
1069       
1070       info->rip += index;
1071     } else {
1072       PrintDebug("Unknown Instruction\n");
1073       SerialMemDump(instr,15);
1074       return -1;
1075     }
1076
1077
1078     return 0;
1079   } else if (info->cpu_mode == PROTECTED) {
1080
1081     int index = 0;
1082     int ret;
1083     char instr[15];
1084
1085    
1086     // We need to read the instruction, which is at CS:IP, but that 
1087     // linear address is guest physical without PG and guest virtual with PG
1088     if (info->cpu_mode == PHYSICAL_MEM) { 
1089       // The real rip address is actually a combination of the rip + CS base 
1090       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
1091     } else { 
1092       // The real rip address is actually a combination of the rip + CS base 
1093       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
1094     }
1095
1096     if (ret != 15) {
1097       PrintDebug("Could not read instruction (ret=%d)\n", ret);
1098       return -1;
1099     }
1100     
1101     while (is_prefix_byte(instr[index])) {
1102       switch(instr[index]) {
1103       case PREFIX_CS_OVERRIDE:
1104       case PREFIX_SS_OVERRIDE:
1105       case PREFIX_DS_OVERRIDE:
1106       case PREFIX_ES_OVERRIDE:
1107       case PREFIX_FS_OVERRIDE:
1108       case PREFIX_GS_OVERRIDE:
1109         PrintDebug("Segment Override!!\n");
1110         return -1;
1111         break;
1112       default:
1113         break;
1114       }
1115       index++; 
1116     }
1117
1118     /*
1119       while (is_prefix_byte(instr[index])) {
1120       index++;
1121       }
1122     */
1123
1124     if ((instr[index] == cr_access_byte) && 
1125         (instr[index + 1] == mov_from_cr_byte)) {
1126       addr_t first_operand;
1127       addr_t second_operand;
1128       struct cr3_32 * virt_cr3;
1129       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
1130       operand_type_t addr_type;
1131
1132       index += 2;
1133
1134       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
1135
1136       if (addr_type != REG_OPERAND) {
1137         /* Mov to CR3 can only be a 32 bit register */
1138         return -1;
1139       }
1140
1141       virt_cr3 = (struct cr3_32 *)first_operand;
1142
1143       if (info->shdw_pg_mode == SHADOW_PAGING) {
1144         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
1145       } else {
1146         *virt_cr3 = *real_cr3;
1147       }
1148       
1149       info->rip += index;
1150     } else {
1151       PrintDebug("Unknown Instruction\n");
1152       SerialMemDump(instr,15);
1153       return -1;
1154     }
1155   } else {
1156     PrintDebug("Invalid operating Mode (0x%x), control registers follow\n", info->cpu_mode);
1157     PrintV3CtrlRegs(info);
1158     return -1;
1159   }
1160
1161   return 0;
1162 }