WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 1 of 4] tools: Detect superpages on domain restore

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 1 of 4] tools: Detect superpages on domain restore
From: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
Date: Mon, 16 May 2011 11:51:03 +0100
Cc: george.dunlap@xxxxxxxxxxxxx
Delivery-date: Mon, 16 May 2011 03:52:30 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1305543062@elijah>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <patchbomb.1305543062@elijah>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mercurial-patchbomb/1.4.3
When receiving pages, look for contiguous 2-meg aligned regions and
attempt to allocate a superpage for that region, falling back to
4k pages if the allocation fails.

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

diff -r f9bb0bbea7c2 -r 57558d87761f tools/libxc/xc_domain_restore.c
--- a/tools/libxc/xc_domain_restore.c   Thu May 12 16:42:54 2011 +0100
+++ b/tools/libxc/xc_domain_restore.c   Mon May 16 11:50:46 2011 +0100
@@ -48,6 +48,11 @@ struct restore_ctx {
 
 #define HEARTBEAT_MS 1000
 
+#define SUPERPAGE_PFN_SHIFT  9
+#define SUPERPAGE_NR_PFNS    (1UL << SUPERPAGE_PFN_SHIFT)
+
+#define SUPER_PAGE_START(pfn)    (((pfn) & (SUPERPAGE_NR_PFNS-1)) == 0 )
+
 #ifndef __MINIOS__
 static ssize_t rdexact(xc_interface *xch, struct restore_ctx *ctx,
                        int fd, void* buf, size_t size)
@@ -882,9 +887,11 @@ static int pagebuf_get(xc_interface *xch
 static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx 
*ctx,
                        xen_pfn_t* region_mfn, unsigned long* pfn_type, int 
pae_extended_cr3,
                        unsigned int hvm, struct xc_mmu* mmu,
-                       pagebuf_t* pagebuf, int curbatch)
+                       pagebuf_t* pagebuf, int curbatch, int superpages)
 {
     int i, j, curpage, nr_mfns;
+    int k, scount;
+    unsigned long superpage_start=INVALID_P2M_ENTRY;
     /* used by debug verify code */
     unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
     /* Our mapping of the current region (batch) */
@@ -902,8 +909,8 @@ static int apply_batch(xc_interface *xch
     if (j > MAX_BATCH_SIZE)
         j = MAX_BATCH_SIZE;
 
-    /* First pass for this batch: work out how much memory to alloc */
-    nr_mfns = 0; 
+    /* First pass for this batch: work out how much memory to alloc, and 
detect superpages */
+    nr_mfns = scount = 0;
     for ( i = 0; i < j; i++ )
     {
         unsigned long pfn, pagetype;
@@ -914,19 +921,103 @@ static int apply_batch(xc_interface *xch
              (ctx->p2m[pfn] == INVALID_P2M_ENTRY) )
         {
             /* Have a live PFN which hasn't had an MFN allocated */
+
+            /* Logic if we're in the middle of detecting a candidate superpage 
*/
+            if ( superpage_start != INVALID_P2M_ENTRY )
+            {
+                /* Is this the next expected continuation? */
+                if ( pfn == superpage_start + scount )
+                {
+                    if ( !superpages )
+                    {
+                        ERROR("Unexpexted codepath with no superpages");
+                        return -1;
+                    }
+
+                    scount++;
+
+                    /* If we've found a whole superpage, allocate it and 
update p2m */
+                    if ( scount  == SUPERPAGE_NR_PFNS )
+                    {
+                        unsigned long supermfn;
+
+
+                        supermfn=superpage_start;
+                        if ( xc_domain_populate_physmap_exact(xch, dom, 1,
+                                         SUPERPAGE_PFN_SHIFT, 0, &supermfn) != 
0 )
+                        {
+                            DPRINTF("No 2M page available for pfn 0x%lx, fall 
back to 4K page.\n",
+                                    superpage_start);
+                            /* If we're falling back from a failed allocation, 
subtract one
+                             * from count, since the last page == pfn, which 
will behandled
+                             * anyway. */
+                            scount--;
+                            goto fallback;
+                        }
+
+                        DPRINTF("Mapping superpage (%d) pfn %lx, mfn %lx\n", 
scount, superpage_start, supermfn);
+                        for (k=0; k<scount; k++)
+                        {
+                            /* We just allocated a new mfn above; update p2m */
+                            ctx->p2m[superpage_start+k] = supermfn+k;
+                            ctx->nr_pfns++;
+                            /* region_map[] will be set below */
+                        }
+                        superpage_start=INVALID_P2M_ENTRY;
+                        scount=0;
+                    }
+                    continue;
+                }
+                
+            fallback:
+                DPRINTF("Falling back %d pages pfn %lx\n", scount, 
superpage_start);
+                for (k=0; k<scount; k++)
+                {
+                    ctx->p2m_batch[nr_mfns++] = superpage_start+k; 
+                    ctx->p2m[superpage_start+k]--;
+                }
+                superpage_start = INVALID_P2M_ENTRY;
+                scount=0;
+            }
+
+            /* Are we ready to start a new superpage candidate? */
+            if ( superpages && SUPER_PAGE_START(pfn) )
+            {
+                superpage_start=pfn;
+                scount++;
+                continue;
+            }
+            
+            /* Add the current pfn to pfn_batch */
             ctx->p2m_batch[nr_mfns++] = pfn; 
             ctx->p2m[pfn]--;
         }
-    } 
+    }
+
+    /* Clean up any partial superpage candidates */
+    if ( superpage_start != INVALID_P2M_ENTRY )
+    {
+        DPRINTF("Falling back %d pages pfn %lx\n", scount, superpage_start);
+        for (k=0; k<scount; k++)
+        {
+            ctx->p2m_batch[nr_mfns++] = superpage_start+k; 
+            ctx->p2m[superpage_start+k]--;
+        }
+        superpage_start = INVALID_P2M_ENTRY;
+    }
 
     /* Now allocate a bunch of mfns for this batch */
-    if ( nr_mfns &&
-         (xc_domain_populate_physmap_exact(xch, dom, nr_mfns, 0,
-                                            0, ctx->p2m_batch) != 0) )
-    { 
-        ERROR("Failed to allocate memory for batch.!\n"); 
-        errno = ENOMEM;
-        return -1;
+    if ( nr_mfns )
+    {
+        DPRINTF("Mapping order 0,  %d; first pfn %lx\n", nr_mfns, 
ctx->p2m_batch[0]);
+    
+        if(xc_domain_populate_physmap_exact(xch, dom, nr_mfns, 0,
+                                            0, ctx->p2m_batch) != 0) 
+        { 
+            ERROR("Failed to allocate memory for batch.!\n"); 
+            errno = ENOMEM;
+            return -1;
+        }
     }
 
     /* Second pass for this batch: update p2m[] and region_mfn[] */
@@ -977,7 +1068,8 @@ static int apply_batch(xc_interface *xch
 
         if (pfn_err[i])
         {
-            ERROR("unexpected PFN mapping failure");
+            ERROR("unexpected PFN mapping failure pfn %lx map_mfn %lx p2m_mfn 
%lx",
+                  pfn, region_mfn[i], ctx->p2m[pfn]);
             goto err_mapped;
         }
 
@@ -1148,9 +1240,6 @@ int xc_domain_restore(xc_interface *xch,
     /* For info only */
     ctx->nr_pfns = 0;
 
-    if ( superpages )
-        return 1;
-
     ctxt = xc_hypercall_buffer_alloc(xch, ctxt, sizeof(*ctxt));
 
     if ( ctxt == NULL )
@@ -1298,7 +1387,8 @@ int xc_domain_restore(xc_interface *xch,
             int brc;
 
             brc = apply_batch(xch, dom, ctx, region_mfn, pfn_type,
-                              pae_extended_cr3, hvm, mmu, &pagebuf, curbatch);
+                              pae_extended_cr3, hvm, mmu, &pagebuf, curbatch,
+                              superpages);
             if ( brc < 0 )
                 goto out;
 

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