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.


ugg
Jack Lange [Mon, 14 Jul 2008 22:53:03 +0000 (22:53 +0000)]
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_decoder.h
palacios/src/palacios/svm.c
palacios/src/palacios/vmm_ctrl_regs.c
palacios/src/palacios/vmm_shadow_paging.c

index 6eb1cc9..b295bfc 100644 (file)
@@ -80,7 +80,7 @@ struct vm_ctrl_ops {
 
 
 typedef enum {SHADOW_PAGING, NESTED_PAGING} vmm_paging_mode_t;
-typedef enum {REAL, PROTECTED, PROTECTED_PAE, LONG} vm_cpu_mode_t;
+typedef enum {REAL, /*UNREAL,*/ PROTECTED, PROTECTED_PAE, LONG} vm_cpu_mode_t;
 typedef enum {PHYSICAL_MEM, VIRTUAL_MEM} vm_mem_mode_t;
 
 struct guest_info {
@@ -94,6 +94,7 @@ struct guest_info {
   
   vmm_paging_mode_t shdw_pg_mode;
   struct shadow_page_state shdw_pg_state;
+  addr_t direct_map_pt;
   // nested_paging_t nested_page_state;
 
 
index 130e1ae..9319da8 100644 (file)
@@ -165,8 +165,11 @@ static inline v3_reg_t get_gpr_mask(struct guest_info * info) {
 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
   switch (info->cpu_mode) {
   case REAL:
-    return addr + (seg->selector << 4);
-    break;
+    // It appears that the segment values are computed and cached in the vmcb structure 
+    // We Need to check this for Intel
+    /*   return addr + (seg->selector << 4);
+        break;*/
+
   case PROTECTED:
     return addr + seg->base;
     break;
index 1bd4241..8c650ff 100644 (file)
@@ -49,14 +49,14 @@ static vmcb_t * Allocate_VMCB() {
 
 
 
-static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
+static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) {
   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
   uint_t i;
 
 
-  guest_state->rsp = vm_info.vm_regs.rsp;
-  // guest_state->rip = vm_info.rip;
+  guest_state->rsp = vm_info->vm_regs.rsp;
+  // guest_state->rip = vm_info->rip;
   guest_state->rip = 0xfff0;
 
   guest_state->cpl = 0;
@@ -85,7 +85,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
   ctrl_area->exceptions.of = 1;
   ctrl_area->exceptions.nmi = 1;
 
-  vm_info.vm_regs.rdx = 0x00000f00;
+  vm_info->vm_regs.rdx = 0x00000f00;
 
   guest_state->cr0 = 0x60000010;
 
@@ -122,7 +122,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
   guest_state->dr6 = 0x00000000ffff0ff0LL;
   guest_state->dr7 = 0x0000000000000400LL;
 
-  if (vm_info.io_map.num_ports > 0) {
+  if (vm_info->io_map.num_ports > 0) {
     vmm_io_hook_t * iter;
     addr_t io_port_bitmap;
     
@@ -133,7 +133,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
 
     //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
 
-    FOREACH_IO_HOOK(vm_info.io_map, iter) {
+    FOREACH_IO_HOOK(vm_info->io_map, iter) {
       ushort_t port = iter->port;
       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
 
@@ -155,15 +155,16 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
   ctrl_area->instrs.INTR = 1;
 
 
-  if (vm_info.shdw_pg_mode == SHADOW_PAGING) {
+  if (vm_info->shdw_pg_mode == SHADOW_PAGING) {
     PrintDebug("Creating initial shadow page table\n");
-    vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
-    vm_info.shdw_pg_state.guest_cr0 = 0x0000000000000010LL;
+    vm_info->direct_map_pt = (addr_t)create_passthrough_pde32_pts(vm_info);
+    vm_info->shdw_pg_state.shadow_cr3 |= (vm_info->direct_map_pt & ~0xfff);
+    vm_info->shdw_pg_state.guest_cr0 = 0x0000000000000010LL;
     PrintDebug("Created\n");
 
-    guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3;
+    guest_state->cr3 = vm_info->shdw_pg_state.shadow_cr3;
 
-    //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low));
+    //PrintDebugPageTables((pde32_t*)(vm_info->shdw_pg_state.shadow_cr3.e_reg.low));
 
     ctrl_area->cr_reads.cr3 = 1;
     ctrl_area->cr_writes.cr3 = 1;
@@ -182,7 +183,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
 
     guest_state->cr0 |= 0x80000000;
 
-  } else if (vm_info.shdw_pg_mode == NESTED_PAGING) {
+  } else if (vm_info->shdw_pg_mode == NESTED_PAGING) {
     // Flush the TLB on entries/exits
     ctrl_area->TLB_CONTROL = 1;
 
@@ -192,7 +193,8 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
     PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
 
     // Set the Nested Page Table pointer
-    ctrl_area->N_CR3 = ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
+    vm_info->direct_map_pt = ((addr_t)create_passthrough_pde32_pts(vm_info) & ~0xfff);
+    ctrl_area->N_CR3 = vm_info->direct_map_pt;
 
     //   ctrl_area->N_CR3 = Get_CR3();
     // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
@@ -226,7 +228,7 @@ static int init_svm_guest(struct guest_info *info) {
 
 
   PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data);
-  Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), *info);
+  Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), info);
   
 
   //  info->rip = 0;
index cc42089..a059573 100644 (file)
@@ -29,6 +29,8 @@ int handle_cr0_write(struct guest_info * info) {
       
       PrintDebug("Real Mode write to CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
 
+      PrintV3Segments(&(info->segments));
+
       // The real rip address is actually a combination of the rip + CS base 
       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
       if (ret != 15) {
@@ -38,6 +40,19 @@ int handle_cr0_write(struct guest_info * info) {
       }
 
       while (is_prefix_byte(instr[index])) {
+       switch(instr[index]) {
+       case PREFIX_CS_OVERRIDE:
+       case PREFIX_SS_OVERRIDE:
+       case PREFIX_DS_OVERRIDE:
+       case PREFIX_ES_OVERRIDE:
+       case PREFIX_FS_OVERRIDE:
+       case PREFIX_GS_OVERRIDE:
+         PrintDebug("Segment Override!!\n");
+         return -1;
+         break;
+       default:
+         break;
+       }
        index++; 
       }
 
@@ -72,7 +87,7 @@ int handle_cr0_write(struct guest_info * info) {
 
          new_cr0 = (struct cr0_real *)host_addr;
        } else {
-         PrintDebug("Memory operand in real mode write to CR0 is UNIMPLEMENTED\n");
+
          // error... don't know what to do
          return -1;
        }
@@ -83,7 +98,7 @@ int handle_cr0_write(struct guest_info * info) {
          info->cpu_mode = REAL;
        }
       
-       new_cr0_val = *(char*)(new_cr0) & 0x0f;
+       new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
 
 
        if (info->shdw_pg_mode == SHADOW_PAGING) {
@@ -154,12 +169,22 @@ int handle_cr0_write(struct guest_info * info) {
        }
          
 
-       if (new_cr0->pg == 1) {
+
+       if ((new_cr0->pg == 1) && (new_cr0->pe == 1)) {
          PrintDebug("Paging is already turned on in switch to protected mode in CR0 write\n");
 
+         // Actually This appears to be Ok. 
+         // Why shouldn't windows be allowed to switch to real mode whenever it wants to modify its page tables?
+
+         info->mem_mode = VIRTUAL_MEM;
+
          // GPF the guest??
+         //  return -1;
+       } else if ((new_cr0->pg == 1) && (new_cr0->pe == 0)) {
+         PrintDebug("Will the madness Never End??\n");
          return -1;
        }
+       
 
        if (info->shdw_pg_mode == SHADOW_PAGING) {
          struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
@@ -172,6 +197,12 @@ int handle_cr0_write(struct guest_info * info) {
          *shadow_cr0 = *new_cr0;
          shadow_cr0->et = 1;
 
+         // Setup the page tables...???
+         if (info->mem_mode == VIRTUAL_MEM) {
+           // If we aren't in paged mode then we have to preserve the identity mapped CR3
+           info->ctrl_regs.cr3 = *(addr_t*)&(info->shdw_pg_state.shadow_cr3);
+         }
+
          PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
        } else {
          PrintDebug("Old CR0=%x\n", *real_cr0);        
@@ -218,10 +249,30 @@ int handle_cr0_write(struct guest_info * info) {
        return -1;
       }
 
+
       while (is_prefix_byte(instr[index])) {
+       switch(instr[index]) {
+       case PREFIX_CS_OVERRIDE:
+       case PREFIX_SS_OVERRIDE:
+       case PREFIX_DS_OVERRIDE:
+       case PREFIX_ES_OVERRIDE:
+       case PREFIX_FS_OVERRIDE:
+       case PREFIX_GS_OVERRIDE:
+         PrintDebug("Segment Override!!\n");
+         return -1;
+         break;
+       default:
+         break;
+       }
        index++; 
       }
 
+      /*
+       while (is_prefix_byte(instr[index])) {
+       index++; 
+       }
+      */
+
       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
 
       struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
@@ -289,8 +340,7 @@ int handle_cr0_write(struct guest_info * info) {
            //info->shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(info) & ~0xfff);
 
            //info->ctrl_regs.cr3 = info->shdw_pg_state.shadow_cr3;
-           info->ctrl_regs.cr3 = ((addr_t)create_passthrough_pde32_pts(info) & ~0xfff);
-
+           info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
 
            *shadow_cr0 = *new_cr0;
            *real_cr0 = *new_cr0;
@@ -298,6 +348,8 @@ int handle_cr0_write(struct guest_info * info) {
            shadow_cr0->et = 1;
            real_cr0->et = 1;
 
+           PrintV3CtrlRegs(&(info->ctrl_regs));
+
          }
 
 
@@ -306,6 +358,83 @@ int handle_cr0_write(struct guest_info * info) {
        }
 
        info->rip += index;
+      } else if ((instr[index] == cr_access_byte) &&
+                (instr[index + 1] == lmsw_byte) &&
+                (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
+       addr_t first_operand;
+       addr_t second_operand;
+       struct cr0_real *real_cr0;
+       struct cr0_real *new_cr0;
+       operand_type_t addr_type;
+       char new_cr0_val = 0;
+
+       index += 2;
+
+       real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
+
+       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
+
+       if (addr_type == REG_OPERAND) {
+         new_cr0 = (struct cr0_real *)first_operand;
+       } else if (addr_type == MEM_OPERAND) {
+         addr_t host_addr;
+         // check segment descriptors....
+
+         /* TODO, TODO, TODO: Lookup segment overrides */
+         struct v3_segment *lmsw_segment = &(info->segments.ds);
+
+         if (info->mem_mode == PHYSICAL_MEM) {
+           if (guest_pa_to_host_va(info, get_addr_linear(info, first_operand, lmsw_segment), &host_addr) == -1) {
+             return -1;
+           }
+         } else {
+           if (guest_va_to_host_va(info, get_addr_linear(info, first_operand, lmsw_segment), &host_addr) == -1) {
+             return -1;
+           }
+         }
+
+         new_cr0 = (struct cr0_real *)host_addr;
+       } else {
+         return -1;
+       }
+
+       
+       if (new_cr0->pe == 0) {
+         // According to the intel manual this it is illegal to use 
+         // lmsw to turn _off_ Protected mode
+         PrintDebug("Cannot switch to real mode with LMSW, unclear what to do\n");
+         return -1;
+       }
+
+       new_cr0_val = (*(char *)(new_cr0)) & 0x0f;
+
+
+       if (info->shdw_pg_mode == SHADOW_PAGING) {
+         struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
+
+         PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
+         /* struct cr0_real is only 4 bits wide, 
+          * so we can overwrite the real_cr0 without worrying about the shadow fields
+          */
+         *(char*)real_cr0 &= 0xf0;
+         *(char*)real_cr0 |= new_cr0_val;
+       
+         *(char*)shadow_cr0 &= 0xf0;
+         *(char*)shadow_cr0 |= new_cr0_val;
+
+
+         PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
+       } else {
+         PrintDebug("Old CR0=%x\n", *real_cr0);        
+         // for now we just pass through....
+         *(char*)real_cr0 &= 0xf0;
+         *(char*)real_cr0 |= new_cr0_val;
+
+         PrintDebug("New CR0=%x\n", *real_cr0);
+       }
+
+       info->rip += index;
+
 
       } else if ((instr[index] == 0x0f) &&
                 (instr[index + 1] == 0x06)) { 
@@ -359,6 +488,7 @@ int handle_cr0_read(struct guest_info * info) {
       int ret;
 
       PrintDebug("Real Mode read from CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
+      PrintV3Segments(&(info->segments));
 
       // The real rip address is actually a combination of the rip + CS base 
       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
@@ -370,9 +500,28 @@ int handle_cr0_read(struct guest_info * info) {
 
 
       while (is_prefix_byte(instr[index])) {
+       switch(instr[index]) {
+       case PREFIX_CS_OVERRIDE:
+       case PREFIX_SS_OVERRIDE:
+       case PREFIX_DS_OVERRIDE:
+       case PREFIX_ES_OVERRIDE:
+       case PREFIX_FS_OVERRIDE:
+       case PREFIX_GS_OVERRIDE:
+         PrintDebug("Segment Override!!\n");
+         return -1;
+         break;
+       default:
+         break;
+       }
        index++; 
       }
 
+      /*
+       while (is_prefix_byte(instr[index])) {
+       index++; 
+       }
+      */
+
       if ((instr[index] == cr_access_byte) && 
          (instr[index + 1] == smsw_byte) && 
          (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
@@ -478,6 +627,10 @@ int handle_cr0_read(struct guest_info * info) {
        ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
       }
 
+
+      PrintDebug("Instr (15 bytes) at %x:\n", instr);
+      PrintTraceMemDump((char*)instr, 15);
+
       if (ret != 15) {
        // I think we should inject a GPF into the guest
        PrintDebug("Could not read Protected %s mode instruction (ret=%d)\n", 
@@ -485,11 +638,31 @@ int handle_cr0_read(struct guest_info * info) {
        return -1;
       }
 
+
       while (is_prefix_byte(instr[index])) {
+       switch(instr[index]) {
+       case PREFIX_CS_OVERRIDE:
+       case PREFIX_SS_OVERRIDE:
+       case PREFIX_DS_OVERRIDE:
+       case PREFIX_ES_OVERRIDE:
+       case PREFIX_FS_OVERRIDE:
+       case PREFIX_GS_OVERRIDE:
+         PrintDebug("Segment Override!!\n");
+         return -1;
+         break;
+       default:
+         break;
+       }
        index++; 
       }
 
 
+      /*
+       while (is_prefix_byte(instr[index])) {
+       index++; 
+       }
+      */
+
       if ((instr[index] == cr_access_byte) &&
          (instr[index+1] == mov_from_cr_byte)) {
        
@@ -561,7 +734,124 @@ int handle_cr0_read(struct guest_info * info) {
 
 
 int handle_cr3_write(struct guest_info * info) {
-  if (info->cpu_mode == PROTECTED) {
+  if (info->cpu_mode == REAL) {
+    // WHAT THE HELL DOES THIS EVEN MEAN?????
+
+    int index = 0;
+    int ret;
+    char instr[15];
+
+    PrintDebug("Real Mode Write to CR3??? What the fuck???\n");
+    // We need to read the instruction, which is at CS:IP, but that 
+    // linear address is guest physical without PG and guest virtual with PG
+
+    ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+
+    if (ret != 15) {
+      PrintDebug("Could not read instruction (ret=%d)\n", ret);
+      return -1;
+    }
+
+    while (is_prefix_byte(instr[index])) {
+      switch(instr[index]) {
+      case PREFIX_CS_OVERRIDE:
+      case PREFIX_SS_OVERRIDE:
+      case PREFIX_DS_OVERRIDE:
+      case PREFIX_ES_OVERRIDE:
+      case PREFIX_FS_OVERRIDE:
+      case PREFIX_GS_OVERRIDE:
+       PrintDebug("Segment Override!!\n");
+       return -1;
+       break;
+      default:
+       break;
+      }
+      index++; 
+    }
+    
+
+    if ((instr[index] == cr_access_byte) && 
+       (instr[index + 1] == mov_to_cr_byte)) {
+
+      addr_t first_operand;
+      addr_t second_operand;
+      struct cr3_32 * new_cr3;
+      //      struct cr3_32 * real_cr3;
+      operand_type_t addr_type;
+
+      index += 2;
+
+      addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+
+      if (addr_type != REG_OPERAND) {
+       /* Mov to CR3 can only be a 32 bit register */
+       return -1;
+      }
+
+      new_cr3 = (struct cr3_32 *)first_operand;
+
+      if (info->shdw_pg_mode == SHADOW_PAGING) {
+       addr_t shadow_pt;
+       struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
+       struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
+
+       /*
+
+         if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) {
+           PrintDebug("Shadow Page Table\n");
+           PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
+         }
+       */
+
+       /* Delete the current Page Tables */
+       delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
+
+       PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
+                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
+
+
+       *guest_cr3 = *new_cr3;
+
+
+
+       // Something like this
+       shadow_pt =  create_new_shadow_pt32(info);
+       //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
+
+       /* Copy Various flags */
+       *shadow_cr3 = *new_cr3;
+
+       /*
+       {
+         addr_t tmp_addr;
+         guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr);
+         PrintDebug("Guest PD\n");
+         PrintPD32((pde32_t *)tmp_addr);
+
+       }
+       */
+
+       
+       shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
+
+       PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
+                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
+
+
+
+
+      }
+      info->rip += index;
+
+    } else {
+      PrintDebug("Unknown Instruction\n");
+      SerialMemDump(instr,15);
+      return -1;
+    }
+
+
+
+  } else if (info->cpu_mode == PROTECTED) {
     int index = 0;
     int ret;
     char instr[15];
@@ -587,10 +877,29 @@ int handle_cr3_write(struct guest_info * info) {
       PrintDebug("Could not read instruction (ret=%d)\n", ret);
       return -1;
     }
-    
+
     while (is_prefix_byte(instr[index])) {
-      index++;
+      switch(instr[index]) {
+      case PREFIX_CS_OVERRIDE:
+      case PREFIX_SS_OVERRIDE:
+      case PREFIX_DS_OVERRIDE:
+      case PREFIX_ES_OVERRIDE:
+      case PREFIX_FS_OVERRIDE:
+      case PREFIX_GS_OVERRIDE:
+       PrintDebug("Segment Override!!\n");
+       return -1;
+       break;
+      default:
+       break;
+      }
+      index++; 
     }
+    
+    /*    
+         while (is_prefix_byte(instr[index])) {
+         index++;
+         }
+    */
 
     if ((instr[index] == cr_access_byte) && 
        (instr[index + 1] == mov_to_cr_byte)) {
@@ -618,10 +927,12 @@ int handle_cr3_write(struct guest_info * info) {
        struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
 
 
+       /*
          if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) {
            PrintDebug("Shadow Page Table\n");
            PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
          }
+       */
 
        /* Delete the current Page Tables */
        delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
@@ -641,6 +952,7 @@ int handle_cr3_write(struct guest_info * info) {
        /* Copy Various flags */
        *shadow_cr3 = *new_cr3;
 
+       /*
        {
          addr_t tmp_addr;
          guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr);
@@ -648,7 +960,7 @@ int handle_cr3_write(struct guest_info * info) {
          PrintPD32((pde32_t *)tmp_addr);
 
        }
-       
+       */
 
        
        shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
@@ -685,34 +997,76 @@ int handle_cr3_write(struct guest_info * info) {
 int handle_cr3_read(struct guest_info * info) {
 
   if (info->cpu_mode == REAL) {
-    // what does this mean???
-
-    /*
-
-    addr_t host_addr;
+    char instr[15];
+    int ret;
+    int index = 0;
     addr_t linear_addr = 0;
 
-
-
     linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
 
     
     PrintDebug("RIP Linear: %x\n", linear_addr);
     PrintV3Segments(&(info->segments));
     
-      
-    if (info->mem_mode == PHYSICAL_MEM) {
-      guest_pa_to_host_pa(info, linear_addr, &host_addr);
-    } else if (info->mem_mode == VIRTUAL_MEM) {
-      guest_va_to_host_pa(info, linear_addr, &host_addr);
+    ret = read_guest_pa_memory(info, linear_addr, 15, instr);
+
+    if (ret != 15) {
+      PrintDebug("Could not read instruction (ret=%d)\n", ret);
+      return -1;
+    }
+    
+    while (is_prefix_byte(instr[index])) {
+      switch(instr[index]) {
+      case PREFIX_CS_OVERRIDE:
+      case PREFIX_SS_OVERRIDE:
+      case PREFIX_DS_OVERRIDE:
+      case PREFIX_ES_OVERRIDE:
+      case PREFIX_FS_OVERRIDE:
+      case PREFIX_GS_OVERRIDE:
+       PrintDebug("Segment Override!!\n");
+       return -1;
+       break;
+      default:
+       break;
+      }
+      index++; 
     }
 
 
-    pt32_lookup((pde32_t *)CR3_TO_PDE32(info->shdw_pg_state.shadow_cr3), , addr_t * paddr);
-    */
+    if ((instr[index] == cr_access_byte) && 
+       (instr[index + 1] == mov_from_cr_byte)) {
+      addr_t first_operand;
+      addr_t second_operand;
+      struct cr3_32 * virt_cr3;
+      struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
+      operand_type_t addr_type;
+
+      index += 2;
 
+      addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
 
-    return -1;
+      if (addr_type != REG_OPERAND) {
+       /* Mov to CR3 can only be a 32 bit register */
+       return -1;
+      }
+
+      virt_cr3 = (struct cr3_32 *)first_operand;
+
+      if (info->shdw_pg_mode == SHADOW_PAGING) {
+       *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
+      } else {
+       *virt_cr3 = *real_cr3;
+      }
+      
+      info->rip += index;
+    } else {
+      PrintDebug("Unknown Instruction\n");
+      SerialMemDump(instr,15);
+      return -1;
+    }
+
+
+    return 0;
   } else if (info->cpu_mode == PROTECTED) {
 
     int index = 0;
@@ -736,9 +1090,28 @@ int handle_cr3_read(struct guest_info * info) {
     }
     
     while (is_prefix_byte(instr[index])) {
-      index++;
+      switch(instr[index]) {
+      case PREFIX_CS_OVERRIDE:
+      case PREFIX_SS_OVERRIDE:
+      case PREFIX_DS_OVERRIDE:
+      case PREFIX_ES_OVERRIDE:
+      case PREFIX_FS_OVERRIDE:
+      case PREFIX_GS_OVERRIDE:
+       PrintDebug("Segment Override!!\n");
+       return -1;
+       break;
+      default:
+       break;
+      }
+      index++; 
     }
 
+    /*
+      while (is_prefix_byte(instr[index])) {
+      index++;
+      }
+    */
+
     if ((instr[index] == cr_access_byte) && 
        (instr[index + 1] == mov_from_cr_byte)) {
       addr_t first_operand;
index a69900a..abb190b 100644 (file)
@@ -30,10 +30,8 @@ int handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_erro
       break;
     case PROTECTED_PAE:
     case LONG:
-      // currently not handled
-      return -1;
-      break;
     default:
+      PrintDebug("Unhandled CPU Mode\n");
       return -1;
     }
   } else {
@@ -136,12 +134,14 @@ int handle_shadow_pagefault32(struct guest_info * info, addr_t fault_addr, pf_er
     PrintDebug("Injecting PDE pf to guest: (guest access error=%d) (pf error code=%d)\n", guest_pde_access, error_code);
     return 0;
 
-    PrintDebug("Guest CR3=%x\n", guest_cr3);
-    PrintDebug("Guest PD\n");
-    PrintPD32(guest_pd);
-    PrintDebug("Shadow PD\n");
-    PrintPD32(shadow_pd);
-
+    /*  
+       PrintDebug("Guest CR3=%x\n", guest_cr3);
+       PrintDebug("Guest PD\n");
+       PrintPD32(guest_pd);
+       PrintDebug("Shadow PD\n");
+       PrintPD32(shadow_pd);
+    */
 
     return -1;
   }