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.


added invlpg support
Jack Lange [Mon, 19 May 2008 23:45:27 +0000 (23:45 +0000)]
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_paging.h
palacios/include/palacios/vmm_shadow_paging.h
palacios/src/geekos/vm.c
palacios/src/palacios/svm.c
palacios/src/palacios/svm_handler.c
palacios/src/palacios/svm_io.c
palacios/src/palacios/vm_guest_mem.c
palacios/src/palacios/vmm_ctrl_regs.c
palacios/src/palacios/vmm_paging.c
palacios/src/palacios/vmm_shadow_paging.c

index 13be2f0..89e6590 100644 (file)
@@ -86,6 +86,8 @@ struct guest_info {
   ullong_t rip;
 
 
+  uint_t cpl;
+
   struct shadow_map mem_map;
 
   
index 5cbdbd3..c3b235e 100644 (file)
@@ -112,8 +112,8 @@ the host state in the vmcs before entering the guest.
 
 
 /* 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_T_ADDR(x) (((x).pt_base_addr) << 12)
+#define PTE32_T_ADDR(x) (((x).page_base_addr) << 12)
 
 
 #endif
index 695e0f6..40182e5 100644 (file)
@@ -57,4 +57,7 @@ int handle_shadow_pte32_fault(struct guest_info* info,
                              pte32_t * guest_pte);
 
 
+
+int handle_shadow_invlpg(struct guest_info * info);
+
 #endif
index fe50c29..3666486 100644 (file)
@@ -304,7 +304,7 @@ int RunVMM(struct Boot_Info * bootInfo) {
       print_shadow_map(&(vm_info.mem_map));
 
       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
-      hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
+      //hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
 
 
       hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial, NULL);
index 9983b08..7889c11 100644 (file)
@@ -143,7 +143,7 @@ int start_svm_guest(struct guest_info *info) {
     CLGI();
 
     //PrintDebug("SVM Launch Args (vmcb=%x), (info=%x), (vm_regs=%x)\n", info->vmm_data,  &(info->vm_regs));
-    PrintDebug("Launching to RIP: %x\n", info->rip);
+    //PrintDebug("Launching to RIP: %x\n", info->rip);
     safe_svm_launch((vmcb_t*)(info->vmm_data), &(info->vm_regs));
     //launch_svm((vmcb_t*)(info->vmm_data));
     //PrintDebug("SVM Returned\n");
@@ -327,6 +327,8 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
   // guest_state->rip = vm_info.rip;
   guest_state->rip = 0xfff0;
 
+  guest_state->cpl = 0;
+
   //ctrl_area->instrs.instrs.CR0 = 1;
   ctrl_area->cr_reads.cr0 = 1;
   ctrl_area->cr_writes.cr0 = 1;
index 7ac7be2..4ab4979 100644 (file)
@@ -7,7 +7,6 @@
 #include <palacios/vmm_intr.h>
 
 
-
 int handle_svm_exit(struct guest_info * info) {
   vmcb_ctrl_t * guest_ctrl = 0;
   vmcb_saved_state_t * guest_state = 0;
@@ -22,6 +21,7 @@ int handle_svm_exit(struct guest_info * info) {
   info->vm_regs.rsp = guest_state->rsp;
   info->vm_regs.rax = guest_state->rax;
 
+  info->cpl = guest_state->cpl;
 
 
   info->ctrl_regs.cr0 = guest_state->cr0;
@@ -36,7 +36,7 @@ int handle_svm_exit(struct guest_info * info) {
 
   exit_code = guest_ctrl->exit_code;
  
-  PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
+  //PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
   // PrintDebugVMCB((vmcb_t*)(info->vmm_data));
 
 
@@ -110,8 +110,15 @@ int handle_svm_exit(struct guest_info * info) {
       return -1;
     }
 
+  } else if (exit_code == VMEXIT_INVLPG) {
+    if (info->page_mode == SHADOW_PAGING) {
+      PrintDebug("Invlpg\n");
+      if (handle_shadow_invlpg(info) == -1) {
+       return -1;
+      }
+    }
+   
     /*
-      (exit_code == VMEXIT_INVLPG)    ||
       (exit_code == VMEXIT_INVLPGA)   || 
     */
     
@@ -226,6 +233,8 @@ int handle_svm_exit(struct guest_info * info) {
   guest_state->rflags = info->ctrl_regs.rflags;
 
 
+  guest_state->cpl = info->cpl;
+
   guest_state->rax = info->vm_regs.rax;
   guest_state->rip = info->rip;
   guest_state->rsp = info->vm_regs.rsp;
index a4208f4..d70be6f 100644 (file)
@@ -20,7 +20,7 @@ int handle_svm_io_in(struct guest_info * info) {
     return -1;
   }
 
-  PrintDebug("IN on  port %d (0x%x)\n", io_info->port, io_info->port);
+  //PrintDebug("IN on  port %d (0x%x)\n", io_info->port, io_info->port);
 
   if (io_info->sz8) { 
     read_size = 1;
@@ -80,7 +80,7 @@ int handle_svm_io_ins(struct guest_info * info) {
     return -1;
   }
 
-  PrintDebug("INS on  port %d (0x%x)\n", io_info->port, io_info->port);
+  //PrintDebug("INS on  port %d (0x%x)\n", io_info->port, io_info->port);
 
   if (io_info->sz8) { 
     read_size = 1;
@@ -150,7 +150,7 @@ int handle_svm_io_out(struct guest_info * info) {
     return -1;
   }
 
-  PrintDebug("OUT on  port %d (0x%x)\n", io_info->port, io_info->port);
+  //PrintDebug("OUT on  port %d (0x%x)\n", io_info->port, io_info->port);
 
   if (io_info->sz8) { 
     write_size = 1;
@@ -208,7 +208,7 @@ int handle_svm_io_outs(struct guest_info * info) {
     return -1;
   }
 
-  PrintDebug("OUTS on  port %d (0x%x)\n", io_info->port, io_info->port);
+  //PrintDebug("OUTS on  port %d (0x%x)\n", io_info->port, io_info->port);
 
   if (io_info->sz8) { 
     write_size = 1;
index 7e45c0c..7b98d83 100644 (file)
@@ -15,9 +15,11 @@ int host_va_to_host_pa(addr_t host_va, addr_t * host_pa) {
     *host_pa = (addr_t)(os_hooks)->vaddr_to_paddr((void *)host_va);
   
     if (*host_pa == 0) {
+      PrintDebug("In HVA->HPA: Invalid HVA(%x)->HPA lookup\n", host_va);
       return -1;
     }
   } else {
+    PrintDebug("In HVA->HPA: os_hooks not defined\n");
     return -1;
   }
   return 0;
@@ -30,9 +32,11 @@ int host_pa_to_host_va(addr_t host_pa, addr_t * host_va) {
     *host_va = (addr_t)(os_hooks)->paddr_to_vaddr((void *)host_pa);
     
     if (*host_va == 0) {
+      PrintDebug("In HPA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa);
       return -1;
     }
   } else {
+    PrintDebug("In HPA->HVA: os_hooks not defined\n");
     return -1;
   }
   return 0;
@@ -43,7 +47,7 @@ int host_pa_to_host_va(addr_t host_pa, addr_t * host_va) {
 int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_pa) {
   // we use the shadow map here...
   if (lookup_shadow_map_addr(&(guest_info->mem_map), guest_pa, host_pa) != HOST_REGION_PHYSICAL_MEMORY) {
-    PrintDebug("Could not find address in shadow map (addr=%x)\n", guest_pa);
+    PrintDebug("In GPA->HPA: Could not find address in shadow map (addr=%x)\n", guest_pa);
     return -1;
   }
 
@@ -57,6 +61,7 @@ int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t
 // 
 int host_pa_to_guest_pa(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_pa) {
   *guest_pa = 0;
+  PrintDebug("ERROR!!! HPA->GPA currently not implemented!!!\n");
 
   return -1;
 }
@@ -71,14 +76,16 @@ int host_pa_to_guest_pa(struct guest_info * guest_info, addr_t host_pa, addr_t *
 /* !! Currently not implemented !! */
 // This will return negative until we implement host_pa_to_guest_pa()
 int host_va_to_guest_pa(struct guest_info * guest_info, addr_t host_va, addr_t * guest_pa) {
-  addr_t host_pa;
+  addr_t host_pa = 0;
   *guest_pa = 0;
 
   if (host_va_to_host_pa(host_va, &host_pa) != 0) {
+    PrintDebug("In HVA->GPA: Invalid HVA(%x)->HPA lookup\n", host_va);
     return -1;
   }
 
   if (host_pa_to_guest_pa(guest_info, host_pa, guest_pa) != 0) {
+    PrintDebug("In HVA->GPA: Invalid HPA(%x)->GPA lookup\n", host_pa);
     return -1;
   }
 
@@ -89,15 +96,17 @@ int host_va_to_guest_pa(struct guest_info * guest_info, addr_t host_va, addr_t *
 
 
 int guest_pa_to_host_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_va) {
-  addr_t host_pa;
+  addr_t host_pa = 0;
 
   *host_va = 0;
 
   if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) {
+    PrintDebug("In GPA->HVA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
     return -1;
   }
   
   if (host_pa_to_host_va(host_pa, host_va) != 0) {
+    PrintDebug("In GPA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa);
     return -1;
   }
 
@@ -117,14 +126,16 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t
       return 0;
     case PROTECTED_PG:
       {
-       addr_t tmp_pa;
-       pde32_t * pde;
+       addr_t tmp_pa = 0;
+       pde32_t * pde = 0;
        addr_t guest_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.guest_cr3);
 
        if (guest_pa_to_host_va(guest_info, guest_pde, (addr_t *)&pde) == -1) {
+         PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PDE32 lookup\n", guest_pde);
          return -1;
        }
 
+
        switch (pde32_lookup(pde, guest_va, &tmp_pa)) {
        case PDE32_ENTRY_NOT_PRESENT: 
          *guest_pa = 0;
@@ -134,13 +145,19 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t
          return 0;
        case PDE32_ENTRY_PTE32:
          {
-           pte32_t * pte;
+           pte32_t * pte = 0;
+
 
            if (guest_pa_to_host_va(guest_info, tmp_pa, (addr_t*)&pte) == -1) {
+             PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PTE32 lookup\n", guest_pa);
              return -1;
            }
            
+           PrintDebug("PTE host addr=%x, GVA=%x, GPA=%x(should be 0)\n", pte, guest_va, *guest_pa);
+
            if (pte32_lookup(pte, guest_va, guest_pa) != 0) {
+             PrintDebug("In GVA->GPA: PTE32 Lookup failure GVA=%x; PTE=%x\n", guest_va, pte);
+             //              PrintPT32(PDE32_INDEX(guest_va) << 22, pte);
              return -1;
            }
 
@@ -182,6 +199,7 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t
  */
 int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * guest_va) {
   *guest_va = 0;
+  PrintDebug("ERROR!!: GPA->GVA Not Implemented!!\n");
   return -1;
 }
 
@@ -192,15 +210,17 @@ int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t
 
 
 int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * host_pa) {
-  addr_t guest_pa;
+  addr_t guest_pa = 0;
 
   *host_pa = 0;
 
   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
+    PrintDebug("In GVA->HPA: Invalid GVA(%x)->GPA lookup\n", guest_va);
     return -1;
   }
   
   if (guest_pa_to_host_pa(guest_info, guest_pa, host_pa) != 0) {
+    PrintDebug("In GVA->HPA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
     return -1;
   }
 
@@ -209,15 +229,17 @@ int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t
 
 /* !! Currently not implemented !! */
 int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_va) {
-  addr_t guest_pa;
+  addr_t guest_pa = 0;
 
   *guest_va = 0;
 
   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
+    PrintDebug("In HPA->GVA: Invalid HPA(%x)->GPA lookup\n", host_pa);
     return -1;
   }
 
   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
+    PrintDebug("In HPA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa);
     return -1;
   }
 
@@ -228,20 +250,23 @@ int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t *
 
 
 int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t * host_va) {
-  addr_t guest_pa;
-  addr_t host_pa;
+  addr_t guest_pa = 0;
+  addr_t host_pa = 0;
 
   *host_va = 0;
 
   if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) {
+    PrintDebug("In GVA->HVA: Invalid GVA(%x)->GPA lookup\n", guest_va);
     return -1;
   }
 
   if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) {
+    PrintDebug("In GVA->HVA: Invalid GPA(%x)->HPA lookup\n", guest_pa);
     return -1;
   }
 
   if (host_pa_to_host_va(host_pa, host_va) != 0) {
+    PrintDebug("In GVA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa);
     return -1;
   }
 
@@ -251,20 +276,23 @@ int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t
 
 /* !! Currently not implemented !! */
 int host_va_to_guest_va(struct guest_info * guest_info, addr_t host_va, addr_t * guest_va) {
-  addr_t host_pa;
-  addr_t guest_pa;
+  addr_t host_pa = 0;
+  addr_t guest_pa = 0;
 
   *guest_va = 0;
 
   if (host_va_to_host_pa(host_va, &host_pa) != 0) {
+    PrintDebug("In HVA->GVA: Invalid HVA(%x)->HPA lookup\n", host_va);
     return -1;
   }
 
   if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) {
+    PrintDebug("In HVA->GVA: Invalid HPA(%x)->GPA lookup\n", host_va);
     return -1;
   }
 
   if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) {
+    PrintDebug("In HVA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa);
     return -1;
   }
 
@@ -283,12 +311,15 @@ int read_guest_va_memory(struct guest_info * guest_info, addr_t guest_va, int co
   addr_t cursor = guest_va;
   int bytes_read = 0;
 
+
+
   while (count > 0) {
     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
-    addr_t host_addr;
+    addr_t host_addr = 0;
 
     if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) {
+      PrintDebug("Invalid GVA(%x)->HVA lookup\n", cursor);
       return bytes_read;
     }
 
@@ -317,7 +348,7 @@ int read_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int co
   while (count > 0) {
     int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor;
     int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge;
-    addr_t host_addr;
+    addr_t host_addr = 0;
 
     if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) {
       return bytes_read;
index d134043..a05f1b9 100644 (file)
@@ -411,6 +411,8 @@ int handle_cr3_write(struct guest_info * info) {
     int ret;
     char instr[15];
 
+
+    /* Isn't the RIP a Guest Virtual Address???????? */
     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);
index 516073a..2c6a078 100644 (file)
@@ -41,8 +41,8 @@ void delete_page_tables_pde32(pde32_t * pde) {
  * The entry addresses could be pointing to either guest physical memory or host physical memory
  * Instead we just return the entry address, and a flag to show if it points to a pte or a large page...
  */
-pde32_entry_type_t pde32_lookup(pde32_t * pde, addr_t addr, addr_t * entry) {
-  pde32_t * pde_entry = &(pde[PDE32_INDEX(addr)]);
+pde32_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) {
+  pde32_t * pde_entry = &(pd[PDE32_INDEX(addr)]);
 
   if (!pde_entry->present) {
     *entry = 0;
@@ -54,6 +54,7 @@ pde32_entry_type_t pde32_lookup(pde32_t * pde, addr_t addr, addr_t * entry) {
       *entry += PAGE_OFFSET(addr);
       return PDE32_ENTRY_LARGE_PAGE;
     } else {
+      *entry = PDE32_T_ADDR(*pde_entry);
       return PDE32_ENTRY_PTE32;
     }
   }  
@@ -64,15 +65,15 @@ pde32_entry_type_t pde32_lookup(pde32_t * pde, addr_t addr, addr_t * entry) {
 
 /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table
  */
-int pte32_lookup(pte32_t * pte, addr_t addr, addr_t * entry) {
-  pte32_t * pte_entry = &(pte[PTE32_INDEX(addr)]);
+int pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) {
+  pte32_t * pte_entry = &(pt[PTE32_INDEX(addr)]);
 
   if (!pte_entry->present) {
     *entry = 0;
+    PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr));
     return -1;
   } else {
-    *entry = PAGE_ADDR(pte_entry->page_base_addr);
-    *entry += PAGE_OFFSET(addr);
+    *entry = PTE32_T_ADDR(*pte_entry) + PT32_PAGE_OFFSET(addr);
     return 0;
   }
 
@@ -124,7 +125,6 @@ pde32_t * create_passthrough_pde32_pts(struct guest_info * guest_info) {
   int i, j;
   struct shadow_map * map = &(guest_info->mem_map);
 
-
   pde32_t * pde = os_hooks->allocate_pages(1);
 
   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
index 72be8e7..69606b8 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <palacios/vmm.h>
 #include <palacios/vm_guest_mem.h>
-
+#include <palacios/vmm_emulate.h>
 
 
 
@@ -249,6 +249,72 @@ addr_t create_new_shadow_pt32(struct guest_info * info) {
 
 
 
+/* Currently Does not work with Segmentation!!! */
+int handle_shadow_invlpg(struct guest_info * info) {
+  if (info->cpu_mode == PROTECTED_PG) {
+    char instr[15];
+    int ret;
+    int index = 0;
+
+    ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+    if (ret != 15) {
+      PrintDebug("Could not read instruction 0x%x (ret=%d)\n", info->rip, ret);
+      return -1;
+    }
+
+   
+    /* Can INVLPG work with Segments?? */
+    while (is_prefix_byte(instr[index])) {
+      index++;
+    }
+    
+    
+    if ((instr[index] == (uchar_t)0x0f) &&
+       (instr[index + 1] == (uchar_t)0x01)) {
+
+      addr_t first_operand;
+      addr_t second_operand;
+      operand_type_t addr_type;
+
+      index += 2;
+
+      addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+
+      if (addr_type == MEM_OPERAND) {
+       pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32(info->shdw_pg_state.shadow_cr3);
+       pde32_t * shadow_pde_entry = (pde32_t *)&shadow_pd[PDE32_INDEX(first_operand)];
+
+       //PrintDebug("PDE Index=%d\n", PDE32_INDEX(first_operand));
+       //PrintDebug("FirstOperand = %x\n", first_operand);
+
+       if (shadow_pde_entry->large_page == 1) {
+         shadow_pde_entry->present = 0;
+       } else {
+         if (shadow_pde_entry->present == 1) {
+           pte32_t * shadow_pt = (pte32_t *)PDE32_T_ADDR((*shadow_pde_entry));
+           pte32_t * shadow_pte_entry = (pte32_t *)&shadow_pt[PTE32_INDEX(first_operand)];
+
+           shadow_pte_entry->present = 0;
+         }
+       }
+
+       info->rip += index;
+
+      } else {
+       PrintDebug("Invalid Operand type\n");
+       return -1;
+      }
+    } else {
+      PrintDebug("invalid Instruction Opcode\n");
+      PrintTraceMemDump(instr, 15);
+      return -1;
+    }       
+  }
+
+  return 0;
+}
+
+
 
 /* Deprecated */
 /*