@@ -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);
@@ -159,6 +159,15 @@ struct xc_sr_restore_ops
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.
*/
@@ -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
@@ -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:
@@ -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;
@@ -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,
};
@@ -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,
};
@@ -1308,7 +1308,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;
@@ -1318,7 +1319,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;
}
@@ -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
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> --- CC: Ian Jackson <Ian.Jackson@citrix.com> CC: Wei Liu <wl@xen.org> CC: Anthony PERARD <anthony.perard@citrix.com> v2: * Split/rearrange from v1 * Don't re-evalute 'k' on migrate v2.1: * Rebase over libxl__cpuid_legacy() changes --- tools/libxc/include/xenguest.h | 12 ++++++++++-- tools/libxc/xc_sr_common.h | 9 +++++++++ tools/libxc/xc_sr_common_x86.c | 8 ++++++++ tools/libxc/xc_sr_common_x86.h | 5 +++++ tools/libxc/xc_sr_restore.c | 7 ++++++- tools/libxc/xc_sr_restore_x86_hvm.c | 1 + tools/libxc/xc_sr_restore_x86_pv.c | 1 + tools/libxl/libxl_create.c | 13 +++++++++++-- tools/libxl/libxl_save_msgs_gen.pl | 2 +- 9 files changed, 52 insertions(+), 6 deletions(-)