x86/xen: export xen_alloc_p2m_entry()
authorDavid Vrabel <david.vrabel@citrix.com>
Wed, 22 Jul 2015 13:48:09 +0000 (14:48 +0100)
committerDavid Vrabel <david.vrabel@citrix.com>
Fri, 23 Oct 2015 13:20:28 +0000 (14:20 +0100)
Rename alloc_p2m() to xen_alloc_p2m_entry() and export it.

This is useful for ensuring that a p2m entry is allocated (i.e., not a
shared missing or identity entry) so that subsequent set_phys_to_machine()
calls will require no further allocations.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v3:
- Make xen_alloc_p2m_entry() a nop on auto-xlate guests.

arch/x86/include/asm/xen/page.h
arch/x86/xen/p2m.c

index 0679e11d2cf7ddf4f7a72bee6db3f4368aff37d1..b922fa4bb4a1049bc9efa84aaf97b2e2ab391897 100644 (file)
@@ -43,6 +43,8 @@ extern unsigned long *xen_p2m_addr;
 extern unsigned long  xen_p2m_size;
 extern unsigned long  xen_max_p2m_pfn;
 
+extern int xen_alloc_p2m_entry(unsigned long pfn);
+
 extern unsigned long get_phys_to_machine(unsigned long pfn);
 extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
 extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
index 660b3cfef23485f149e1a9b0b88f0b12666dbefb..cab9f766bb06b28b8f0f8f35583e70ae50adb30e 100644 (file)
@@ -530,7 +530,7 @@ static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *pte_pg)
  * the new pages are installed with cmpxchg; if we lose the race then
  * simply free the page we allocated and use the one that's there.
  */
-static bool alloc_p2m(unsigned long pfn)
+int xen_alloc_p2m_entry(unsigned long pfn)
 {
        unsigned topidx;
        unsigned long *top_mfn_p, *mid_mfn;
@@ -540,6 +540,9 @@ static bool alloc_p2m(unsigned long pfn)
        unsigned long addr = (unsigned long)(xen_p2m_addr + pfn);
        unsigned long p2m_pfn;
 
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return 0;
+
        ptep = lookup_address(addr, &level);
        BUG_ON(!ptep || level != PG_LEVEL_4K);
        pte_pg = (pte_t *)((unsigned long)ptep & ~(PAGE_SIZE - 1));
@@ -548,7 +551,7 @@ static bool alloc_p2m(unsigned long pfn)
                /* PMD level is missing, allocate a new one */
                ptep = alloc_p2m_pmd(addr, pte_pg);
                if (!ptep)
-                       return false;
+                       return -ENOMEM;
        }
 
        if (p2m_top_mfn && pfn < MAX_P2M_PFN) {
@@ -566,7 +569,7 @@ static bool alloc_p2m(unsigned long pfn)
 
                        mid_mfn = alloc_p2m_page();
                        if (!mid_mfn)
-                               return false;
+                               return -ENOMEM;
 
                        p2m_mid_mfn_init(mid_mfn, p2m_missing);
 
@@ -592,7 +595,7 @@ static bool alloc_p2m(unsigned long pfn)
 
                p2m = alloc_p2m_page();
                if (!p2m)
-                       return false;
+                       return -ENOMEM;
 
                if (p2m_pfn == PFN_DOWN(__pa(p2m_missing)))
                        p2m_init(p2m);
@@ -625,8 +628,9 @@ static bool alloc_p2m(unsigned long pfn)
                HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn;
        }
 
-       return true;
+       return 0;
 }
+EXPORT_SYMBOL(xen_alloc_p2m_entry);
 
 unsigned long __init set_phys_range_identity(unsigned long pfn_s,
                                      unsigned long pfn_e)
@@ -688,7 +692,10 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
        if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
-               if (!alloc_p2m(pfn))
+               int ret;
+
+               ret = xen_alloc_p2m_entry(pfn);
+               if (ret < 0)
                        return false;
 
                return __set_phys_to_machine(pfn, mfn);