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.


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