Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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