X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_shadow_paging_32.h;h=68766490cbcd09caccc77907f3610f0b25dfb8dc;hb=3a47eb153e415d718e5d5601b79767b7335a149f;hp=7e0106a7990710f58a46d7be4f41c3e6ca44cb7a;hpb=53f181096ad02cde9f79e30e2238ddad43ede574;p=palacios.git diff --git a/palacios/src/palacios/vmm_shadow_paging_32.h b/palacios/src/palacios/vmm_shadow_paging_32.h index 7e0106a..6876649 100644 --- a/palacios/src/palacios/vmm_shadow_paging_32.h +++ b/palacios/src/palacios/vmm_shadow_paging_32.h @@ -51,7 +51,7 @@ static int cache_page_tables_32(struct guest_info * info, addr_t pde) { // We assume that shdw_pg_state.guest_cr3 is pointing to the page tables we want to activate // We also assume that the CPU mode has not changed during this page table transition -static int activate_shadow_pt_32(struct guest_info * info) { +static inline int activate_shadow_pt_32(struct guest_info * info) { struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3); struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3); int cached = 0; @@ -63,15 +63,12 @@ static int activate_shadow_pt_32(struct guest_info * info) { PrintError("CR3 Cache failed\n"); 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(); + struct shadow_page_data * shdw_page = create_new_shadow_pt(info); + + shdw_page->cr3 = shdw_page->page_pa; - 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 ); + shadow_cr3->pdt_base_addr = PAGE_BASE_ADDR(shdw_page->page_pa); + 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"); } @@ -100,7 +97,7 @@ static int handle_shadow_pte32_fault(struct guest_info * info, pte32_t * guest_pt); -static int handle_shadow_pagefault_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { +static inline int handle_shadow_pagefault_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { pde32_t * guest_pd = NULL; pde32_t * shadow_pd = CR3_TO_PDE32_VA(info->ctrl_regs.cr3); addr_t guest_cr3 = CR3_TO_PDE32_PA(info->shdw_pg_state.guest_cr3); @@ -136,7 +133,8 @@ static int handle_shadow_pagefault_32(struct guest_info * info, addr_t fault_add if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) { - pte32_t * shadow_pt = (pte32_t *)create_new_shadow_pt(); + struct shadow_page_data * shdw_page = create_new_shadow_pt(info); + pte32_t * shadow_pt = (pte32_t *)V3_VAddr((void *)shdw_page->page_pa); shadow_pde->present = 1; shadow_pde->user_page = guest_pde->user_page; @@ -173,6 +171,12 @@ static int handle_shadow_pagefault_32(struct guest_info * info, addr_t fault_add // ?? 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) @@ -204,8 +208,7 @@ static int handle_shadow_pagefault_32(struct guest_info * info, addr_t fault_add } } else if ((shadow_pde_access == PT_ACCESS_WRITE_ERROR) && - (guest_pde->large_page == 1) && - (((pde32_4MB_t *)guest_pde)->dirty == 0)) + (guest_pde->large_page == 1)) { // // Page Directory Entry marked read-only @@ -260,6 +263,7 @@ static int handle_large_pagefault_32(struct guest_info * info, pt_access_status_t shadow_pte_access = v3_can_access_pte32(shadow_pt, fault_addr, error_code); pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]); addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_4MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_4MB(fault_addr); + struct shadow_page_state * state = &(info->shdw_pg_state); struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info, guest_fault_pa); @@ -285,7 +289,6 @@ static int handle_large_pagefault_32(struct guest_info * info, if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) { - struct shadow_page_state * state = &(info->shdw_pg_state); addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_fault_pa); shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa); @@ -302,7 +305,6 @@ static int handle_large_pagefault_32(struct guest_info * info, if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_fault_pa)) != NULL) { // Check if the entry is a page table... PrintDebug("Marking page as Guest Page Table (large page)\n"); - shadow_pte->vmm_info = PT32_GUEST_PT; shadow_pte->writable = 0; } else if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) { shadow_pte->writable = 0; @@ -333,7 +335,10 @@ static int handle_large_pagefault_32(struct guest_info * info, PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } - } else if (shadow_pte->vmm_info == PT32_GUEST_PT) { + } + + + if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_fault_pa)) != NULL) { struct shadow_page_state * state = &(info->shdw_pg_state); PrintDebug("Write operation on Guest PAge Table Page (large page)\n"); state->cached_cr3 = 0; @@ -367,6 +372,7 @@ static int handle_shadow_pte32_fault(struct guest_info * info, pte32_t * guest_pte = (pte32_t *)&(guest_pt[PTE32_INDEX(fault_addr)]);; pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]); addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) + PAGE_OFFSET(fault_addr); + struct shadow_page_state * state = &(info->shdw_pg_state); struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info, guest_pa); @@ -398,6 +404,7 @@ static int handle_shadow_pte32_fault(struct guest_info * info, inject_guest_pf(info, fault_addr, error_code); return 0; } + if (shadow_pte_access == PT_ACCESS_OK) { @@ -414,7 +421,6 @@ static int handle_shadow_pte32_fault(struct guest_info * info, if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) { - struct shadow_page_state * state = &(info->shdw_pg_state); addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_pa); shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa); @@ -430,28 +436,27 @@ static int handle_shadow_pte32_fault(struct guest_info * info, guest_pte->accessed = 1; - if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_pa)) != NULL) { - // Check if the entry is a page table... - PrintDebug("Marking page as Guest Page Table %d\n", shadow_pte->writable); - shadow_pte->vmm_info = PT32_GUEST_PT; - } - - if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) { - shadow_pte->writable = 0; - } else if (guest_pte->dirty == 1) { + if (guest_pte->dirty == 1) { shadow_pte->writable = guest_pte->writable; } else if ((guest_pte->dirty == 0) && (error_code.write == 1)) { shadow_pte->writable = guest_pte->writable; guest_pte->dirty = 1; - - if (shadow_pte->vmm_info == PT32_GUEST_PT) { - // Well that was quick... - struct shadow_page_state * state = &(info->shdw_pg_state); - PrintDebug("Immediate Write operation on Guest PAge Table Page\n"); + } else if ((guest_pte->dirty == 0) && (error_code.write == 0)) { + shadow_pte->writable = 0; + } + + // dirty flag has been set, check if its in the cache + if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_pa)) != NULL) { + if (error_code.write == 1) { state->cached_cr3 = 0; + shadow_pte->writable = guest_pte->writable; + } else { + shadow_pte->writable = 0; } + } - } else if ((guest_pte->dirty == 0) && (error_code.write == 0)) { // was = + // Write hooks trump all, and are set Read Only + if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) { shadow_pte->writable = 0; } @@ -476,7 +481,7 @@ static int handle_shadow_pte32_fault(struct guest_info * info, shadow_pte->writable = guest_pte->writable; } - if (shadow_pte->vmm_info == PT32_GUEST_PT) { + if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_pa)) != NULL) { struct shadow_page_state * state = &(info->shdw_pg_state); PrintDebug("Write operation on Guest PAge Table Page\n"); state->cached_cr3 = 0; @@ -495,3 +500,35 @@ static int handle_shadow_pte32_fault(struct guest_info * info, PrintDebug("Returning end of function\n"); return 0; } + + + +/* If we start to optimize we should look up the guest pages in the cache... */ +static inline int handle_shadow_invlpg_32(struct guest_info * info, addr_t vaddr) { + pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32_VA(info->ctrl_regs.cr3); + pde32_t * shadow_pde = (pde32_t *)&shadow_pd[PDE32_INDEX(vaddr)]; + + addr_t guest_cr3 = CR3_TO_PDE32_PA(info->shdw_pg_state.guest_cr3); + pde32_t * guest_pd = NULL; + pde32_t * guest_pde; + + if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) { + PrintError("Invalid Guest PDE Address: 0x%p\n", (void *)guest_cr3); + return -1; + } + + guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(vaddr)]); + + if (guest_pde->large_page == 1) { + shadow_pde->present = 0; + PrintDebug("Invalidating Large Page\n"); + } else if (shadow_pde->present == 1) { + pte32_t * shadow_pt = (pte32_t *)(addr_t)BASE_TO_PAGE_ADDR_4KB(shadow_pde->pt_base_addr); + pte32_t * shadow_pte = (pte32_t *) V3_VAddr( (void*) &shadow_pt[PTE32_INDEX(vaddr)] ); + + PrintDebug("Setting not present\n"); + + shadow_pte->present = 0; + } + return 0; +}