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.


revamped the INVLPG handler
Jack Lange [Tue, 3 Feb 2009 20:45:02 +0000 (14:45 -0600)]
palacios/include/palacios/vmm_decoder.h
palacios/include/palacios/vmm_paging.h
palacios/include/palacios/vmm_shadow_paging.h
palacios/src/palacios/vmm_shadow_paging.c
palacios/src/palacios/vmm_shadow_paging_32.h
palacios/src/palacios/vmm_shadow_paging_32pae.h
palacios/src/palacios/vmm_shadow_paging_64.h
palacios/src/palacios/vmm_xed.c

index 0ae0109..6aa0833 100644 (file)
@@ -28,6 +28,7 @@
 
 typedef enum { V3_INVALID_OP,
               V3_OP_MOVCR2, V3_OP_MOV2CR, V3_OP_SMSW, V3_OP_LMSW, V3_OP_CLTS,
+              V3_OP_INVLPG,
               V3_OP_ADC, V3_OP_ADD, V3_OP_AND, V3_OP_OR, V3_OP_XOR, V3_OP_SUB,
               V3_OP_INC, V3_OP_DEC, V3_OP_NEG, V3_OP_MOV, V3_OP_NOT, V3_OP_XCHG, 
               V3_OP_SETB, V3_OP_SETBE, V3_OP_SETL, V3_OP_SETLE, V3_OP_SETNB, 
index e7f68f1..7535a3e 100644 (file)
@@ -129,23 +129,7 @@ typedef enum {PAGE_4KB, PAGE_2MB, PAGE_4MB, PAGE_1GB,
 
 
 /* Gets the base address needed for a Page Table entry */
-/* Deprecate these :*/
-/*
-  #define PD32_BASE_ADDR(x) (((uint_t)x) >> 12)
-  #define PT32_BASE_ADDR(x) (((uint_t)x) >> 12)
-  #define PD32_4MB_BASE_ADDR(x) (((uint_t)x) >> 22)
-  
-  #define PML4E64_BASE_ADDR(x) (((ullong_t)x) >> 12)
-  #define PDPE64_BASE_ADDR(x) (((ullong_t)x) >> 12)
-  #define PDE64_BASE_ADDR(x) (((ullong_t)x) >> 12)
-  #define PTE64_BASE_ADDR(x) (((ullong_t)x) >> 12)
-  
-  // Accessor functions for the page table structures 
-  #define PDE32_T_ADDR(x) (((x).pt_base_addr) << 12)
-  #define PTE32_T_ADDR(x) (((x).page_base_addr) << 12)
-  #define PDE32_4MB_T_ADDR(x) (((x).page_base_addr) << 22)
-*/
-/* Replace The above with these... */
+
 #define PAGE_BASE_ADDR(x) ((x) >> 12)
 #define PAGE_BASE_ADDR_4KB(x) ((x) >> 12)
 #define PAGE_BASE_ADDR_2MB(x) ((x) >> 21)
@@ -159,21 +143,7 @@ typedef enum {PAGE_4KB, PAGE_2MB, PAGE_4MB, PAGE_1GB,
 #define BASE_TO_PAGE_ADDR_1GB(x) (((addr_t)x) << 30)
 /* *** */
 
-/* Deprecated */
-/*
-  #define PT32_PAGE_OFFSET(x) (((uint_t)x) & 0xfff)
-  #define PD32_4MB_PAGE_OFFSET(x) (((uint_t)x) & 0x003fffff)
-  
-  #define PT32_PAGE_ADDR(x)   (((uint_t)x) & 0xfffff000)
-  #define PD32_4MB_PAGE_ADDR(x) (((uint_t)x) & 0xffc00000)
-  
-  #define PT32_PAGE_POWER 12
-  #define PAGE_ALIGNED_ADDR(x)   (((uint_t) (x)) >> 12)
-  //#define PAGE_ADDR(x)   (PAGE_ALIGNED_ADDR(x) << 12)
-  #define PAGE_POWER 12
-  #define PAGE_SIZE 4096
-*/
-/* use these instead */
+
 #define PAGE_OFFSET(x) ((x) & 0xfff)
 #define PAGE_OFFSET_4KB(x) ((x) & 0xfff)
 #define PAGE_OFFSET_2MB(x) ((x) & 0x1fffff)
index 1b63e8b..da9c76d 100644 (file)
@@ -61,15 +61,6 @@ int v3_handle_shadow_invlpg(struct guest_info * info);
 int v3_activate_shadow_pt(struct guest_info * info);
 int v3_activate_passthrough_pt(struct guest_info * info);
 
-/* TODO: Change to static functions
- * External visibility not needed
- */
-addr_t v3_create_new_shadow_pt();
-int v3_replace_shdw_page32(struct guest_info * info, addr_t location, pte32_t * new_page, pte32_t * old_page); 
-/* *** */
-
-
-int v3_replace_shdw_page(struct guest_info * info, addr_t location, void * new_page, void * old_page);
 
 #endif // ! __V3VEE__
 
index 6a0b3be..0f98acf 100644 (file)
@@ -99,16 +99,13 @@ int v3_init_shadow_page_state(struct guest_info * info) {
   state->guest_cr0 = 0;
 
   state->cached_ptes = NULL;
-
+  state->cached_cr3 = 0;
+  
   return 0;
 }
 
 
 
-
-
-
-
 // Reads the guest CR3 register
 // creates new shadow page tables
 // updates the shadow CR3 register to point to the new pts
@@ -148,12 +145,6 @@ int v3_handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_e
   
   if (info->mem_mode == PHYSICAL_MEM) {
     // If paging is not turned on we need to handle the special cases
-
-#ifdef DEBUG_SHADOW_PAGING
-    PrintHostPageTree(info->cpu_mode, fault_addr, info->ctrl_regs.cr3);
-    PrintGuestPageTree(info, fault_addr, info->shdw_pg_state.guest_cr3);
-#endif
-
     return handle_special_page_fault(info, fault_addr, fault_addr, error_code);
   } else if (info->mem_mode == VIRTUAL_MEM) {
 
@@ -238,97 +229,58 @@ static int is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shado
 
 
 
+int v3_handle_shadow_invlpg(struct guest_info * info) {
+  uchar_t instr[15];
+  struct x86_instr dec_instr;
+  int ret = 0;
+  addr_t vaddr = 0;
 
-
-/* Currently Does not work with Segmentation!!! */
-int v3_handle_shadow_invlpg(struct guest_info * info)
-{
   if (info->mem_mode != VIRTUAL_MEM) {
     // Paging must be turned on...
     // should handle with some sort of fault I think
     PrintError("ERROR: INVLPG called in non paged mode\n");
     return -1;
   }
-  
-  
-  if (info->cpu_mode != PROTECTED) {
-    PrintError("Unsupported CPU mode (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
-    return -1;
+
+  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);
   }
-  
-  uchar_t instr[15];
-  int index = 0;
-  
-  int ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
-  if (ret != 15) {
-    PrintError("Could not read instruction 0x%p (ret=%d)\n",  (void *)(addr_t)(info->rip), ret);
+
+  if (ret == -1) {
+    PrintError("Could not read instruction into buffer\n");
     return -1;
   }
-  
-  
-  /* Can INVLPG work with Segments?? */
-  while (is_prefix_byte(instr[index])) {
-    index++;
-  }
-    
-    
-  if( (instr[index + 0] != (uchar_t) 0x0f) ||  
-      (instr[index + 1] != (uchar_t) 0x01) ) {
-    PrintError("invalid Instruction Opcode\n");
-    PrintTraceMemDump(instr, 15);
+
+  if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
+    PrintError("Decoding Error\n");
     return -1;
   }
   
-  addr_t first_operand;
-  addr_t second_operand;
-  addr_t guest_cr3 =  CR3_TO_PDE32_PA(info->shdw_pg_state.guest_cr3);
-  
-  pde32_t * guest_pd = NULL;
-  
-  if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) {
-    PrintError("Invalid Guest PDE Address: 0x%p\n",  (void *)guest_cr3);
+  if ((dec_instr.op_type != V3_OP_INVLPG) || 
+      (dec_instr.num_operands != 1) ||
+      (dec_instr.dst_operand.type != MEM_OPERAND)) {
+    PrintError("Decoder Error: Not a valid INVLPG instruction...\n");
     return -1;
   }
-  
-  index += 2;
 
-  v3_operand_type_t addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
-  
-  if (addr_type != MEM_OPERAND) {
-    PrintError("Invalid Operand type\n");
+  vaddr = dec_instr.dst_operand.operand;
+
+  info->rip += dec_instr.instr_length;
+
+  switch (info->cpu_mode) {
+  case PROTECTED:
+    return handle_shadow_invlpg_32(info, vaddr);
+  case PROTECTED_PAE:
+    return handle_shadow_invlpg_32pae(info, vaddr);
+  case LONG:
+  case LONG_32_COMPAT:
+  case LONG_16_COMPAT:
+    return handle_shadow_invlpg_64(info, vaddr);
+  default:
+    PrintError("Invalid CPU mode: %d\n", info->cpu_mode);
     return -1;
   }
-  
-  pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32_VA(info->ctrl_regs.cr3);
-  pde32_t * shadow_pde = (pde32_t *)&shadow_pd[PDE32_INDEX(first_operand)];
-  pde32_t * guest_pde;
-  
-  //PrintDebug("PDE Index=%d\n", PDE32_INDEX(first_operand));
-  //PrintDebug("FirstOperand = %x\n", first_operand);
-  
-  PrintDebug("Invalidating page for %p\n", (void *)first_operand);
-  
-  guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(first_operand)]);
-  
-  if (guest_pde->large_page == 1) {
-    shadow_pde->present = 0;
-    PrintDebug("Invalidating Large Page\n");
-  } else
-    if (shadow_pde->present == 1) {
-      pte32_t * shadow_pt = (pte32_t *)(addr_t)BASE_TO_PAGE_ADDR(shadow_pde->pt_base_addr);
-      pte32_t * shadow_pte = (pte32_t *) V3_VAddr( (void*) &shadow_pt[PTE32_INDEX(first_operand)] );
-      
-#ifdef DEBUG_SHADOW_PAGING
-      PrintDebug("Setting not present\n");
-      PrintPTEntry(PAGE_PT32, first_operand, shadow_pte);
-#endif
-      
-      shadow_pte->present = 0;
-    }
-  
-  info->rip += index;
-  
-  return 0;
 }
 
-
index 7e0106a..b43a5a6 100644 (file)
@@ -495,3 +495,37 @@ static int handle_shadow_pte32_fault(struct guest_info * info,
   PrintDebug("Returning end of function\n");
   return 0;
 }
+
+
+
+/* If we start to optimize we should look up the guest pages in the cache... */
+static int handle_shadow_invlpg_32(struct guest_info * info, addr_t vaddr) {
+  pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32_VA(info->ctrl_regs.cr3);
+  pde32_t * shadow_pde = (pde32_t *)&shadow_pd[PDE32_INDEX(vaddr)];
+
+  addr_t guest_cr3 =  CR3_TO_PDE32_PA(info->shdw_pg_state.guest_cr3);
+  pde32_t * guest_pd = NULL;
+  pde32_t * guest_pde;
+
+  if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) {
+    PrintError("Invalid Guest PDE Address: 0x%p\n",  (void *)guest_cr3);
+    return -1;
+  }
+  
+  guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(vaddr)]);
+  
+  if (guest_pde->large_page == 1) {
+    shadow_pde->present = 0;
+    PrintDebug("Invalidating Large Page\n");
+  } else if (shadow_pde->present == 1) {
+    pte32_t * shadow_pt = (pte32_t *)(addr_t)BASE_TO_PAGE_ADDR_4KB(shadow_pde->pt_base_addr);
+    pte32_t * shadow_pte = (pte32_t *) V3_VAddr( (void*) &shadow_pt[PTE32_INDEX(vaddr)] );
+    
+    PrintDebug("Setting not present\n");
+    
+    shadow_pte->present = 0;
+  }
+  
+
+  return 0;
+}
index 58a4300..42570de 100644 (file)
@@ -25,6 +25,11 @@ static int handle_shadow_pagefault_32pae(struct guest_info * info, addr_t fault_
 }
 
 
+static int handle_shadow_invlpg_32pae(struct guest_info * info, addr_t vaddr) {
+  PrintError("32 bit PAE shadow paging not implemented\n");
+  return -1;
+}
+
 
 
 
index 685ed61..12a21e5 100644 (file)
@@ -36,3 +36,9 @@ static int handle_shadow_pagefault_64(struct guest_info * info, addr_t fault_add
   PrintError("64 bit shadow paging not implemented\n");
   return -1;
 }
+
+
+static int handle_shadow_invlpg_64(struct guest_info * info, addr_t vaddr) {
+  PrintError("64 bit shadow paging not implemented\n");
+  return -1;
+}
index 3c39b13..73dd4ce 100644 (file)
@@ -1021,6 +1021,9 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a
 static v3_op_type_t get_opcode(xed_iform_enum_t iform) {
 
   switch (iform) {
+
+    /* Control Instructions */
+
   case XED_IFORM_MOV_CR_GPR64_CR:
   case XED_IFORM_MOV_CR_GPR32_CR:
     return V3_OP_MOVCR2;
@@ -1038,6 +1041,12 @@ static v3_op_type_t get_opcode(xed_iform_enum_t iform) {
   case XED_IFORM_CLTS:
     return V3_OP_CLTS;
 
+  case XED_IFORM_INVLPG_MEMb:
+    return V3_OP_INVLPG;
+
+
+    /* Data Instructions */
+
   case XED_IFORM_ADC_MEMv_GPRv:
   case XED_IFORM_ADC_MEMv_IMM:
   case XED_IFORM_ADC_MEMb_GPR8:
@@ -1149,6 +1158,7 @@ static v3_op_type_t get_opcode(xed_iform_enum_t iform) {
   case XED_IFORM_SETZ_MEMb:
     return V3_OP_SETZ;
 
+
   case XED_IFORM_MOVSB:
   case XED_IFORM_MOVSW:
   case XED_IFORM_MOVSD: