]> xenbits.xensource.com Git - people/liuw/xen.git/commitdiff
xxx
authorWei Liu <wei.liu2@citrix.com>
Wed, 23 Jan 2019 17:42:56 +0000 (17:42 +0000)
committerWei Liu <wei.liu2@citrix.com>
Thu, 24 Jan 2019 14:49:49 +0000 (14:49 +0000)
xen/arch/x86/mm.c

index 206f074f6e6b8c3d4c0cc1dfdc59a32bd1bff857..6f1d5f96ad87861bb3823daa35f2bdb5f118d814 100644 (file)
@@ -4830,10 +4830,14 @@ static l3_pgentry_t *virt_to_xen_l3e(unsigned long v)
     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;
+    l2_pgentry_t *pl2e = NULL;
 
     pl3e = virt_to_xen_l3e(v);
     if ( !pl3e )
@@ -4842,28 +4846,51 @@ static l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
     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;
 
+        mfn = alloc_xen_pagetable_new();
+        if ( mfn_eq(mfn, INVALID_MFN) )
+            goto out;
+
+        l2t = map_xen_pagetable_new(mfn);
         if ( !l2t )
-            return NULL;
+        {
+            free_xen_pagetable_new(mfn);
+            goto out;
+        }
+
         if ( locking )
             spin_lock(&map_pgdir_lock);
         if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
         {
             clear_page(l2t);
-            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);
-    pl2e = l3e_to_l2e(*pl3e) + l2_table_offset(v);
-    unmap_xen_pagetable_new(pl3e);
 
+    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;
 }