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.


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