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.


more 64 bit guest support
[palacios.git] / palacios / src / palacios / vmm_ctrl_regs.c
index e2ab2bc..b3d3356 100644 (file)
@@ -96,6 +96,10 @@ int v3_handle_cr0_write(struct guest_info * info) {
 
     if (info->cpu_mode == LONG) {
       // 64 bit registers
+      // Set efer.lma = 1
+
+      PrintError("Long mode currently not handled\n");
+      return -1;
     } else {
       // 32 bit registers
        struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
@@ -270,14 +274,12 @@ int v3_handle_cr3_write(struct guest_info * info) {
       } else if (cached == 0) {
        addr_t shadow_pt;
        
-       if( info->mem_mode == VIRTUAL_MEM )
-       {
-               PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 );      
-       
-               delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
+       if(info->mem_mode == VIRTUAL_MEM) {
+         PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 );
+         delete_page_tables_32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
        }
        
-       shadow_pt =  v3_create_new_shadow_pt32();
+       shadow_pt =  v3_create_new_shadow_pt();
        
        shadow_cr3->pdt_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PD32_BASE_ADDR(shadow_pt));
        PrintDebug( "Created new shadow page table %p\n", (void *)(addr_t)shadow_cr3->pdt_base_addr );
@@ -361,3 +363,127 @@ int v3_handle_cr3_read(struct guest_info * info) {
 
   return 0;
 }
+
+int v3_handle_cr4_read(struct guest_info * info) {
+  PrintError("CR4 Read not handled\n");
+  return -1;
+}
+
+int v3_handle_cr4_write(struct guest_info * info) {
+  uchar_t instr[15];
+  int ret;
+  struct x86_instr dec_instr;
+
+  if (info->mem_mode == PHYSICAL_MEM) { 
+    ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+  } else { 
+    ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+  }
+
+  if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
+    PrintError("Could not decode instruction\n");
+    return -1;
+  }
+
+  if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) != 0) {
+    PrintError("Invalid opcode in write to CR4\n");
+    return -1;
+  }
+
+  if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PAE)) {
+    struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
+    struct cr4_32 * old_cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
+    
+    PrintDebug("OperandVal = %x, length = %d\n", *(uint_t *)new_cr4, dec_instr.src_operand.size);
+    PrintDebug("Old CR4=%x\n", *(uint_t *)old_cr4);
+
+
+
+
+    if ((info->shdw_pg_mode == SHADOW_PAGING) && 
+       (v3_get_mem_mode(info) == PHYSICAL_MEM)) {
+
+      if ((old_cr4->pae == 0) && (new_cr4->pae == 1)) {
+       PrintDebug("Creating PAE passthrough tables\n");
+
+       // Delete the old 32 bit direct map page tables
+       delete_page_tables_32((pde32_t *)V3_VAddr((void *)(info->direct_map_pt)));
+
+       // create 32 bit PAE direct map page table
+       info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_32PAE(info));
+
+       // reset cr3 to new page tables
+       info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
+
+      } else if ((old_cr4->pae == 1) && (new_cr4->pae == 0)) {
+       // Create passthrough standard 32bit pagetables
+       return -1;
+      }
+    }
+
+    *old_cr4 = *new_cr4;
+    PrintDebug("New CR4=%x\n", *(uint_t *)old_cr4);
+
+  } else {
+    return -1;
+  }
+
+  info->rip += dec_instr.instr_length;
+  return 0;
+}
+
+
+int v3_handle_efer_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
+  PrintError("EFER Read not handled\n");
+  return -1;
+}
+
+
+int v3_handle_efer_write(uint_t msr, struct v3_msr src, void * priv_data) {
+  struct guest_info * info = (struct guest_info *)(priv_data);
+  struct efer_64 * new_efer = (struct efer_64 *)&(src.value);
+  struct efer_64 * old_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
+
+  PrintDebug("Old EFER=%p\n", (void *)*(addr_t*)(old_efer));
+
+  if ((info->shdw_pg_mode == SHADOW_PAGING) && 
+      (v3_get_mem_mode(info) == PHYSICAL_MEM)) {
+    
+    if ((old_efer->lme == 0) && (new_efer->lme == 1)) {
+      PrintDebug("Transition to longmode\n");
+      PrintDebug("Creating Passthrough 64 bit page tables\n");
+      
+      // Delete the old 32 bit direct map page tables
+      /* 
+       * JRL BUG? 
+       * Will these page tables always be in PAE format?? 
+       */
+      PrintDebug("Deleting old PAE Page tables\n");
+      PrintError("JRL BUG?: Will the old page tables always be in PAE format??\n");
+      delete_page_tables_32PAE((pdpe32pae_t *)V3_VAddr((void *)(info->direct_map_pt)));
+      
+      // create 64 bit direct map page table
+      info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(info));
+      
+      // reset cr3 to new page tables
+      info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
+      
+
+      // Does this mean we will have to fully virtualize a shadow  EFER??
+      new_efer->lma = 1;
+      
+    } else if ((old_efer->lme == 1) && (new_efer->lme == 0)) {
+      // transition out of long mode
+      return -1;
+    }
+
+    *old_efer = *new_efer;
+    PrintDebug("New EFER=%p\n", (void *)*(addr_t *)(old_efer));
+  } else {
+    return -1;
+  }
+
+  info->rip += 2; // WRMSR/RDMSR are two byte operands
+
+  return 0;
+}