]> xenbits.xensource.com Git - people/hx242/xen.git/commitdiff
x86/mm: rewrite virt_to_xen_l*e
authorWei Liu <wei.liu2@citrix.com>
Tue, 29 Jan 2019 12:42:23 +0000 (12:42 +0000)
committerHongyan Xia <hongyax@amazon.com>
Wed, 16 Oct 2019 12:25:06 +0000 (13:25 +0100)
Rewrite that function to use the new APIs. Modify its callers to unmap
the pointer returned.

Note that the change of virt_to_xen_l1e also requires vmap_to_mfn to
unmap the page.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Signed-off-by: Hongyan Xia <hongyax@amazon.com>
xen/arch/x86/domain_page.c
xen/arch/x86/mm.c
xen/include/asm-x86/mm.h
xen/include/asm-x86/page.h

index 4a07cfb18e9478afa4defd89d2d0ee24b371e827..24083e9a8624005ca22a0c682b87999c33453e98 100644 (file)
@@ -333,21 +333,23 @@ void unmap_domain_page_global(const void *ptr)
 mfn_t domain_page_map_to_mfn(const void *ptr)
 {
     unsigned long va = (unsigned long)ptr;
-    const l1_pgentry_t *pl1e;
+    l1_pgentry_t l1e;
 
     if ( va >= DIRECTMAP_VIRT_START )
         return _mfn(virt_to_mfn(ptr));
 
     if ( va >= VMAP_VIRT_START && va < VMAP_VIRT_END )
     {
-        pl1e = virt_to_xen_l1e(va);
+        l1_pgentry_t *pl1e = virt_to_xen_l1e(va);
         BUG_ON(!pl1e);
+        l1e = *pl1e;
+        UNMAP_XEN_PAGETABLE_NEW(pl1e);
     }
     else
     {
         ASSERT(va >= MAPCACHE_VIRT_START && va < MAPCACHE_VIRT_END);
-        pl1e = &__linear_l1_table[l1_linear_offset(va)];
+        l1e = __linear_l1_table[l1_linear_offset(va)];
     }
 
-    return l1e_get_mfn(*pl1e);
+    return l1e_get_mfn(l1e);
 }
index 79c65b15d5640a9433ecfbe5c7b9bf3706f9deef..f904b374af2fe52b0e7c5cde6b547384ed7c63b1 100644 (file)
@@ -4896,102 +4896,170 @@ void free_xen_pagetable_new(mfn_t mfn)
 
 static DEFINE_SPINLOCK(map_pgdir_lock);
 
+/*
+ * Given a virtual address, return a pointer to xen's L3 entry. Caller
+ * needs to unmap the pointer.
+ */
 static l3_pgentry_t *virt_to_xen_l3e(unsigned long v)
 {
     l4_pgentry_t *pl4e;
+    l3_pgentry_t *pl3e = NULL;
 
     pl4e = &idle_pg_table[l4_table_offset(v)];
     if ( !(l4e_get_flags(*pl4e) & _PAGE_PRESENT) )
     {
         bool locking = system_state > SYS_STATE_boot;
-        l3_pgentry_t *l3t = alloc_xen_pagetable();
+        l3_pgentry_t *l3t;
+        mfn_t mfn;
 
-        if ( !l3t )
-            return NULL;
+        mfn = alloc_xen_pagetable_new();
+        if ( mfn_eq(mfn, INVALID_MFN) )
+            goto out;
+        l3t = map_xen_pagetable_new(mfn);
         clear_page(l3t);
         if ( locking )
             spin_lock(&map_pgdir_lock);
         if ( !(l4e_get_flags(*pl4e) & _PAGE_PRESENT) )
         {
-            l4_pgentry_t l4e = l4e_from_paddr(__pa(l3t), __PAGE_HYPERVISOR);
+            l4_pgentry_t l4e = l4e_from_mfn(mfn, __PAGE_HYPERVISOR);
 
             l4e_write(pl4e, l4e);
             efi_update_l4_pgtable(l4_table_offset(v), l4e);
+            pl3e = l3t + l3_table_offset(v);
             l3t = NULL;
         }
         if ( locking )
             spin_unlock(&map_pgdir_lock);
         if ( l3t )
-            free_xen_pagetable(l3t);
+        {
+            ASSERT(!pl3e);
+            ASSERT(!mfn_eq(mfn, INVALID_MFN));
+            UNMAP_XEN_PAGETABLE_NEW(l3t);
+            free_xen_pagetable_new(mfn);
+        }
+    }
+
+    if ( !pl3e )
+    {
+        ASSERT(l4e_get_flags(*pl4e) & _PAGE_PRESENT);
+        pl3e = (l3_pgentry_t *)map_xen_pagetable_new(l4e_get_mfn(*pl4e))
+            + l3_table_offset(v);
     }
 
-    return l4e_to_l3e(*pl4e) + l3_table_offset(v);
+ out:
+    return pl3e;
 }
 
+/*
+ * Given a virtual address, return a pointer to xen's L2 entry. Caller
+ * needs to unmap the pointer.
+ */
 static l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
 {
     l3_pgentry_t *pl3e;
+    l2_pgentry_t *pl2e = NULL;
 
     pl3e = virt_to_xen_l3e(v);
     if ( !pl3e )
-        return NULL;
+        goto out;
 
     if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
     {
         bool locking = system_state > SYS_STATE_boot;
-        l2_pgentry_t *l2t = alloc_xen_pagetable();
+        l2_pgentry_t *l2t;
+        mfn_t mfn;
 
-        if ( !l2t )
-            return NULL;
+        mfn = alloc_xen_pagetable_new();
+        if ( mfn_eq(mfn, INVALID_MFN) )
+            goto out;
+        l2t = map_xen_pagetable_new(mfn);
         clear_page(l2t);
         if ( locking )
             spin_lock(&map_pgdir_lock);
         if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
         {
-            l3e_write(pl3e, l3e_from_paddr(__pa(l2t), __PAGE_HYPERVISOR));
+            l3e_write(pl3e, l3e_from_mfn(mfn, __PAGE_HYPERVISOR));
+            pl2e = l2t + l2_table_offset(v);
             l2t = NULL;
         }
         if ( locking )
             spin_unlock(&map_pgdir_lock);
+
         if ( l2t )
-            free_xen_pagetable(l2t);
+        {
+            ASSERT(!pl2e);
+            ASSERT(!mfn_eq(mfn, INVALID_MFN));
+            UNMAP_XEN_PAGETABLE_NEW(l2t);
+            free_xen_pagetable_new(mfn);
+        }
     }
 
     BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
-    return l3e_to_l2e(*pl3e) + l2_table_offset(v);
+
+    if ( !pl2e )
+    {
+        ASSERT(l3e_get_flags(*pl3e) & _PAGE_PRESENT);
+        pl2e = (l2_pgentry_t *)map_xen_pagetable_new(l3e_get_mfn(*pl3e))
+            + l2_table_offset(v);
+    }
+
+ out:
+    UNMAP_XEN_PAGETABLE_NEW(pl3e);
+    return pl2e;
 }
 
 l1_pgentry_t *virt_to_xen_l1e(unsigned long v)
 {
     l2_pgentry_t *pl2e;
+    l1_pgentry_t *pl1e = NULL;
 
     pl2e = virt_to_xen_l2e(v);
     if ( !pl2e )
-        return NULL;
+        goto out;
 
     if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
     {
         bool locking = system_state > SYS_STATE_boot;
-        l1_pgentry_t *l1t = alloc_xen_pagetable();
+        l1_pgentry_t *l1t;
+        mfn_t mfn;
 
-        if ( !l1t )
-            return NULL;
+        mfn = alloc_xen_pagetable_new();
+        if ( mfn_eq(mfn, INVALID_MFN) )
+            goto out;
+        l1t = map_xen_pagetable_new(mfn);
         clear_page(l1t);
         if ( locking )
             spin_lock(&map_pgdir_lock);
         if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
         {
-            l2e_write(pl2e, l2e_from_paddr(__pa(l1t), __PAGE_HYPERVISOR));
+            l2e_write(pl2e, l2e_from_mfn(mfn, __PAGE_HYPERVISOR));
+            pl1e = l1t + l1_table_offset(v);
             l1t = NULL;
         }
         if ( locking )
             spin_unlock(&map_pgdir_lock);
+
         if ( l1t )
-            free_xen_pagetable(l1t);
+        {
+            ASSERT(!pl1e);
+            ASSERT(!mfn_eq(mfn, INVALID_MFN));
+            UNMAP_XEN_PAGETABLE_NEW(l1t);
+            free_xen_pagetable_new(mfn);
+        }
     }
 
     BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
-    return l2e_to_l1e(*pl2e) + l1_table_offset(v);
+
+    if ( !pl1e )
+    {
+        ASSERT(l2e_get_flags(*pl2e) & _PAGE_PRESENT);
+        pl1e = (l1_pgentry_t *)map_xen_pagetable_new(l2e_get_mfn(*pl2e))
+            + l1_table_offset(v);
+    }
+
+ out:
+    UNMAP_XEN_PAGETABLE_NEW(pl2e);
+    return pl1e;
 }
 
 /* Convert to from superpage-mapping flags for map_pages_to_xen(). */
@@ -5014,8 +5082,8 @@ int map_pages_to_xen(
     unsigned int flags)
 {
     bool locking = system_state > SYS_STATE_boot;
-    l3_pgentry_t *pl3e, ol3e;
-    l2_pgentry_t *pl2e, ol2e;
+    l3_pgentry_t *pl3e = NULL, ol3e;
+    l2_pgentry_t *pl2e = NULL, ol2e;
     l1_pgentry_t *pl1e, ol1e;
     unsigned int  i;
     int rc = -ENOMEM;
@@ -5390,7 +5458,10 @@ int map_pages_to_xen(
             else if ( locking )
                 spin_unlock(&map_pgdir_lock);
         }
-    end_of_loop:;
+    end_of_loop:
+        UNMAP_XEN_PAGETABLE_NEW(pl1e);
+        UNMAP_XEN_PAGETABLE_NEW(pl2e);
+        UNMAP_XEN_PAGETABLE_NEW(pl3e);
     }
 
 #undef flush_flags
@@ -5398,6 +5469,9 @@ int map_pages_to_xen(
     rc = 0;
 
  out:
+    UNMAP_XEN_PAGETABLE_NEW(pl1e);
+    UNMAP_XEN_PAGETABLE_NEW(pl2e);
+    UNMAP_XEN_PAGETABLE_NEW(pl3e);
     return rc;
 }
 
@@ -5421,6 +5495,7 @@ int populate_pt_range(unsigned long virt, unsigned long nr_mfns)
 int modify_xen_mappings(unsigned long s, unsigned long e, unsigned int nf)
 {
     bool locking = system_state > SYS_STATE_boot;
+    l3_pgentry_t *pl3e = NULL;
     l2_pgentry_t *pl2e;
     l1_pgentry_t *pl1e;
     unsigned int  i;
@@ -5436,7 +5511,7 @@ int modify_xen_mappings(unsigned long s, unsigned long e, unsigned int nf)
 
     while ( v < e )
     {
-        l3_pgentry_t *pl3e = virt_to_xen_l3e(v);
+        pl3e = virt_to_xen_l3e(v);
 
         if ( !pl3e || !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
         {
@@ -5662,7 +5737,8 @@ int modify_xen_mappings(unsigned long s, unsigned long e, unsigned int nf)
             else if ( locking )
                 spin_unlock(&map_pgdir_lock);
         }
-    end_of_loop:;
+    end_of_loop:
+        UNMAP_XEN_PAGETABLE_NEW(pl3e);
     }
 
     flush_area(NULL, FLUSH_TLB_GLOBAL);
@@ -5671,6 +5747,7 @@ int modify_xen_mappings(unsigned long s, unsigned long e, unsigned int nf)
     rc = 0;
 
  out:
+    UNMAP_XEN_PAGETABLE_NEW(pl3e);
     return rc;
 }
 
index 80173eb4c3b3e1f3d902eda2940b2e2ea252ecf1..125d4cd643d5ea3e4b19f1e3399818dc24b1442a 100644 (file)
@@ -646,4 +646,14 @@ void free_xen_pagetable_new(mfn_t mfn);
 
 l1_pgentry_t *virt_to_xen_l1e(unsigned long v);
 
+static inline mfn_t vmap_to_mfn(void *va)
+{
+    l1_pgentry_t *pl1e = virt_to_xen_l1e((unsigned long)(va));
+    unsigned long retpfn = l1e_get_pfn(*pl1e);
+    unmap_xen_pagetable_new(pl1e);
+    return _mfn(retpfn);
+}
+
+#define vmap_to_page(va)    mfn_to_page(vmap_to_mfn(va))
+
 #endif /* __ASM_X86_MM_H__ */
index 05a8b1efa637532720c23cd67269ac02207d7c0c..f3e6d18e7ae0009b3ca656e15874e4b08a5e3791 100644 (file)
@@ -271,8 +271,6 @@ void copy_page_sse2(void *, const void *);
 #define pfn_to_paddr(pfn)   __pfn_to_paddr(pfn)
 #define paddr_to_pfn(pa)    __paddr_to_pfn(pa)
 #define paddr_to_pdx(pa)    pfn_to_pdx(paddr_to_pfn(pa))
-#define vmap_to_mfn(va)     _mfn(l1e_get_pfn(*virt_to_xen_l1e((unsigned long)(va))))
-#define vmap_to_page(va)    mfn_to_page(vmap_to_mfn(va))
 
 #endif /* !defined(__ASSEMBLY__) */