]> xenbits.xensource.com Git - xen.git/commitdiff
x86/mm: Carve steal_linear_address() out of replace_grant_host_mapping()
authorAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 1 Aug 2017 15:39:59 +0000 (16:39 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 13 Sep 2017 10:22:22 +0000 (11:22 +0100)
Document its curious semantics.

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/mm.c

index 1eb9d834212238cea788b237c7f46ce10c8940bc..26d781e5015edb5ebbc66c6f714f8f96e34c1909 100644 (file)
@@ -4084,14 +4084,68 @@ int create_grant_pv_mapping(uint64_t addr, unsigned long frame,
     return rc;
 }
 
-int replace_grant_pv_mapping(uint64_t addr, unsigned long frame,
-                             uint64_t new_addr, unsigned int flags)
+/*
+ * This exists soley for implementing GNTABOP_unmap_and_replace, the ABI of
+ * which is bizarre.  This GNTTABOP isn't used any more, but was used by
+ * classic-xen kernels and PVOps Linux before the M2P_OVERRIDE infrastructure
+ * was replaced with something which actually worked.
+ *
+ * Look up the L1e mapping linear, and zap it.  Return the L1e via *out.
+ * Returns a boolean indicating success.  If success, the caller is
+ * responsible for calling put_page_from_l1e().
+ */
+static bool steal_linear_address(unsigned long linear, l1_pgentry_t *out)
 {
     struct vcpu *curr = current;
     struct domain *currd = curr->domain;
     l1_pgentry_t *pl1e, ol1e;
+    struct page_info *page;
     mfn_t gl1mfn;
-    struct page_info *l1pg;
+    bool okay = false;
+
+    ASSERT(is_pv_domain(currd));
+
+    pl1e = map_guest_l1e(linear, &gl1mfn);
+    if ( !pl1e )
+    {
+        gdprintk(XENLOG_WARNING,
+                 "Could not find L1 PTE for linear %"PRIx64"\n", linear);
+        goto out;
+    }
+
+    if ( !get_page_from_mfn(gl1mfn, currd) )
+        goto out_unmap;
+
+    page = mfn_to_page(gl1mfn);
+    if ( !page_lock(page) )
+        goto out_put;
+
+    if ( (page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table )
+        goto out_unlock;
+
+    ol1e = *pl1e;
+    okay = UPDATE_ENTRY(l1, pl1e, ol1e, l1e_empty(), mfn_x(gl1mfn), curr, 0);
+
+ out_unlock:
+    page_unlock(page);
+ out_put:
+    put_page(page);
+ out_unmap:
+    unmap_domain_page(pl1e);
+
+    if ( okay )
+        *out = ol1e;
+
+ out:
+    return okay;
+}
+
+int replace_grant_pv_mapping(uint64_t addr, unsigned long frame,
+                             uint64_t new_addr, unsigned int flags)
+{
+    struct vcpu *curr = current;
+    struct domain *currd = curr->domain;
+    l1_pgentry_t ol1e;
     int rc;
     unsigned int grant_pte_flags = grant_to_pte_flags(flags, 0);
 
@@ -4117,51 +4171,8 @@ int replace_grant_pv_mapping(uint64_t addr, unsigned long frame,
     if ( !new_addr )
         return destroy_grant_va_mapping(addr, frame, grant_pte_flags, curr);
 
-    pl1e = map_guest_l1e(new_addr, &gl1mfn);
-    if ( !pl1e )
-    {
-        gdprintk(XENLOG_WARNING,
-                 "Could not find L1 PTE for address %"PRIx64"\n", new_addr);
-        return GNTST_general_error;
-    }
-
-    if ( !get_page_from_mfn(gl1mfn, currd) )
-    {
-        unmap_domain_page(pl1e);
-        return GNTST_general_error;
-    }
-
-    l1pg = mfn_to_page(gl1mfn);
-    if ( !page_lock(l1pg) )
-    {
-        put_page(l1pg);
-        unmap_domain_page(pl1e);
-        return GNTST_general_error;
-    }
-
-    if ( (l1pg->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table )
-    {
-        page_unlock(l1pg);
-        put_page(l1pg);
-        unmap_domain_page(pl1e);
-        return GNTST_general_error;
-    }
-
-    ol1e = *pl1e;
-
-    if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, l1e_empty(),
-                                mfn_x(gl1mfn), curr, 0)) )
-    {
-        page_unlock(l1pg);
-        put_page(l1pg);
-        gdprintk(XENLOG_WARNING, "Cannot delete PTE entry at %p\n", pl1e);
-        unmap_domain_page(pl1e);
+    if ( !steal_linear_address(new_addr, &ol1e) )
         return GNTST_general_error;
-    }
-
-    page_unlock(l1pg);
-    put_page(l1pg);
-    unmap_domain_page(pl1e);
 
     rc = replace_grant_va_mapping(addr, frame, grant_pte_flags, ol1e, curr);
     if ( rc )