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

[Xen-devel] [RFC][PATCH] 6/9 Populate-on-demand memory: superpage splintering


  • To: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
  • From: "George Dunlap" <George.Dunlap@xxxxxxxxxxxxx>
  • Date: Tue, 23 Dec 2008 13:51:32 +0000
  • Delivery-date: Tue, 23 Dec 2008 05:51:56 -0800
  • Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:sender:to:subject:mime-version:content-type :content-transfer-encoding:content-disposition:x-google-sender-auth; b=rrsljWRtgqsB5L7RwjvtW98lYYPQuwK3kv3OxikAinIC6SfyBR7+Xjd0fwdVtCkDa1 fCHDqUI3SUCJn+yXxbHHbMKQ4/kWJci0ydKuLMBnXHDJzQ14nUBmf2ZhwKFCzv20VytB nOsIR9G+ARso3bnKKB9c35boJjAr7hcNUA8Ug=
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>

Deal with splintering superpages in the PoD cache, and with
splintering superpage PoD entries in the p2m table.

Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>

diff -r d7ac5e33d86c xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c     Wed Dec 17 14:12:52 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c     Wed Dec 17 14:13:56 2008 +0000
@@ -321,6 +321,70 @@
     spin_unlock(&d->page_alloc_lock);

     return 0;
+}
+
+/* Get a page of size order from the populate-on-demand cache.  Will break
+ * down 2-meg pages into singleton pages automatically.  Returns null if
+ * a superpage is requested and no superpages are available.  Must be called
+ * with the d->page_lock held. */
+static struct page_info * p2m_pod_cache_get(struct domain *d,
+                                            unsigned long order)
+{
+    struct p2m_domain *p2md = d->arch.p2m;
+    struct page_info *p = NULL;
+    int i;
+
+    if ( order == 9 && list_empty(&p2md->pod.super) )
+    {
+        return NULL;
+    }
+    else if ( order == 0 && list_empty(&p2md->pod.single) )
+    {
+        unsigned long mfn;
+        struct page_info *q;
+
+        BUG_ON( list_empty(&p2md->pod.super) );
+
+        /* Break up a superpage to make single pages. NB count doesn't
+         * need to be adjusted. */
+        printk("%s: Breaking up superpage.\n", __func__);
+        p = list_entry(p2md->pod.super.next, struct page_info, list);
+        list_del(&p->list);
+        mfn = mfn_x(page_to_mfn(p));
+
+        for ( i=0; i<(1<<9); i++ )
+        {
+            q = mfn_to_page(_mfn(mfn+i));
+            list_add_tail(&q->list, &p2md->pod.single);
+        }
+    }
+
+    switch ( order )
+    {
+    case 9:
+        BUG_ON( list_empty(&p2md->pod.super) );
+        p = list_entry(p2md->pod.super.next, struct page_info, list);
+        p2md->pod.count -= 1 << order; /* Lock: page_alloc */
+        break;
+    case 0:
+        BUG_ON( list_empty(&p2md->pod.single) );
+        p = list_entry(p2md->pod.single.next, struct page_info, list);
+        p2md->pod.count -= 1;
+        break;
+    default:
+        BUG();
+    }
+
+    list_del(&p->list);
+
+    /* Put the pages back on the domain page_list */
+    for ( i = 0 ; i < (1 << order) ; i++ )
+    {
+        BUG_ON(page_get_owner(p + i) != d);
+        list_add_tail(&p[i].list, &d->page_list);
+    }
+
+    return p;
 }

 void
@@ -815,35 +879,14 @@
     if ( p2md->pod.count == 0 )
         goto out_of_memory;

-    /* FIXME -- use single pages / splinter superpages if need be */
-    switch ( order )
-    {
-    case 9:
-        BUG_ON( list_empty(&p2md->pod.super) );
-        p = list_entry(p2md->pod.super.next, struct page_info, list);
-        p2md->pod.count -= 1 << order; /* Lock: page_alloc */
-        break;
-    case 0:
-        BUG_ON( list_empty(&p2md->pod.single) );
-        p = list_entry(p2md->pod.single.next, struct page_info, list);
-        p2md->pod.count -= 1;
-        break;
-    default:
-        BUG();
-    }
-
-    list_del(&p->list);
+    /* Get a page f/ the cache.  A NULL return value indicates that the
+     * 2-meg range should be marked singleton PoD, and retried */
+    if ( (p = p2m_pod_cache_get(d, order)) == NULL )
+        goto remap_and_retry;

     mfn = page_to_mfn(p);

     BUG_ON((mfn_x(mfn) & ((1 << order)-1)) != 0);
-
-    /* Put the pages back on the domain page_list */
-    for ( i = 0 ; i < (1 << order) ; i++ )
-    {
-        BUG_ON(page_get_owner(p + i) != d);
-        list_add_tail(&p[i].list, &d->page_list);
-    }

     spin_unlock(&d->page_alloc_lock);

@@ -888,6 +931,18 @@
     printk("%s: Out of populate-on-demand memory!\n", __func__);
     domain_crash(d);
     return -1;
+remap_and_retry:
+    BUG_ON(order != 9);
+    spin_unlock(&d->page_alloc_lock);
+
+    /* Remap this 2-meg region in singleton chunks */
+    gfn_aligned = (gfn>>order)<<order;
+    for(i=0; i<(1<<order); i++)
+        set_p2m_entry(d, gfn_aligned+i, _mfn(POPULATE_ON_DEMAND_MFN), 0,
+                      p2m_populate_on_demand);
+    audit_p2m(d);
+    p2m_unlock(p2md);
+    return 0;
 }

 // Returns 0 on error (out of memory)

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

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