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.


Add proper cleanup for a nested VMX guest This also fixes a bug that was preventing...
Peter Dinda [Thu, 12 Mar 2015 02:00:40 +0000 (21:00 -0500)]
palacios/src/palacios/vmm_direct_paging.c
palacios/src/palacios/vmx_npt.h

index 2884923..0458155 100644 (file)
@@ -182,6 +182,10 @@ static addr_t create_generic_pt_page(struct guest_info *core) {
 
 
 int v3_init_passthrough_pts(struct guest_info * info) {
+    if (info->shdw_pg_mode == NESTED_PAGING && is_vmx_nested()) { 
+        // skip - ept_init will do this allocation
+        return 0;
+    }
     info->direct_map_pt = (addr_t)V3_PAddr((void *)create_generic_pt_page(info));
     return 0;
 }
@@ -190,6 +194,18 @@ int v3_init_passthrough_pts(struct guest_info * info) {
 int v3_free_passthrough_pts(struct guest_info * core) {
     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
 
+    if (core->shdw_pg_mode == NESTED_PAGING && is_vmx_nested()) { 
+        // there are no passthrough page tables, but
+        // the EPT implementation is using direct_map_pt to store
+        // the EPT root table pointer...  and the EPT tables
+        // are not compatible with regular x86 tables, so we
+        // must not attempt to free them here...
+        return 0;
+    }
+  
+    // we are either in shadow or in SVM nested
+    // in either case, we can nuke the PTs
+
     // Delete the old direct map page tables
     switch(mode) {
        case REAL:
@@ -609,6 +625,8 @@ int v3_init_nested_paging_core(struct guest_info *core, void *hwinfo)
     return init_ept(core, (struct vmx_hw_info *) hwinfo);
   } else {
     // no initialization for SVM
+    // the direct map page tables are used since the 
+    // nested pt format is identical to the main pt format
     return 0;
   }
 }
@@ -637,9 +655,17 @@ int v3_deinit_nested_paging(struct v3_vm_info *vm)
 
 int v3_deinit_nested_paging_core(struct guest_info *core)
 {
-  // nothing to do..  probably dealloc?  FIXME PAD
-
-  return 0;
+  if (core->shdw_pg_mode == NESTED_PAGING) {
+    if (is_vmx_nested()) {
+     return deinit_ept(core);
+    } else {
+      // SVM nested deinit is handled by the passthrough paging teardown
+      return 0;
+    }
+  } else {
+    // not relevant
+    return 0;
+  }
 }
 
 
index aa1bc14..041d67b 100644 (file)
@@ -96,6 +96,66 @@ static int init_ept(struct guest_info * core, struct vmx_hw_info * hw_info) {
 
     ept_ptr->pml_base_addr = PAGE_BASE_ADDR(ept_pa);
 
+    PrintDebug(core->vm_info,core,"init_ept direct_map_pt=%p\n",(void*)(core->direct_map_pt));
+
+
+    return 0;
+}
+
+// 
+// You would think we could just the regular 64 bit PT free
+// routine, but no, because the EPT format is slightly different, in that
+// it has no present bit....   We signify present via the read 
+static void delete_page_tables_ept64(ept_pml4_t * pml4) {
+    int i, j, k;
+
+    if (pml4 == NULL) {
+       return;
+    }
+
+    PrintDebug(VM_NONE, VCORE_NONE,"Deleting EPT Page Tables -- PML4 (%p)\n", pml4);
+
+    for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
+       if (!pml4[i].read && !pml4[i].write && !pml4[i].exec) {
+           continue;
+       }
+
+       ept_pdp_t * pdpe = (ept_pdp_t *)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR_4KB(pml4[i].pdp_base_addr));
+
+       for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
+           if ((!pdpe[j].read && !pdpe[j].write && !pdpe[j].exec) || (pdpe[j].large_page == 1)) {
+               continue;
+           }
+
+           ept_pde_t * pde = (ept_pde_t *)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR_4KB(pdpe[j].pd_base_addr));
+
+           for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
+               if ((!pde[k].read && !pde[k].write && !pde[k].exec) || (pde[k].large_page == 1)) {
+                   continue;
+               }
+
+               V3_FreePages((void *)(addr_t)BASE_TO_PAGE_ADDR_4KB(pde[k].pt_base_addr), 1);
+           }
+           
+           V3_FreePages(V3_PAddr(pde), 1);
+       }
+
+       V3_FreePages(V3_PAddr(pdpe), 1);
+    }
+
+    V3_FreePages(V3_PAddr(pml4), 1);
+}
+
+
+
+static int deinit_ept(struct guest_info * core) {
+    ept_pml4_t    *pml;
+
+    pml = (ept_pml4_t *)CR3_TO_PML4E64_VA(core->direct_map_pt);
+
+    delete_page_tables_ept64(pml);
+    core->direct_map_pt = 0;
 
     return 0;
 }