Perform the translation of a guest virtual address to a guest physical address using the currently installed page tables. This must be used for virtual addresses that are not identity mapped addresses, e.g. a virtual address returned by alloc_vpage(), where virt_to_phys() won't work. Signed-off-by: Pavan Kumar Paluri <papaluri@xxxxxxx> --- lib/x86/vm.c | 24 ++++++++++++++++++++++++ lib/x86/vm.h | 1 + 2 files changed, 25 insertions(+) diff --git a/lib/x86/vm.c b/lib/x86/vm.c index ce2063aee75d..078665b2faf4 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -332,3 +332,27 @@ void walk_pte(void *virt, size_t len, pte_callback_t callback) callback(search, (void *)curr); } } + +unsigned long pgtable_va_to_pa(unsigned long va) +{ + pteval_t *pt = (pgd_t *)read_cr3(); + unsigned long offset, paddr; + int level; + + for (level = PAGE_LEVEL; level; level--) { + offset = PGDIR_OFFSET((uintptr_t)va, level); + assert_msg(pt[offset], "PTE absent"); + + if (level == 1 || + (level <= 3 && (pt[offset] & PT_PAGE_SIZE_MASK))) { + paddr = pt[offset] & PT_ADDR_MASK; + paddr += va & ((1UL << PGDIR_BITS(level)) - 1); + + return paddr; + } + + pt = phys_to_virt(pt[offset] & PT_ADDR_MASK); + } + + __builtin_unreachable(); +} diff --git a/lib/x86/vm.h b/lib/x86/vm.h index a5bd8d4ecf7c..9f72c267086d 100644 --- a/lib/x86/vm.h +++ b/lib/x86/vm.h @@ -59,6 +59,7 @@ static inline void *current_page_table(void) void split_large_page(unsigned long *ptep, int level); void force_4k_page(void *addr); +unsigned long pgtable_va_to_pa(unsigned long vaddr); struct vm_vcpu_info { u64 cr3; -- 2.34.1