[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen master] xen/arm: p2m: Re-implement relinquish_p2m_mapping using p2m_{get, set}_entry



commit 438c5fe4f0c193cac3ee57419a29e45033515189
Author:     Julien Grall <julien.grall@xxxxxxx>
AuthorDate: Thu Sep 15 12:28:34 2016 +0100
Commit:     Stefano Stabellini <sstabellini@xxxxxxxxxx>
CommitDate: Tue Sep 27 18:14:12 2016 -0700

    xen/arm: p2m: Re-implement relinquish_p2m_mapping using p2m_{get,set}_entry
    
    The function relinquish_p2m_mapping can be re-implemented using
    p2m_{get,set}_entry by iterating over the range mapped and using the
    mapping order given by the callee.
    
    Given that the preemption was chosen arbitrarily, it is now done on every
    512 iterations. Meaning that Xen may check more often if the function is
    preempted when there are no mappings.
    
    Finally drop the operation RELINQUISH in apply_* as nobody is using it
    anymore. Note that the functions could have been dropped in one go at
    the end, however I find easier to drop the operations one by one
    avoiding a big deletion in the patch that remove the last operation.
    
    Signed-off-by: Julien Grall <julien.grall@xxxxxxx>
    Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>
    Tested-by: Tamas K Lengyel <tamas@xxxxxxxxxxxxx>
---
 xen/arch/arm/p2m.c | 77 +++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 59 insertions(+), 18 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index ae19c14..ecde5db 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -754,7 +754,6 @@ static int p2m_mem_access_radix_set(struct p2m_domain *p2m, 
gfn_t gfn,
 enum p2m_operation {
     INSERT,
     REMOVE,
-    RELINQUISH,
     MEMACCESS,
 };
 
@@ -1318,7 +1317,6 @@ static int apply_one_level(struct domain *d,
 
         break;
 
-    case RELINQUISH:
     case REMOVE:
         if ( !p2m_valid(orig_pte) )
         {
@@ -1502,17 +1500,6 @@ static int apply_p2m_changes(struct domain *d,
         {
             switch ( op )
             {
-            case RELINQUISH:
-                /*
-                 * Arbitrarily, preempt every 512 operations or 8192 nops.
-                 * 512*P2M_ONE_PROGRESS == 8192*P2M_ONE_PROGRESS_NOP == 0x2000
-                 * This is set in preempt_count_limit.
-                 *
-                 */
-                p2m->lowest_mapped_gfn = _gfn(addr >> PAGE_SHIFT);
-                rc = -ERESTART;
-                goto out;
-
             case MEMACCESS:
             {
                 /*
@@ -1919,16 +1906,70 @@ int p2m_init(struct domain *d)
     return rc;
 }
 
+/*
+ * The function will go through the p2m and remove page reference when it
+ * is required. The mapping will be removed from the p2m.
+ *
+ * XXX: See whether the mapping can be left intact in the p2m.
+ */
 int relinquish_p2m_mapping(struct domain *d)
 {
     struct p2m_domain *p2m = &d->arch.p2m;
-    unsigned long nr;
+    unsigned long count = 0;
+    p2m_type_t t;
+    int rc = 0;
+    unsigned int order;
+
+    /* Convenience alias */
+    gfn_t start = p2m->lowest_mapped_gfn;
+    gfn_t end = p2m->max_mapped_gfn;
+
+    p2m_write_lock(p2m);
+
+    for ( ; gfn_x(start) < gfn_x(end);
+          start = gfn_next_boundary(start, order) )
+    {
+        mfn_t mfn = p2m_get_entry(p2m, start, &t, NULL, &order);
+
+        count++;
+        /*
+         * Arbitrarily preempt every 512 iterations.
+         */
+        if ( !(count % 512) && hypercall_preempt_check() )
+        {
+            rc = -ERESTART;
+            break;
+        }
 
-    nr = gfn_x(p2m->max_mapped_gfn) - gfn_x(p2m->lowest_mapped_gfn);
+        /*
+         * p2m_set_entry will take care of removing reference on page
+         * when it is necessary and removing the mapping in the p2m.
+         */
+        if ( !mfn_eq(mfn, INVALID_MFN) )
+        {
+            /*
+             * For valid mapping, the start will always be aligned as
+             * entry will be removed whilst relinquishing.
+             */
+            rc = __p2m_set_entry(p2m, start, order, INVALID_MFN,
+                                 p2m_invalid, p2m_access_rwx);
+            if ( unlikely(rc) )
+            {
+                printk(XENLOG_G_ERR "Unable to remove mapping gfn=%#"PRI_gfn" 
order=%u from the p2m of domain %d\n", gfn_x(start), order, d->domain_id);
+                break;
+            }
+        }
+    }
 
-    return apply_p2m_changes(d, RELINQUISH, p2m->lowest_mapped_gfn, nr,
-                             INVALID_MFN, 0, p2m_invalid,
-                             d->arch.p2m.default_access);
+    /*
+     * Update lowest_mapped_gfn so on the next call we still start where
+     * we stopped.
+     */
+    p2m->lowest_mapped_gfn = start;
+
+    p2m_write_unlock(p2m);
+
+    return rc;
 }
 
 int p2m_cache_flush(struct domain *d, gfn_t start, unsigned long nr)
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.