From: Jack Lange Date: Tue, 3 Feb 2009 22:19:08 +0000 (-0600) Subject: starting work on 64 bit shadow paging X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=e4c0bf63a6e95019f79f7ff9915fd5d360d2c31a starting work on 64 bit shadow paging --- diff --git a/palacios/include/palacios/vmm_shadow_paging.h b/palacios/include/palacios/vmm_shadow_paging.h index da9c76d..84dee84 100644 --- a/palacios/include/palacios/vmm_shadow_paging.h +++ b/palacios/include/palacios/vmm_shadow_paging.h @@ -26,6 +26,7 @@ #include #include #include +#include struct shadow_page_state { @@ -34,6 +35,8 @@ struct shadow_page_state { v3_reg_t guest_cr3; v3_reg_t guest_cr0; + // list of allocated shadow pages + struct list_head page_list; /* SOON TO BE DEPRECATED */ // Hash table that contains a mapping of guest pte addresses to host pte addresses @@ -53,7 +56,6 @@ struct guest_info; int v3_init_shadow_page_state(struct guest_info * info); - int v3_handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code); int v3_handle_shadow_invlpg(struct guest_info * info); diff --git a/palacios/src/palacios/vmm_shadow_paging.c b/palacios/src/palacios/vmm_shadow_paging.c index 611e0ea..e6bad8a 100644 --- a/palacios/src/palacios/vmm_shadow_paging.c +++ b/palacios/src/palacios/vmm_shadow_paging.c @@ -39,34 +39,14 @@ ***/ -struct guest_table { - addr_t cr3; - struct list_head link; -}; - - -struct backptr { - addr_t ptr; - struct list_head link; -}; - - struct shadow_page_data { - addr_t ptr; - addr_t guest_addr; - - struct list_head backptrs; - struct list_head guest_tables; + v3_reg_t cr3; + addr_t page_pa; + + struct list_head page_list_node; }; - - -//DEFINE_HASHTABLE_INSERT(add_cr3_to_cache, addr_t, struct hashtable *); -//DEFINE_HASHTABLE_SEARCH(find_cr3_in_cache, addr_t, struct hashtable *); -//DEFINE_HASHTABLE_REMOVE(del_cr3_from_cache, addr_t, struct hashtable *, 0); - - DEFINE_HASHTABLE_INSERT(add_pte_map, addr_t, addr_t); DEFINE_HASHTABLE_SEARCH(find_pte_map, addr_t, addr_t); //DEFINE_HASHTABLE_REMOVE(del_pte_map, addr_t, addr_t, 0); @@ -81,7 +61,7 @@ static int pte_equals(addr_t key1, addr_t key2) { return (key1 == key2); } -static addr_t create_new_shadow_pt(); +static addr_t create_new_shadow_pt(struct guest_info * info); static void inject_guest_pf(struct guest_info * info, addr_t fault_addr, pf_error_t error_code); static int is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shadow_access); @@ -98,6 +78,8 @@ int v3_init_shadow_page_state(struct guest_info * info) { state->guest_cr3 = 0; state->guest_cr0 = 0; + INIT_LIST_HEAD(&(state->page_list)); + state->cached_ptes = NULL; state->cached_cr3 = 0; @@ -226,13 +208,38 @@ int v3_handle_shadow_invlpg(struct guest_info * info) { -static addr_t create_new_shadow_pt() { - void * host_pde = 0; +static addr_t create_new_shadow_pt(struct guest_info * info) { + struct shadow_page_state * state = &(info->shdw_pg_state); + v3_reg_t cur_cr3 = info->ctrl_regs.cr3; + struct shadow_page_data * page_tail = NULL; + addr_t shdw_page = 0; + + if (!list_empty(&(state->page_list))) { + page_tail = list_tail_entry(&(state->page_list), struct shadow_page_data, page_list_node); + + if (page_tail->cr3 != cur_cr3) { + page_tail->cr3 = cur_cr3; + list_move(&(page_tail->page_list_node), &(state->page_list)); + + memset(V3_VAddr((void *)(page_tail->page_pa)), 0, PAGE_SIZE_4KB); + PrintDebug("Reusing old shadow Page\n"); + + return (addr_t)V3_VAddr((void *)(page_tail->page_pa)); + } + } + + // else + + page_tail = (struct shadow_page_data *)V3_Malloc(sizeof(struct shadow_page_data)); + page_tail->page_pa = (addr_t)V3_AllocPages(1); - host_pde = V3_VAddr(V3_AllocPages(1)); - memset(host_pde, 0, PAGE_SIZE); + page_tail->cr3 = cur_cr3; + list_add(&(page_tail->page_list_node), &(state->page_list)); - return (addr_t)host_pde; + shdw_page = (addr_t)V3_VAddr((void *)(page_tail->page_pa)); + memset((void *)shdw_page, 0, PAGE_SIZE_4KB); + + return shdw_page; } @@ -248,9 +255,9 @@ static void inject_guest_pf(struct guest_info * info, addr_t fault_addr, pf_erro static int is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shadow_access) { /* basically the reasoning is that there can be multiple reasons for a page fault: - If there is a permissions failure for a page present in the guest _BUT_ - the reason for the fault was that the page is not present in the shadow, - _THEN_ we have to map the shadow page in and reexecute, this will generate + If there is a permissions failure for a page present in the guest _BUT_ + the reason for the fault was that the page is not present in the shadow, + _THEN_ we have to map the shadow page in and reexecute, this will generate a permissions fault which is _THEN_ valid to send to the guest _UNLESS_ both the guest and shadow have marked the page as not present @@ -258,7 +265,7 @@ static int is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shado */ if (guest_access != PT_ACCESS_OK) { // Guest Access Error - + if ((shadow_access != PT_ACCESS_NOT_PRESENT) && (guest_access != PT_ACCESS_NOT_PRESENT)) { // aka (guest permission error) @@ -266,7 +273,7 @@ static int is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shado } if ((shadow_access == PT_ACCESS_NOT_PRESENT) && - (guest_access == PT_ACCESS_NOT_PRESENT)) { + (guest_access == PT_ACCESS_NOT_PRESENT)) { // Page tables completely blank, handle guest first return 1; } diff --git a/palacios/src/palacios/vmm_shadow_paging_32.h b/palacios/src/palacios/vmm_shadow_paging_32.h index 749d371..6acd920 100644 --- a/palacios/src/palacios/vmm_shadow_paging_32.h +++ b/palacios/src/palacios/vmm_shadow_paging_32.h @@ -64,14 +64,11 @@ static inline int activate_shadow_pt_32(struct guest_info * info) { return -1; } else if (cached == 0) { addr_t shadow_pt; - - PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 ); - delete_page_tables_32(CR3_TO_PDE32_VA(*(uint_t*)shadow_cr3)); - - shadow_pt = create_new_shadow_pt(); + + shadow_pt = create_new_shadow_pt(info); shadow_cr3->pdt_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PAGE_BASE_ADDR(shadow_pt)); - PrintDebug( "Created new shadow page table %p\n", (void *)(addr_t)shadow_cr3->pdt_base_addr ); + PrintDebug( "Created new shadow page table %p\n", (void *)BASE_TO_PAGE_ADDR(shadow_cr3->pdt_base_addr)); } else { PrintDebug("Reusing cached shadow Page table\n"); } @@ -136,7 +133,7 @@ static inline int handle_shadow_pagefault_32(struct guest_info * info, addr_t fa if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) { - pte32_t * shadow_pt = (pte32_t *)create_new_shadow_pt(); + pte32_t * shadow_pt = (pte32_t *)create_new_shadow_pt(info); shadow_pde->present = 1; shadow_pde->user_page = guest_pde->user_page; @@ -173,6 +170,12 @@ static inline int handle_shadow_pagefault_32(struct guest_info * info, addr_t fa // ?? What if guest pde is dirty a this point? ((pde32_4MB_t *)guest_pde)->dirty = 0; shadow_pde->writable = 0; + + if (handle_large_pagefault_32(info, fault_addr, error_code, shadow_pt, (pde32_4MB_t *)guest_pde) == -1) { + PrintError("Error handling large pagefault\n"); + return -1; + } + } } else if (shadow_pde_access == PT_ACCESS_OK) diff --git a/palacios/src/palacios/vmm_shadow_paging_64.h b/palacios/src/palacios/vmm_shadow_paging_64.h index fbd3f3f..5ed98b0 100644 --- a/palacios/src/palacios/vmm_shadow_paging_64.h +++ b/palacios/src/palacios/vmm_shadow_paging_64.h @@ -1,8 +1,19 @@ static inline int activate_shadow_pt_64(struct guest_info * info) { - // struct cr3_64 * shadow_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3); - - return -1; + struct cr3_64 * shadow_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3); + struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3); + addr_t shadow_pt = 0; + + shadow_pt = create_new_shadow_pt(info); + + shadow_cr3->pml4t_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PAGE_BASE_ADDR_4KB(shadow_pt)); + PrintDebug("Creating new 64 bit shadow page table %p\n", (void *)BASE_TO_PAGE_ADDR(shadow_cr3->pml4t_base_addr)) + + + shadow_cr3->pwt = guest_cr3->pwt; + shadow_cr3->pcd = guest_cr3->pcd; + + return 0; } @@ -17,20 +28,30 @@ static inline int activate_shadow_pt_64(struct guest_info * info) { * * * * */ +/* +static int handle_2MB_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code, + pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde); -static inline int handle_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { - pt_access_status_t guest_access; - pt_access_status_t shadow_access; - int ret; - PrintDebug("64 bit shadow page fault\n"); - - ret = v3_check_guest_pt_32(info, info->shdw_pg_state.guest_cr3, fault_addr, error_code, &guest_access); +static int handle_pte_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code, + pte64_t * shadow_pt, pte64_t * guest_pt); - PrintDebug("Guest Access Check: %d (access=%d)\n", ret, guest_access); +static int handle_pde_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code, + pde64_t * shadow_pd, pde64_t * guest_pd); - ret = v3_check_host_pt_32(info->ctrl_regs.cr3, fault_addr, error_code, &shadow_access); +static int handle_pdpe_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code, + pdpe64_t * shadow_pdp, pdpe64_t * guest_pdp); +*/ - PrintDebug("Shadow Access Check: %d (access=%d)\n", ret, shadow_access); +static inline int handle_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { + /* pml4e64_t * guest_pml = NULL; + pml4e64_t * shadow_pml = CR3_TO_PML4E64_VA(info->ctrl_regs.cr3); + addr_t guest_cr3 = CR3_TO_PML4E64_PA(info->shdw_pg_state.guest_cr3); + pt_access_status_t guest_pml_access; + pt_access_status_t shadow_pml_access; + pml4e64_t * guest_pmle = NULL; + // pml4e64_t * shadow_pmle = ; + */ + PrintError("64 bit shadow paging not implemented\n");