]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
core: Reintroduce page_map_virt2phys
authorJan Kiszka <jan.kiszka@siemens.com>
Thu, 16 Jan 2014 17:54:12 +0000 (18:54 +0100)
committerJan Kiszka <jan.kiszka@siemens.com>
Thu, 16 Jan 2014 19:56:31 +0000 (20:56 +0100)
This was quick: We actually need this function to obtain guest->host
physical address translations during page_map_get_foreign_page.
Reintroduce it, but with adjusted interface:

First, the only page table offset we need is the one of the hypervisor
because this function will only be used for walking page tables that are
fully mapped into the hypervisor address space.

Second, to align its interface to the companion function page_map_create
and page_map_destroy, introduce a variable level parameter.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
hypervisor/include/jailhouse/paging.h
hypervisor/paging.c

index 9d6f80c1bc04144b1032eaed4ed339de704f2eb0..3a5c12df9e3d50f5eb7890e2a1d842aa671cbf6c 100644 (file)
@@ -47,6 +47,9 @@ static inline void *page_map_phys2hvirt(unsigned long phys)
        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,
index fe82b63138cf72e3c72bb4abe6484c3da07c1495..beecc349f5b48c54b74ecfd8474fedd3cf2441fb 100644 (file)
@@ -103,6 +103,46 @@ void page_free(struct page_pool *pool, void *page, unsigned int num)
        }
 }
 
+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)
 {