tools/libx[cl]: Plumb 'missing' through static_data_done() up into libxl
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 16 Dec 2019 19:03:14 +0000 (19:03 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 29 May 2020 16:33:03 +0000 (17:33 +0100)
Pre Xen-4.14 streams will not contain any CPUID/MSR information.  There is
nothing libxc can do about this, and will have to rely on the higher level
toolstack to provide backwards compatibility.

To facilitate this, extend the static_data_done() callback, highlighting the
missing information, and modify libxl to use it.  At the libxc level, this
requires an arch-specific hook which, for now, always reports CPUID and MSR as
missing.  This will be adjusted in a later change.

No overall functional change - this is just plumbing.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
tools/libxc/include/xenguest.h
tools/libxc/xc_sr_common.h
tools/libxc/xc_sr_common_x86.c
tools/libxc/xc_sr_common_x86.h
tools/libxc/xc_sr_restore.c
tools/libxc/xc_sr_restore_x86_hvm.c
tools/libxc/xc_sr_restore_x86_pv.c
tools/libxl/libxl_create.c
tools/libxl/libxl_save_msgs_gen.pl

index b4df8d0ffeff97a0c15f38f1a3feb23837a0eb85..7a12d21ff2c2b933ecab76fb961280cb05d71115 100644 (file)
@@ -139,8 +139,16 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom,
 
 /* callbacks provided by xc_domain_restore */
 struct restore_callbacks {
-    /* Called once the STATIC_DATA_END record has been received/inferred. */
-    int (*static_data_done)(void *data);
+    /*
+     * Called once the STATIC_DATA_END record has been received/inferred.
+     *
+     * For compatibility with older streams, provides a list of static data
+     * expected to be found in the stream, which was missing.  A higher level
+     * toolstack is responsible for providing any necessary compatibiltiy.
+     */
+#define XGR_SDD_MISSING_CPUID (1 << 0)
+#define XGR_SDD_MISSING_MSR   (1 << 1)
+    int (*static_data_done)(unsigned int missing, void *data);
 
     /* Called after a new checkpoint to suspend the guest. */
     int (*suspend)(void *data);
index 774226069066a340066e6f6f05d0873b55bf5a0c..f3bdea8006ce598739e1c9ad2f5a560f31468f2e 100644 (file)
@@ -158,6 +158,15 @@ struct xc_sr_restore_ops
 #define BROKEN_CHANNEL 2
     int (*process_record)(struct xc_sr_context *ctx, struct xc_sr_record *rec);
 
+    /**
+     * Perform any actions required after the static data has arrived.  Called
+     * when the STATIC_DATA_COMPLETE record has been recieved/inferred.
+     * 'missing' should be filled in for any data item the higher level
+     * toolstack needs to provide compatiblity for.
+     */
+    int (*static_data_complete)(struct xc_sr_context *ctx,
+                                unsigned int *missing);
+
     /**
      * Perform any actions required after the stream has been finished. Called
      * after the END record has been received.
index 6267655dabb0902b9dd77531ccbbc05e5c0ea51f..a849891634e7bb9f53dd6f6e56ab474038fcf7d3 100644 (file)
@@ -132,6 +132,14 @@ int handle_x86_msr_policy(struct xc_sr_context *ctx, struct xc_sr_record *rec)
     return rc;
 }
 
+int x86_static_data_complete(struct xc_sr_context *ctx, unsigned int *missing)
+{
+    /* TODO: Become conditional on there being no data in the stream. */
+    *missing = XGR_SDD_MISSING_MSR | XGR_SDD_MISSING_CPUID;
+
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
index d1050981dd7a9aa260330b9ed5a76e7c4aeb485f..e08d81e0e7c07e8fce0ef7d44111ba48e2895ee3 100644 (file)
@@ -34,6 +34,11 @@ int handle_x86_cpuid_policy(struct xc_sr_context *ctx,
 int handle_x86_msr_policy(struct xc_sr_context *ctx,
                           struct xc_sr_record *rec);
 
+/*
+ * Perform common x86 actions required after the static data has arrived.
+ */
+int x86_static_data_complete(struct xc_sr_context *ctx, unsigned int *missing);
+
 #endif
 /*
  * Local variables:
index bb94cd879d9080b9ed5196e150c9f7b1d577cac2..bc811e6e3a34877fa014a517543444047c05de7d 100644 (file)
@@ -659,6 +659,7 @@ static int buffer_record(struct xc_sr_context *ctx, struct xc_sr_record *rec)
 int handle_static_data_end(struct xc_sr_context *ctx)
 {
     xc_interface *xch = ctx->xch;
+    unsigned int missing = 0;
     int rc = 0;
 
     if ( ctx->restore.seen_static_data_end )
@@ -669,9 +670,13 @@ int handle_static_data_end(struct xc_sr_context *ctx)
 
     ctx->restore.seen_static_data_end = true;
 
+    rc = ctx->restore.ops.static_data_complete(ctx, &missing);
+    if ( rc )
+        return rc;
+
     if ( ctx->restore.callbacks->static_data_done &&
          (rc = ctx->restore.callbacks->static_data_done(
-             ctx->restore.callbacks->data) != 0) )
+             missing, ctx->restore.callbacks->data) != 0) )
         ERROR("static_data_done() callback failed: %d\n", rc);
 
     return rc;
index 1704d524b493944fa6bffca894ba88e4715913d0..a77624cc9ddb876d8421ca0b0e9a3d0326b413fa 100644 (file)
@@ -258,6 +258,7 @@ struct xc_sr_restore_ops restore_ops_x86_hvm =
     .localise_page   = x86_hvm_localise_page,
     .setup           = x86_hvm_setup,
     .process_record  = x86_hvm_process_record,
+    .static_data_complete = x86_static_data_complete,
     .stream_complete = x86_hvm_stream_complete,
     .cleanup         = x86_hvm_cleanup,
 };
index a3d85d517d866c542ee3807272c984d96920747b..d086271efb6d30f1d9c20bb886a60da3983fa52f 100644 (file)
@@ -1194,6 +1194,7 @@ struct xc_sr_restore_ops restore_ops_x86_pv =
     .localise_page   = x86_pv_localise_page,
     .setup           = x86_pv_setup,
     .process_record  = x86_pv_process_record,
+    .static_data_complete = x86_static_data_complete,
     .stream_complete = x86_pv_stream_complete,
     .cleanup         = x86_pv_cleanup,
 };
index cc7340c48db8c8cb7444c2b0bae93c9b307d86ea..75862dc6ed968d431192f80bfcd2d164b3b77fd9 100644 (file)
@@ -1428,7 +1428,8 @@ static void libxl__colo_restore_setup_done(libxl__egc *egc,
     libxl__stream_read_start(egc, &dcs->srs);
 }
 
-int libxl__srm_callout_callback_static_data_done(void *user)
+int libxl__srm_callout_callback_static_data_done(unsigned int missing,
+                                                 void *user)
 {
     libxl__save_helper_state *shs = user;
     libxl__domain_create_state *dcs = shs->caller_state;
@@ -1438,7 +1439,15 @@ int libxl__srm_callout_callback_static_data_done(void *user)
     libxl_domain_config *d_config = dcs->guest_config;
     libxl_domain_build_info *info = &d_config->b_info;
 
-    libxl__cpuid_legacy(ctx, dcs->guest_domid, info);
+    /*
+     * CPUID/MSR information is not present in pre Xen-4.14 streams.
+     *
+     * Libxl used to always regenerate the CPUID policy from first principles
+     * on migrate.  Continue to do so for backwards compatibility when the
+     * stream doesn't contain any CPUID data.
+     */
+    if (missing & XGR_SDD_MISSING_CPUID)
+        libxl__cpuid_legacy(ctx, dcs->guest_domid, info);
 
     return 0;
 }
index 93dc252370ce2019ef2b7cb7264e7678a623cb64..5bfbd4fd10673f245da5927eed460df073a7e3a6 100755 (executable)
@@ -29,7 +29,7 @@ our @msgs = (
     [ 'srcxA',  "wait_checkpoint", [] ],
     [ 'scxA',   "switch_qemu_logdirty",  [qw(uint32_t domid
                                           unsigned enable)] ],
-    [ 'rcxW',   "static_data_done",      [] ],
+    [ 'rcxW',   "static_data_done",      [qw(unsigned missing)] ],
     [ 'rcx',    "restore_results",       ['xen_pfn_t', 'store_gfn',
                                           'xen_pfn_t', 'console_gfn'] ],
     [ 'srW',    "complete",              [qw(int retval