diff --git a/hypervisor/arch/x86/ept.c b/hypervisor/arch/x86/ept.c index 18c2dcaa1..3c46dda6e 100644 --- a/hypervisor/arch/x86/ept.c +++ b/hypervisor/arch/x86/ept.c @@ -120,18 +120,13 @@ void destroy_ept(struct vm *vm) uint64_t _gpa2hpa(struct vm *vm, uint64_t gpa, uint32_t *size) { uint64_t hpa = 0UL; - uint32_t pg_size = 0U; - struct entry_params entry; - struct map_params map_params; + uint64_t *pgentry, pg_size = 0UL; - map_params.page_table_type = PTT_EPT; - map_params.pml4_base = vm->arch_vm.nworld_eptp; - map_params.pml4_inverted = vm->arch_vm.m2p; - obtain_last_page_table_entry(&map_params, &entry, (void *)gpa, true); - if (entry.entry_present == PT_PRESENT) { - hpa = ((entry.entry_val & (~(entry.page_size - 1))) - | (gpa & (entry.page_size - 1))); - pg_size = entry.page_size; + pgentry = lookup_address((uint64_t *)vm->arch_vm.nworld_eptp, + gpa, &pg_size, PTT_EPT); + if (pgentry != NULL) { + hpa = ((*pgentry & (~(pg_size - 1UL))) + | (gpa & (pg_size - 1UL))); pr_dbg("GPA2HPA: 0x%llx->0x%llx", gpa, hpa); } else { pr_err("VM %d GPA2HPA: failed for gpa 0x%llx", @@ -139,7 +134,7 @@ uint64_t _gpa2hpa(struct vm *vm, uint64_t gpa, uint32_t *size) } if (size != NULL) { - *size = pg_size; + *size = (uint32_t)pg_size; } return hpa; @@ -153,23 +148,17 @@ uint64_t gpa2hpa(struct vm *vm, uint64_t gpa) uint64_t hpa2gpa(struct vm *vm, uint64_t hpa) { - struct entry_params entry; - struct map_params map_params; + uint64_t *pgentry, pg_size = 0UL; - map_params.page_table_type = PTT_EPT; - map_params.pml4_base = vm->arch_vm.nworld_eptp; - map_params.pml4_inverted = vm->arch_vm.m2p; - - obtain_last_page_table_entry(&map_params, &entry, - (void *)hpa, false); - - if (entry.entry_present == PT_NOT_PRESENT) { + pgentry = lookup_address((uint64_t *)vm->arch_vm.m2p, + hpa, &pg_size, PTT_EPT); + if (pgentry == NULL) { pr_err("VM %d hpa2gpa: failed for hpa 0x%llx", vm->attr.boot_idx, hpa); ASSERT(false, "hpa2gpa not found"); } - return ((entry.entry_val & (~(entry.page_size - 1))) - | (hpa & (entry.page_size - 1))); + return ((*pgentry & (~(pg_size - 1UL))) + | (hpa & (pg_size - 1UL))); } bool is_ept_supported(void) diff --git a/hypervisor/arch/x86/pagetable.c b/hypervisor/arch/x86/pagetable.c index ade9b0722..880671b5e 100644 --- a/hypervisor/arch/x86/pagetable.c +++ b/hypervisor/arch/x86/pagetable.c @@ -452,3 +452,42 @@ int mmu_add(uint64_t *pml4_page, uint64_t paddr_base, return 0; } + +uint64_t *lookup_address(uint64_t *pml4_page, + uint64_t addr, uint64_t *pg_size, enum _page_table_type ptt) +{ + uint64_t *pml4e, *pdpte, *pde, *pte; + + if ((pml4_page == NULL) || (pg_size == NULL)) { + return NULL; + } + + pml4e = pml4e_offset(pml4_page, addr); + if (pgentry_present(ptt, *pml4e) == 0UL) { + return NULL; + } + + pdpte = pdpte_offset(pml4e, addr); + if (pgentry_present(ptt, *pdpte) == 0UL) { + return NULL; + } else if (pdpte_large(*pdpte) != 0UL) { + *pg_size = PDPTE_SIZE; + return pdpte; + } + + pde = pde_offset(pdpte, addr); + if (pgentry_present(ptt, *pde) == 0UL) { + return NULL; + } else if (pde_large(*pde) != 0UL) { + *pg_size = PDE_SIZE; + return pde; + } + + pte = pte_offset(pde, addr); + if (pgentry_present(ptt, *pte) == 0UL) { + return NULL; + } else { + *pg_size = PTE_SIZE; + return pte; + } +} diff --git a/hypervisor/include/arch/x86/mmu.h b/hypervisor/include/arch/x86/mmu.h index 0d20db48f..86567c5b2 100644 --- a/hypervisor/include/arch/x86/mmu.h +++ b/hypervisor/include/arch/x86/mmu.h @@ -339,6 +339,8 @@ void invept(struct vcpu *vcpu); bool check_continuous_hpa(struct vm *vm, uint64_t gpa_arg, uint64_t size_arg); int obtain_last_page_table_entry(struct map_params *map_params, struct entry_params *entry, void *addr, bool direct); +uint64_t *lookup_address(uint64_t *pml4_page, uint64_t addr, + uint64_t *pg_size, enum _page_table_type ptt); int register_mmio_emulation_handler(struct vm *vm, hv_mem_io_handler_t read_write, uint64_t start,