return (void *)phys + hypervisor_header.page_offset;
}
+unsigned long page_map_virt2phys(pgd_t *page_table, unsigned long virt,
+ unsigned int levels);
+
int page_map_create(pgd_t *page_table, unsigned long phys, unsigned long size,
unsigned long virt, unsigned long page_flags,
unsigned long table_flags, unsigned int levels,
}
}
+unsigned long page_map_virt2phys(pgd_t *page_table, unsigned long virt,
+ unsigned int levels)
+{
+ unsigned long offs = hypervisor_header.page_offset;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ switch (levels) {
+ case 4:
+ pgd = pgd_offset(page_table, virt);
+ if (!pgd_valid(pgd))
+ return INVALID_PHYS_ADDR;
+
+ pud = pud4l_offset(pgd, offs, virt);
+ break;
+ case 3:
+ pud = pud3l_offset(page_table, virt);
+ break;
+ default:
+ return INVALID_PHYS_ADDR;
+ }
+ if (!pud_valid(pud))
+ return INVALID_PHYS_ADDR;
+
+ pmd = pmd_offset(pud, offs, virt);
+ if (!pmd_valid(pud))
+ return INVALID_PHYS_ADDR;
+
+ if (pmd_is_hugepage(pmd))
+ return phys_address_hugepage(pmd, virt);
+
+ pte = pte_offset(pmd, offs, virt);
+ if (!pte_valid(pte))
+ return INVALID_PHYS_ADDR;
+
+ return phys_address(pte, virt);
+}
+
static void flush_page_table(void *addr, unsigned long size,
enum page_map_coherent coherent)
{