From: Jack Lange Date: Wed, 22 Oct 2008 23:28:20 +0000 (-0500) Subject: added 64 bit paging for paged real mode X-Git-Tag: 1.0^2~3 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=0c51b09942d51a3b355728526333ad3f3895131d added 64 bit paging for paged real mode --- diff --git a/palacios/include/palacios/vmm_paging.h b/palacios/include/palacios/vmm_paging.h index 1721760..4831525 100644 --- a/palacios/include/palacios/vmm_paging.h +++ b/palacios/include/palacios/vmm_paging.h @@ -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__ diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 77653af..c9d69ef 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -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; diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c index 5b7c39f..ef025fa 100644 --- a/palacios/src/palacios/vm_guest.c +++ b/palacios/src/palacios/vm_guest.c @@ -23,6 +23,7 @@ #include #include #include +#include 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)); + } diff --git a/palacios/src/palacios/vmm_paging.c b/palacios/src/palacios/vmm_paging.c index 429c6d2..0832077 100644 --- a/palacios/src/palacios/vmm_paging.c +++ b/palacios/src/palacios/vmm_paging.c @@ -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) {