x86: Introduce function to get pmd entry pointer
authorJuergen Gross <jgross@suse.com>
Fri, 28 Nov 2014 10:53:56 +0000 (11:53 +0100)
committerDavid Vrabel <david.vrabel@citrix.com>
Thu, 4 Dec 2014 14:09:04 +0000 (14:09 +0000)
Introduces lookup_pmd_address() to get the address of the pmd entry
related to a virtual address in the current address space. This
function is needed for support of a virtual mapped sparse p2m list
in xen pv domains, as we need the address of the pmd entry, not the
one of the pte in that case.

Signed-off-by: Juergen Gross <jgross@suse.com>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
arch/x86/include/asm/pgtable_types.h
arch/x86/mm/pageattr.c

index 0778964..d83f5e7 100644 (file)
@@ -396,6 +396,7 @@ static inline void update_page_count(int level, unsigned long pages) { }
 extern pte_t *lookup_address(unsigned long address, unsigned int *level);
 extern pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
                                    unsigned int *level);
+extern pmd_t *lookup_pmd_address(unsigned long address);
 extern phys_addr_t slow_virt_to_phys(void *__address);
 extern int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
                                   unsigned numpages, unsigned long page_flags);
index 36de293..1298108 100644 (file)
@@ -383,6 +383,26 @@ static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address,
         return lookup_address(address, level);
 }
 
+/*
+ * Lookup the PMD entry for a virtual address. Return a pointer to the entry
+ * or NULL if not present.
+ */
+pmd_t *lookup_pmd_address(unsigned long address)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+
+       pgd = pgd_offset_k(address);
+       if (pgd_none(*pgd))
+               return NULL;
+
+       pud = pud_offset(pgd, address);
+       if (pud_none(*pud) || pud_large(*pud) || !pud_present(*pud))
+               return NULL;
+
+       return pmd_offset(pud, address);
+}
+
 /*
  * This is necessary because __pa() does not work on some
  * kinds of memory, like vmalloc() or the alloc_remap()