diff --git a/tools/libxc/include/xenguest.h b/tools/libxc/include/xenguest.h
index b4df8d0ffe..7a12d21ff2 100644
--- a/tools/libxc/include/xenguest.h
+++ b/tools/libxc/include/xenguest.h
@@ -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);
diff --git a/tools/libxc/xc_sr_common.h b/tools/libxc/xc_sr_common.h
index 7742260690..f3bdea8006 100644
--- a/tools/libxc/xc_sr_common.h
+++ b/tools/libxc/xc_sr_common.h
@@ -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.
      */
diff --git a/tools/libxc/xc_sr_common_x86.c b/tools/libxc/xc_sr_common_x86.c
index 6267655dab..a849891634 100644
--- a/tools/libxc/xc_sr_common_x86.c
+++ b/tools/libxc/xc_sr_common_x86.c
@@ -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
diff --git a/tools/libxc/xc_sr_common_x86.h b/tools/libxc/xc_sr_common_x86.h
index d1050981dd..e08d81e0e7 100644
--- a/tools/libxc/xc_sr_common_x86.h
+++ b/tools/libxc/xc_sr_common_x86.h
@@ -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:
diff --git a/tools/libxc/xc_sr_restore.c b/tools/libxc/xc_sr_restore.c
index bb94cd879d..bc811e6e3a 100644
--- a/tools/libxc/xc_sr_restore.c
+++ b/tools/libxc/xc_sr_restore.c
@@ -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;
diff --git a/tools/libxc/xc_sr_restore_x86_hvm.c b/tools/libxc/xc_sr_restore_x86_hvm.c
index cef99e0397..9190edaee7 100644
--- a/tools/libxc/xc_sr_restore_x86_hvm.c
+++ b/tools/libxc/xc_sr_restore_x86_hvm.c
@@ -248,6 +248,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,
 };
diff --git a/tools/libxc/xc_sr_restore_x86_pv.c b/tools/libxc/xc_sr_restore_x86_pv.c
index 3aac4bd502..1252cd1310 100644
--- a/tools/libxc/xc_sr_restore_x86_pv.c
+++ b/tools/libxc/xc_sr_restore_x86_pv.c
@@ -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,
 };
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 09f84858d5..1d54cdc429 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -1298,7 +1298,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;
@@ -1308,9 +1309,18 @@ int libxl__srm_callout_callback_static_data_done(void *user)
     const libxl_domain_config *d_config = dcs->guest_config;
     const libxl_domain_build_info *info = &d_config->b_info;
 
-    libxl__cpuid_apply_policy(ctx, dcs->guest_domid);
-    if (info->cpuid != NULL)
-        libxl__cpuid_set(ctx, dcs->guest_domid, info->cpuid);
+    /*
+     * 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_apply_policy(ctx, dcs->guest_domid);
+        if (info->cpuid != NULL)
+            libxl__cpuid_set(ctx, dcs->guest_domid, info->cpuid);
+    }
 
     return 0;
 }
diff --git a/tools/libxl/libxl_save_msgs_gen.pl b/tools/libxl/libxl_save_msgs_gen.pl
index 93dc252370..5bfbd4fd10 100755
--- a/tools/libxl/libxl_save_msgs_gen.pl
+++ b/tools/libxl/libxl_save_msgs_gen.pl
@@ -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
