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

[PATCH v10 6/10] libs/guest: use foreign copy API during migration



From: Edwin Török <edwin.torok@xxxxxxxxxx>

Use foreign code emulation code provided by previous commit to prepare
to use new hypercall.
This to make sure there are no regression in both functionality and
performance.

In particular tested:
- HVM VM;
- PV VM;
- verification code.

Migration times did not change.

Signed-off-by: Edwin Török <edwin.torok@xxxxxxxxxx>
Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
---
Changes since v6:
- merge with "finalize PoC" to remove the PoC;
- remove statistics, old and not clear at all how they were made;
- describe tests made.
---
 tools/libs/guest/xg_sr_common.h  |  4 +-
 tools/libs/guest/xg_sr_restore.c | 78 +++++++++++++++++---------------
 tools/libs/guest/xg_sr_save.c    | 62 +++++++++++--------------
 3 files changed, 71 insertions(+), 73 deletions(-)

diff --git a/tools/libs/guest/xg_sr_common.h b/tools/libs/guest/xg_sr_common.h
index 50f235ba87..ec3435790a 100644
--- a/tools/libs/guest/xg_sr_common.h
+++ b/tools/libs/guest/xg_sr_common.h
@@ -243,6 +243,7 @@ struct xc_sr_context
             unsigned long *deferred_pages;
             unsigned long nr_deferred_pages;
             xc_hypercall_buffer_t dirty_bitmap_hbuf;
+            xc_hypercall_buffer_t dest_buf;
             struct xc_sr_context_save_buffers
             {
                 xen_pfn_t batch_pfns[MAX_BATCH_SIZE];
@@ -256,8 +257,6 @@ struct xc_sr_context
                 struct iovec iov[MAX_BATCH_SIZE + 2]; /* Headers + data. */
                 MEM_NOACCESS_BUFFER(na4, 64);
                 uint64_t rec_pfns[MAX_BATCH_SIZE];
-                MEM_NOACCESS_BUFFER(na5, 64);
-                int errors[MAX_BATCH_SIZE];
             } *buffers;
         } save;
 
@@ -269,6 +268,7 @@ struct xc_sr_context
             int send_back_fd;
             unsigned long p2m_size;
             xc_hypercall_buffer_t dirty_bitmap_hbuf;
+            xc_hypercall_buffer_t verify_buf;
 
             /* From Image Header. */
             uint32_t format_version;
diff --git a/tools/libs/guest/xg_sr_restore.c b/tools/libs/guest/xg_sr_restore.c
index 458eaa5992..af97f3d466 100644
--- a/tools/libs/guest/xg_sr_restore.c
+++ b/tools/libs/guest/xg_sr_restore.c
@@ -257,16 +257,15 @@ static int process_page_data(struct xc_sr_context *ctx, 
unsigned int count,
 {
     xc_interface *xch = ctx->xch;
     xen_pfn_t *mfns = malloc(count * sizeof(*mfns));
-    int *map_errs = malloc(count * sizeof(*map_errs));
     int rc;
-    void *mapping = NULL, *guest_page = NULL;
     unsigned int nr_pages = 0;
+    void *const source = page_data;
 
-    if ( !mfns || !map_errs )
+    if ( !mfns )
     {
         rc = -1;
         ERROR("Failed to allocate %zu bytes to process page data",
-              count * (sizeof(*mfns) + sizeof(*map_errs)));
+              count * sizeof(*mfns));
         goto err;
     }
 
@@ -294,27 +293,8 @@ static int process_page_data(struct xc_sr_context *ctx, 
unsigned int count,
     if ( nr_pages == 0 )
         goto done;
 
-    mapping = guest_page = xenforeignmemory_map(
-        xch->fmem, ctx->domid, PROT_READ | PROT_WRITE,
-        nr_pages, mfns, map_errs);
-    if ( !mapping )
-    {
-        rc = -1;
-        PERROR("Unable to map %u mfns for %u pages of data",
-               nr_pages, count);
-        goto err;
-    }
-
     for ( unsigned int i = 0; i < nr_pages; ++i )
     {
-        if ( map_errs[i] )
-        {
-            rc = -1;
-            ERROR("Mapping pfn %#"PRIpfn" (mfn %#"PRIpfn", type %#"PRIx32") 
failed with %d",
-                  pfns[i], mfns[i], types[i], map_errs[i]);
-            goto err;
-        }
-
         /* Undo page normalisation done by the saver. */
         rc = ctx->restore.ops.localise_page(ctx, types[i], page_data);
         if ( rc )
@@ -324,31 +304,41 @@ static int process_page_data(struct xc_sr_context *ctx, 
unsigned int count,
             goto err;
         }
 
-        if ( ctx->restore.verify )
+        page_data += PAGE_SIZE;
+    }
+    if ( !ctx->restore.verify )
+    {
+        rc = xg_foreignmemory_copy_to(xch, ctx->domid, nr_pages, mfns, source);
+        if ( rc < 0 )
+            goto err;
+    }
+    else
+    {
+        DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, verify_buf,
+                                        &ctx->restore.verify_buf);
+        void *guest_page = verify_buf;
+
+        rc = xg_foreignmemory_copy_from(xch, ctx->domid, nr_pages, verify_buf, 
mfns);
+        if ( rc < 0 )
+            goto err;
+
+        page_data = source;
+        for ( unsigned int i = 0; i < nr_pages; ++i )
         {
             /* Verify mode - compare incoming data to what we already have. */
             if ( memcmp(guest_page, page_data, PAGE_SIZE) )
                 ERROR("verify pfn %#"PRIpfn" failed (type %#"PRIx32")",
                       pfns[i], types[i] >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
-        }
-        else
-        {
-            /* Regular mode - copy incoming data into place. */
-            memcpy(guest_page, page_data, PAGE_SIZE);
-        }
 
-        guest_page += PAGE_SIZE;
-        page_data += PAGE_SIZE;
+            guest_page += PAGE_SIZE;
+            page_data += PAGE_SIZE;
+        }
     }
 
  done:
     rc = 0;
 
  err:
-    if ( mapping )
-        xenforeignmemory_unmap(xch->fmem, mapping, nr_pages);
-
-    free(map_errs);
     free(mfns);
 
     return rc;
@@ -738,6 +728,18 @@ static int setup(struct xc_sr_context *ctx)
     int rc;
     DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
                                     &ctx->restore.dirty_bitmap_hbuf);
+    DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, verify_buf,
+                                    &ctx->restore.verify_buf);
+
+    verify_buf = xc_hypercall_buffer_alloc_pages(
+        xch, verify_buf, MAX_BATCH_SIZE);
+
+    if ( !verify_buf )
+    {
+        ERROR("Unable to allocate memory for test buffer");
+        rc = -1;
+        goto err;
+    }
 
     if ( ctx->stream_type == XC_STREAM_COLO )
     {
@@ -786,6 +788,8 @@ static void cleanup(struct xc_sr_context *ctx)
     unsigned int i;
     DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
                                     &ctx->restore.dirty_bitmap_hbuf);
+    DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, verify_buf,
+                                    &ctx->restore.verify_buf);
 
     for ( i = 0; i < ctx->restore.buffered_rec_num; i++ )
         free(ctx->restore.buffered_records[i].data);
@@ -794,6 +798,8 @@ static void cleanup(struct xc_sr_context *ctx)
         xc_hypercall_buffer_free_pages(
             xch, dirty_bitmap, NRPAGES(bitmap_size(ctx->restore.p2m_size)));
 
+    xc_hypercall_buffer_free_pages(xch, verify_buf, MAX_BATCH_SIZE);
+
     free(ctx->restore.buffered_records);
     free(ctx->restore.populated_pfns);
 
diff --git a/tools/libs/guest/xg_sr_save.c b/tools/libs/guest/xg_sr_save.c
index 96d7e9e2f8..6b381f0219 100644
--- a/tools/libs/guest/xg_sr_save.c
+++ b/tools/libs/guest/xg_sr_save.c
@@ -86,11 +86,9 @@ static int write_checkpoint_record(struct xc_sr_context *ctx)
 static int write_batch(struct xc_sr_context *ctx)
 {
     xc_interface *xch = ctx->xch;
-    void *guest_mapping = NULL;
     int rc = -1;
-    unsigned int i, p, nr_pages = 0, nr_pages_mapped = 0;
+    unsigned int i, nr_pages = 0;
     unsigned int nr_pfns = ctx->save.nr_batch_pfns;
-    void *page, *orig_page;
     int iovcnt = 0;
     xen_pfn_t *const batch_pfns = ctx->save.buffers->batch_pfns;
     struct {
@@ -111,8 +109,6 @@ static int write_batch(struct xc_sr_context *ctx)
     xen_pfn_t *const mfns = ctx->save.buffers->mfns;
     /* Types of the batch pfns. */
     xen_pfn_t *const types = ctx->save.buffers->types;
-    /* Errors from attempting to map the gfns. */
-    int *const errors = ctx->save.buffers->errors;
     /* Pointers to locally allocated pages.  Need freeing. */
     void **const local_pages = ctx->save.buffers->local_pages;
     /* iovec[] for writev(). */
@@ -170,30 +166,26 @@ static int write_batch(struct xc_sr_context *ctx)
         mfns[nr_pages++] = mfns[i];
     }
 
-    if ( nr_pages > 0 )
+    if ( nr_pages )
     {
-        guest_mapping = xenforeignmemory_map(
-            xch->fmem, ctx->domid, PROT_READ, nr_pages, mfns, errors);
-        if ( !guest_mapping )
+        DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, dest_buf,
+                                        &ctx->save.dest_buf);
+
+        rc = xg_foreignmemory_copy_from(xch, ctx->domid, nr_pages, dest_buf, 
mfns);
+        if ( rc < 0 )
         {
-            PERROR("Failed to map guest pages");
+            ERROR("xg_foreignmemory_copy_from failed");
             goto err;
         }
-        nr_pages_mapped = nr_pages;
 
-        for ( i = 0, p = 0; i < nr_pfns; ++i )
+        for ( unsigned int i = 0, p = 0; i < nr_pfns; ++i )
         {
+            void *page, *orig_page;
+
             if ( !page_type_has_stream_data(types[i]) )
                 continue;
 
-            if ( errors[p] )
-            {
-                ERROR("Mapping of pfn %#"PRIpfn" (mfn %#"PRIpfn") failed %d",
-                      batch_pfns[i], mfns[p], errors[p]);
-                goto err;
-            }
-
-            orig_page = page = guest_mapping + (p * PAGE_SIZE);
+            orig_page = page = dest_buf + (p * PAGE_SIZE);
             rc = ctx->save.ops.normalise_page(ctx, types[i], &page);
 
             if ( orig_page != page )
@@ -201,15 +193,13 @@ static int write_batch(struct xc_sr_context *ctx)
 
             if ( rc )
             {
-                if ( rc == -1 && errno == EAGAIN )
-                {
-                    set_bit(batch_pfns[i], ctx->save.deferred_pages);
-                    ++ctx->save.nr_deferred_pages;
-                    types[i] = XEN_DOMCTL_PFINFO_XTAB;
-                    --nr_pages;
-                }
-                else
+                if ( rc != -1 || errno != EAGAIN )
                     goto err;
+
+                set_bit(batch_pfns[i], ctx->save.deferred_pages);
+                ++ctx->save.nr_deferred_pages;
+                types[i] = XEN_DOMCTL_PFINFO_XTAB;
+                --nr_pages;
             }
             else if ( iov[iovcnt - 1].iov_base + iov[iovcnt - 1].iov_len !=
                       page )
@@ -222,8 +212,6 @@ static int write_batch(struct xc_sr_context *ctx)
             {
                 iov[iovcnt - 1].iov_len += PAGE_SIZE;
             }
-
-            rc = -1;
             ++p;
         }
     }
@@ -236,14 +224,13 @@ static int write_batch(struct xc_sr_context *ctx)
     if ( writev_exact(ctx->fd, iov, iovcnt) )
     {
         PERROR("Failed to write page data to stream");
+        rc = -1;
         goto err;
     }
 
     rc = ctx->save.nr_batch_pfns = 0;
 
  err:
-    if ( guest_mapping )
-        xenforeignmemory_unmap(xch->fmem, guest_mapping, nr_pages_mapped);
     for ( i = 0; i < nr_pfns; ++i )
     {
         free(local_pages[i]);
@@ -770,17 +757,21 @@ static int setup(struct xc_sr_context *ctx)
     int rc;
     DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
                                     &ctx->save.dirty_bitmap_hbuf);
+    DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, dest_buf,
+                                    &ctx->save.dest_buf);
 
     rc = ctx->save.ops.setup(ctx);
     if ( rc )
         goto err;
 
+    dest_buf = xc_hypercall_buffer_alloc_pages(
+        xch, dest_buf, MAX_BATCH_SIZE);
     dirty_bitmap = xc_hypercall_buffer_alloc_pages(
         xch, dirty_bitmap, NRPAGES(bitmap_size(ctx->save.p2m_size)));
     ctx->save.deferred_pages = bitmap_alloc(ctx->save.p2m_size);
     ctx->save.buffers = calloc(1, sizeof(*ctx->save.buffers));
 
-    if ( !ctx->save.buffers || !dirty_bitmap || !ctx->save.deferred_pages )
+    if ( !ctx->save.buffers || !dirty_bitmap || !ctx->save.deferred_pages || 
!dest_buf )
     {
         ERROR("Unable to allocate memory for dirty bitmaps, deferred pages"
               " and various batch buffers");
@@ -793,7 +784,6 @@ static int setup(struct xc_sr_context *ctx)
     MEM_NOACCESS_INIT(ctx->save.buffers->na2);
     MEM_NOACCESS_INIT(ctx->save.buffers->na3);
     MEM_NOACCESS_INIT(ctx->save.buffers->na4);
-    MEM_NOACCESS_INIT(ctx->save.buffers->na5);
 
     rc = 0;
 
@@ -806,7 +796,8 @@ static void cleanup(struct xc_sr_context *ctx)
     xc_interface *xch = ctx->xch;
     DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
                                     &ctx->save.dirty_bitmap_hbuf);
-
+    DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, dest_buf,
+                                    &ctx->save.dest_buf);
 
     xc_shadow_control(xch, ctx->domid, XEN_DOMCTL_SHADOW_OP_OFF,
                       NULL, 0);
@@ -816,6 +807,7 @@ static void cleanup(struct xc_sr_context *ctx)
 
     xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
                                    NRPAGES(bitmap_size(ctx->save.p2m_size)));
+    xc_hypercall_buffer_free_pages(xch, dest_buf, MAX_BATCH_SIZE);
     free(ctx->save.deferred_pages);
     free(ctx->save.buffers);
 }
-- 
2.43.0




 


Rackspace

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