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 64 bit paging for paged real mode
Jack Lange [Wed, 22 Oct 2008 23:28:20 +0000 (18:28 -0500)]
palacios/include/palacios/vmm_paging.h
palacios/src/palacios/svm.c
palacios/src/palacios/vm_guest.c
palacios/src/palacios/vmm_paging.c

index 1721760..4831525 100644 (file)
@@ -110,6 +110,12 @@ the host state in the vmcs before entering the guest.
 #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)
+
 #define PT32_PAGE_ADDR(x)   (((uint_t)x) & 0xfffff000)
 #define PT32_PAGE_OFFSET(x) (((uint_t)x) & 0xfff)
 #define PT32_PAGE_POWER 12
@@ -211,15 +217,14 @@ typedef struct pte32 {
 typedef struct pml4e64 {
   uint_t present        : 1;
   uint_t writable       : 1;
-  uint_t user           : 1;
-  uint_t pwt            : 1;
-  uint_t pcd            : 1;
+  uint_t user_page           : 1;
+  uint_t write_through  : 1;
+  uint_t cache_disable  : 1;
   uint_t accessed       : 1;
   uint_t reserved       : 1;
   uint_t zero           : 2;
   uint_t vmm_info       : 3;
-  uint_t pdp_base_addr_lo : 20;
-  uint_t pdp_base_addr_hi : 20;
+  ullong_t pdp_base_addr : 40;
   uint_t available      : 11;
   uint_t no_execute     : 1;
 } pml4e64_t;
@@ -228,16 +233,15 @@ typedef struct pml4e64 {
 typedef struct pdpe64 {
   uint_t present        : 1;
   uint_t writable       : 1;
-  uint_t user           : 1;
-  uint_t pwt            : 1;
-  uint_t pcd            : 1;
+  uint_t user_page           : 1;
+  uint_t write_through  : 1;
+  uint_t cache_disable  : 1;
   uint_t accessed       : 1;
   uint_t reserved       : 1;
-  uint_t large_pages    : 1;
+  uint_t large_page    : 1;
   uint_t zero           : 1;
   uint_t vmm_info       : 3;
-  uint_t pd_base_addr_lo : 20;
-  uint_t pd_base_addr_hi : 20;
+  ullong_t pd_base_addr : 40;
   uint_t available      : 11;
   uint_t no_execute     : 1;
 } pdpe64_t;
@@ -247,28 +251,32 @@ typedef struct pdpe64 {
 
 typedef struct pde64 {
   uint_t present         : 1;
-  uint_t flags           : 4;
+  uint_t writable        : 1;
+  uint_t user_page       : 1;
+  uint_t write_through   : 1;
+  uint_t cache_disable   : 1;
   uint_t accessed        : 1;
   uint_t reserved        : 1;
-  uint_t large_pages     : 1;
+  uint_t large_page     : 1;
   uint_t reserved2       : 1;
   uint_t vmm_info        : 3;
-  uint_t pt_base_addr_lo    : 20;
-  uint_t pt_base_addr_hi : 20;
+  ullong_t pt_base_addr  : 40;
   uint_t available       : 11;
   uint_t no_execute      : 1;
 } pde64_t;
 
 typedef struct pte64 {
   uint_t present         : 1;
-  uint_t flags           : 4;
+  uint_t writable        : 1;
+  uint_t user_page       : 1;
+  uint_t write_through   : 1;
+  uint_t cache_disable   : 1;
   uint_t accessed        : 1;
   uint_t dirty           : 1;
   uint_t pte_attr        : 1;
   uint_t global_page     : 1;
   uint_t vmm_info        : 3;
-  uint_t page_base_addr_lo  : 20;
-  uint_t page_base_addr_hi : 20;
+  ullong_t page_base_addr : 40;
   uint_t available       : 11;
   uint_t no_execute      : 1;
 } pte64_t;
@@ -309,7 +317,7 @@ pt_access_status_t can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t acces
 struct guest_info;
 
 pde32_t * create_passthrough_pde32_pts(struct guest_info * guest_info);
-
+pml4e64_t * create_passthrough_pts_64(struct guest_info * info);
 
 
 
@@ -324,6 +332,7 @@ void PrintPT32(addr_t starting_address, pte32_t * pte);
 void PrintPD32(pde32_t * pde);
 void PrintPTE32(addr_t virtual_address, pte32_t * pte);
 void PrintPDE32(addr_t virtual_address, pde32_t * pde);
+void PrintPTE64(addr_t virtual_address, pte64_t * pte);
 
 #endif // !__V3VEE__
 
index 77653af..c9d69ef 100644 (file)
@@ -213,7 +213,9 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) {
 
   if (vm_info->shdw_pg_mode == SHADOW_PAGING) {
     PrintDebug("Creating initial shadow page table\n");
-    vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pde32_pts(vm_info));
+    //    vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pde32_pts(vm_info));
+    /* Testing 64 bit page tables for long paged real mode guests */
+    vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(vm_info));
 
     //vm_info->shdw_pg_state.shadow_cr3 |= (vm_info->direct_map_pt & ~0xfff);
     vm_info->shdw_pg_state.shadow_cr3 = 0;
index 5b7c39f..ef025fa 100644 (file)
@@ -23,6 +23,7 @@
 #include <palacios/vm_guest.h>
 #include <palacios/vmm_ctrl_regs.h>
 #include <palacios/vmm.h>
+#include <palacios/vmcb.h>
 
 
 v3_vm_cpu_mode_t v3_get_cpu_mode(struct guest_info * info) {
@@ -102,6 +103,7 @@ void v3_print_ctrl_regs(struct guest_info * info) {
   int i = 0;
   v3_reg_t * reg_ptr;
   char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", NULL};
+  vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(info->vmm_data);
 
   reg_ptr= (v3_reg_t *)regs;
 
@@ -110,6 +112,9 @@ void v3_print_ctrl_regs(struct guest_info * info) {
   for (i = 0; reg_names[i] != NULL; i++) {
     PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)reg_ptr[i]);  
   }
+
+  PrintDebug("\tEFER=0x%p\n", (void*)(guest_state->efer));
+
 }
 
 
index 429c6d2..0832077 100644 (file)
@@ -26,6 +26,9 @@
 
 
 
+  
+
+
 void delete_page_tables_pde32(pde32_t * pde) {
   int i;//, j;
 
@@ -36,7 +39,8 @@ void delete_page_tables_pde32(pde32_t * pde) {
   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) {
     if (pde[i].present) {
       // We double cast, first to an addr_t to handle 64 bit issues, then to the pointer
-      pte32_t * pte = (pte32_t *)((addr_t)(pde[i].pt_base_addr << PAGE_POWER));
+      PrintDebug("PTE base addr %x \n", pde[i].pt_base_addr);
+      pte32_t * pte = (pte32_t *)((addr_t)(uint_t)(pde[i].pt_base_addr << PAGE_POWER));
 
       /*
        for (j = 0; (j < MAX_PTE32_ENTRIES); j++) {
@@ -45,12 +49,12 @@ void delete_page_tables_pde32(pde32_t * pde) {
        }
        }
       */
-      //PrintDebug("Deleting PTE %d (%x)\n", i, pte);
+      PrintDebug("Deleting PTE %d (%p)\n", i, pte);
       V3_FreePage(pte);
     }
   }
 
-  //  PrintDebug("Deleting PDE (%x)\n", pde);
+  PrintDebug("Deleting PDE (%p)\n", pde);
   V3_FreePage(V3_PAddr(pde));
 }
 
@@ -166,7 +170,7 @@ pt_access_status_t can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t acces
  * If there are any gaps in the layout, we add them as unmapped pages
  */
 pde32_t * create_passthrough_pde32_pts(struct guest_info * guest_info) {
-  ullong_t current_page_addr = 0;
+  addr_t current_page_addr = 0;
   int i, j;
   struct shadow_map * map = &(guest_info->mem_map);
 
@@ -260,6 +264,180 @@ pde32_t * create_passthrough_pde32_pts(struct guest_info * guest_info) {
 
 
 
+pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
+  addr_t current_page_addr = 0;
+  int i, j, k, m;
+  struct shadow_map * map = &(info->mem_map);
+  
+  pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
+
+  for (i = 0; i < 1; i++) {
+    int pdpe_present = 0;
+    pdpe64_t * pdpe = V3_VAddr(V3_AllocPages(1));
+
+    for (j = 0; j < 1; j++) {
+      int pde_present = 0;
+      pde64_t * pde = V3_VAddr(V3_AllocPages(1));
+
+      for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
+       int pte_present = 0;
+       pte64_t * pte = V3_VAddr(V3_AllocPages(1));
+
+
+       for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
+         struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
+         
+
+         
+         if (!region || 
+             (region->host_type == HOST_REGION_HOOK) || 
+             (region->host_type == HOST_REGION_UNALLOCATED) || 
+             (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
+             (region->host_type == HOST_REGION_REMOTE) ||
+             (region->host_type == HOST_REGION_SWAPPED)) {
+           pte[m].present = 0;
+           pte[m].writable = 0;
+           pte[m].user_page = 0;
+           pte[m].write_through = 0;
+           pte[m].cache_disable = 0;
+           pte[m].accessed = 0;
+           pte[m].dirty = 0;
+           pte[m].pte_attr = 0;
+           pte[m].global_page = 0;
+           pte[m].vmm_info = 0;
+           pte[m].page_base_addr = 0;
+         } else {
+           addr_t host_addr;
+           pte[m].present = 1;
+           pte[m].writable = 1;
+           pte[m].user_page = 1;
+           pte[m].write_through = 0;
+           pte[m].cache_disable = 0;
+           pte[m].accessed = 0;
+           pte[m].dirty = 0;
+           pte[m].pte_attr = 0;
+           pte[m].global_page = 0;
+           pte[m].vmm_info = 0;
+           
+           if (guest_pa_to_host_pa(info, current_page_addr, &host_addr) == -1) {
+             // BIG ERROR
+             // PANIC
+             return NULL;
+           }
+
+           pte[m].page_base_addr = PTE64_BASE_ADDR(host_addr);
+
+           //PrintPTE64(current_page_addr, &(pte[m]));
+
+           pte_present = 1;      
+         }
+
+
+
+
+         current_page_addr += PAGE_SIZE;
+       }
+       
+       if (pte_present == 0) {
+         V3_FreePage(V3_PAddr(pte));
+
+         pde[k].present = 0;
+         pde[k].writable = 0;
+         pde[k].user_page = 0;
+         pde[k].write_through = 0;
+         pde[k].cache_disable = 0;
+         pde[k].accessed = 0;
+         pde[k].reserved = 0;
+         pde[k].large_page = 0;
+         //pde[k].global_page = 0;
+         pde[k].vmm_info = 0;
+         pde[k].pt_base_addr = 0;
+       } else {
+         pde[k].present = 1;
+         pde[k].writable = 1;
+         pde[k].user_page = 1;
+         pde[k].write_through = 0;
+         pde[k].cache_disable = 0;
+         pde[k].accessed = 0;
+         pde[k].reserved = 0;
+         pde[k].large_page = 0;
+         //pde[k].global_page = 0;
+         pde[k].vmm_info = 0;
+         pde[k].pt_base_addr = PAGE_ALIGNED_ADDR((addr_t)V3_PAddr(pte));
+
+         pde_present = 1;
+       }
+      }
+
+      if (pde_present == 0) {
+       V3_FreePage(V3_PAddr(pde));
+       
+       pdpe[j].present = 0;
+       pdpe[j].writable = 0;
+       pdpe[j].user_page = 0;
+       pdpe[j].write_through = 0;
+       pdpe[j].cache_disable = 0;
+       pdpe[j].accessed = 0;
+       pdpe[j].reserved = 0;
+       pdpe[j].large_page = 0;
+       //pdpe[j].global_page = 0;
+       pdpe[j].vmm_info = 0;
+       pdpe[j].pd_base_addr = 0;
+      } else {
+       pdpe[j].present = 1;
+       pdpe[j].writable = 1;
+       pdpe[j].user_page = 1;
+       pdpe[j].write_through = 0;
+       pdpe[j].cache_disable = 0;
+       pdpe[j].accessed = 0;
+       pdpe[j].reserved = 0;
+       pdpe[j].large_page = 0;
+       //pdpe[j].global_page = 0;
+       pdpe[j].vmm_info = 0;
+       pdpe[j].pd_base_addr = PAGE_ALIGNED_ADDR((addr_t)V3_PAddr(pde));
+
+
+       pdpe_present = 1;
+      }
+
+    }
+
+    PrintDebug("PML index=%d\n", i);
+
+    if (pdpe_present == 0) {
+      V3_FreePage(V3_PAddr(pdpe));
+      
+      pml[i].present = 0;
+      pml[i].writable = 0;
+      pml[i].user_page = 0;
+      pml[i].write_through = 0;
+      pml[i].cache_disable = 0;
+      pml[i].accessed = 0;
+      pml[i].reserved = 0;
+      //pml[i].large_page = 0;
+      //pml[i].global_page = 0;
+      pml[i].vmm_info = 0;
+      pml[i].pdp_base_addr = 0;
+    } else {
+      pml[i].present = 1;
+      pml[i].writable = 1;
+      pml[i].user_page = 1;
+      pml[i].write_through = 0;
+      pml[i].cache_disable = 0;
+      pml[i].accessed = 0;
+      pml[i].reserved = 0;
+      //pml[i].large_page = 0;
+      //pml[i].global_page = 0;
+      pml[i].vmm_info = 0;
+      pml[i].pdp_base_addr = PAGE_ALIGNED_ADDR((addr_t)V3_PAddr(pdpe));
+    }
+  }
+
+  return pml;
+}
+
+
+
 
 
 void PrintPDE32(addr_t virtual_address, pde32_t * pde)
@@ -278,6 +456,7 @@ void PrintPDE32(addr_t virtual_address, pde32_t * pde)
             pde->global_page,
             pde->vmm_info);
 }
+
   
 void PrintPTE32(addr_t virtual_address, pte32_t * pte)
 {
@@ -297,6 +476,45 @@ void PrintPTE32(addr_t virtual_address, pte32_t * pte)
 }
 
 
+void PrintPDE64(addr_t virtual_address, pde64_t * pde)
+{
+  PrintDebug("PDE64 %p -> %p : present=%x, writable=%x, user=%x, wt=%x, cd=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n",
+            (void *)virtual_address,
+            (void *)(addr_t) (pde->pt_base_addr << PAGE_POWER),
+            pde->present,
+            pde->writable,
+            pde->user_page, 
+            pde->write_through,
+            pde->cache_disable,
+            pde->accessed,
+            pde->reserved,
+            pde->large_page,
+            0,//pde->global_page,
+            pde->vmm_info);
+}
+
+  
+void PrintPTE64(addr_t virtual_address, pte64_t * pte)
+{
+  PrintDebug("PTE64 %p -> %p : present=%x, writable=%x, user=%x, wt=%x, cd=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, vmm_info=%x\n",
+            (void *)virtual_address,
+            (void*)(addr_t)(pte->page_base_addr << PAGE_POWER),
+            pte->present,
+            pte->writable,
+            pte->user_page,
+            pte->write_through,
+            pte->cache_disable,
+            pte->accessed,
+            pte->dirty,
+            pte->pte_attr,
+            pte->global_page,
+            pte->vmm_info);
+}
+
+  
+
+
+
 
 void PrintPD32(pde32_t * pde)
 {