# HG changeset patch # User Juergen Gross # Date 1342171664 -7200 # Node ID 7bf9266bc106acaedd3c2cf70f7040e48be96bbb # Parent 8b1e10c2494fd31f2ca53926cca2993dff045125 xen 4.0: tools: Introduce "allocate-only" page type for migration To detect presence of superpages on the receiver side, we need to have strings of sequential pfns sent across on the first iteration through the memory. However, as we go through the memory, more and more of it will be marked dirty, making it wasteful to send those pages. This patch introduces a new PFINFO type, "XALLOC". Like PFINFO_XTAB, it indicates that there is no corresponding page present in the subsquent page buffer. However, unlike PFINFO_XTAB, it contains a pfn which should be allocated. This new type is only used for migration; but it's placed in xen/public/domctl.h so that the value isn't reused. Signed-off-by: George Dunlap diff -r 8b1e10c2494f -r 7bf9266bc106 tools/libxc/xc_domain_restore.c --- a/tools/libxc/xc_domain_restore.c Fri Jul 13 11:27:43 2012 +0200 +++ b/tools/libxc/xc_domain_restore.c Fri Jul 13 11:27:44 2012 +0200 @@ -757,7 +757,8 @@ static int pagebuf_get_one(struct restor countpages = count; for (i = oldcount; i < buf->nr_pages; ++i) - if ((buf->pfn_types[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XTAB) + if ((buf->pfn_types[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XTAB + ||(buf->pfn_types[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XALLOC) --countpages; if (!countpages) @@ -835,6 +836,7 @@ static int apply_batch(int xc_handle, ui pfn = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; pagetype = pagebuf->pfn_types[i + curbatch] & XEN_DOMCTL_PFINFO_LTAB_MASK; + /* For allocation purposes, treat XEN_DOMCTL_PFINFO_XALLOC as a normal page */ if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && (ctx->p2m[pfn] == INVALID_P2M_ENTRY) ) { @@ -946,21 +948,21 @@ static int apply_batch(int xc_handle, ui pfn = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; pagetype = pagebuf->pfn_types[i + curbatch] & XEN_DOMCTL_PFINFO_LTAB_MASK; - if ( pagetype == XEN_DOMCTL_PFINFO_XTAB ) + if ( pagetype != XEN_DOMCTL_PFINFO_XTAB + && ctx->p2m[pfn] == (INVALID_P2M_ENTRY-1) ) + { + /* We just allocated a new mfn above; update p2m */ + ctx->p2m[pfn] = ctx->p2m_batch[nr_mfns++]; + ctx->nr_pfns++; + } + + /* setup region_mfn[] for batch map, if necessary. + * For HVM guests, this interface takes PFNs, not MFNs */ + if ( pagetype == XEN_DOMCTL_PFINFO_XTAB + || pagetype == XEN_DOMCTL_PFINFO_XALLOC ) region_mfn[i] = ~0UL; /* map will fail but we don't care */ - else - { - if ( ctx->p2m[pfn] == (INVALID_P2M_ENTRY-1) ) - { - /* We just allocated a new mfn above; update p2m */ - ctx->p2m[pfn] = ctx->p2m_batch[nr_mfns++]; - ctx->nr_pfns++; - } - - /* setup region_mfn[] for batch map. - * For HVM guests, this interface takes PFNs, not MFNs */ + else region_mfn[i] = hvm ? pfn : ctx->p2m[pfn]; - } } /* Map relevant mfns */ @@ -980,8 +982,9 @@ static int apply_batch(int xc_handle, ui pfn = pagebuf->pfn_types[i + curbatch] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; pagetype = pagebuf->pfn_types[i + curbatch] & XEN_DOMCTL_PFINFO_LTAB_MASK; - if ( pagetype == XEN_DOMCTL_PFINFO_XTAB ) - /* a bogus/unmapped page: skip it */ + if ( pagetype == XEN_DOMCTL_PFINFO_XTAB + || pagetype == XEN_DOMCTL_PFINFO_XALLOC) + /* a bogus/unmapped/allocate-only page: skip it */ continue; if (pfn_err[i]) diff -r 8b1e10c2494f -r 7bf9266bc106 tools/libxc/xc_domain_save.c --- a/tools/libxc/xc_domain_save.c Fri Jul 13 11:27:43 2012 +0200 +++ b/tools/libxc/xc_domain_save.c Fri Jul 13 11:27:44 2012 +0200 @@ -1224,13 +1224,15 @@ int xc_domain_save(int xc_handle, int io } else { - if ( !last_iter && + int dont_skip = (last_iter || (superpages && iter==1)); + + if ( !dont_skip && test_bit(n, to_send) && test_bit(n, to_skip) ) skip_this_iter++; /* stats keeping */ if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) || - (test_bit(n, to_send) && last_iter) || + (test_bit(n, to_send) && dont_skip) || (test_bit(n, to_fix) && last_iter)) ) continue; @@ -1243,7 +1245,7 @@ int xc_domain_save(int xc_handle, int io /* ** we get here if: ** 1. page is marked to_send & hasn't already been re-dirtied - ** 2. (ignore to_skip in last iteration) + ** 2. (ignore to_skip in first and last iterations) ** 3. add in pages that still need fixup (net bufs) */ @@ -1267,7 +1269,7 @@ int xc_domain_save(int xc_handle, int io set_bit(n, to_fix); continue; } - + if ( last_iter && test_bit(n, to_fix) && !test_bit(n, to_send) ) @@ -1294,56 +1296,66 @@ int xc_domain_save(int xc_handle, int io goto out; } - if ( hvm ) + /* Get page types */ + if ( xc_get_pfn_type_batch(xc_handle, dom, batch, pfn_type) ) { - /* Look for and skip completely empty batches. */ - for ( j = 0; j < batch; j++ ) + PERROR("get_pfn_type_batch failed"); + goto out; + } + + for ( run = j = 0; j < batch; j++ ) + { + unsigned long gmfn = pfn_batch[j]; + + if ( !hvm ) + gmfn = pfn_to_mfn(gmfn); + + if ( pfn_err[j] ) { - if ( !pfn_err[j] ) - break; - pfn_type[j] |= XEN_DOMCTL_PFINFO_XTAB; - } - if ( j == batch ) - { - munmap(region_base, batch*PAGE_SIZE); - continue; /* bail on this batch: no valid pages */ - } - for ( ; j < batch; j++ ) - if ( pfn_err[j] ) - pfn_type[j] |= XEN_DOMCTL_PFINFO_XTAB; - } - else - { - /* Get page types */ - if ( xc_get_pfn_type_batch(xc_handle, dom, batch, pfn_type) ) - { - ERROR("get_pfn_type_batch failed"); - goto out; + if ( pfn_type[j] == XEN_DOMCTL_PFINFO_XTAB ) + continue; + + DPRINTF("map fail: page %i mfn %08lx err %d\n", + j, gmfn, pfn_err[j]); + pfn_type[j] = XEN_DOMCTL_PFINFO_XTAB; + continue; } - for ( j = 0; j < batch; j++ ) + if ( pfn_type[j] == XEN_DOMCTL_PFINFO_XTAB ) { - unsigned long mfn = pfn_to_mfn(pfn_batch[j]); - - if ( pfn_type[j] == XEN_DOMCTL_PFINFO_XTAB ) - { - DPRINTF("type fail: page %i mfn %08lx\n", - j, mfn); - continue; - } - - if ( debug ) + DPRINTF("type fail: page %i mfn %08lx\n", j, gmfn); + continue; + } + + if ( superpages && iter==1 && test_bit(gmfn, to_skip)) + pfn_type[j] = XEN_DOMCTL_PFINFO_XALLOC; + + /* canonicalise mfn->pfn */ + pfn_type[j] |= pfn_batch[j]; + ++run; + + if ( debug ) + { + if ( hvm ) + DPRINTF("%d pfn=%08lx sum=%08lx\n", + iter, + pfn_type[j], + csum_page(region_base + (PAGE_SIZE*j))); + else DPRINTF("%d pfn= %08lx mfn= %08lx [mfn]= %08lx" " sum= %08lx\n", iter, - pfn_type[j] | pfn_batch[j], - mfn, - mfn_to_pfn(mfn), + pfn_type[j], + gmfn, + mfn_to_pfn(gmfn), csum_page(region_base + (PAGE_SIZE*j))); - - /* canonicalise mfn->pfn */ - pfn_type[j] |= pfn_batch[j]; } + } + + if ( !run ) + { + munmap(region_base, batch*PAGE_SIZE); + continue; /* bail on this batch: no valid pages */ } if ( write_exact(io_fd, &batch, sizeof(unsigned int)) ) @@ -1392,8 +1404,9 @@ int xc_domain_save(int xc_handle, int io } } - /* skip pages that aren't present */ - if ( pagetype == XEN_DOMCTL_PFINFO_XTAB ) + /* skip pages that aren't present or are alloc-only */ + if ( pagetype == XEN_DOMCTL_PFINFO_XTAB + || pagetype == XEN_DOMCTL_PFINFO_XALLOC ) continue; pagetype &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK; diff -r 8b1e10c2494f -r 7bf9266bc106 xen/include/public/domctl.h --- a/xen/include/public/domctl.h Fri Jul 13 11:27:43 2012 +0200 +++ b/xen/include/public/domctl.h Fri Jul 13 11:27:44 2012 +0200 @@ -137,6 +137,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_getme #define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7U<<28) #define XEN_DOMCTL_PFINFO_LPINTAB (0x1U<<31) #define XEN_DOMCTL_PFINFO_XTAB (0xfU<<28) /* invalid page */ +#define XEN_DOMCTL_PFINFO_XALLOC (0xeU<<28) /* allocate-only page */ #define XEN_DOMCTL_PFINFO_PAGEDTAB (0x8U<<28) #define XEN_DOMCTL_PFINFO_LTAB_MASK (0xfU<<28)