/* callbacks provided by xc_domain_restore */
struct restore_callbacks {
- /* Called once the STATIC_DATA_END record has been received. */
+ /* Called once the STATIC_DATA_END record has been received/inferred. */
int (*static_data_done)(void *data);
/* Called after a new checkpoint to suspend the guest. */
/* Currently buffering records between a checkpoint */
bool buffer_all_records;
- /* Whether a STATIC_DATA_END record has been seen. */
+ /* Whether a STATIC_DATA_END record has been seen/inferred. */
bool seen_static_data_end;
/*
int populate_pfns(struct xc_sr_context *ctx, unsigned int count,
const xen_pfn_t *original_pfns, const uint32_t *types);
+/* Handle a STATIC_DATA_END record. */
+int handle_static_data_end(struct xc_sr_context *ctx);
+
#endif
/*
* Local variables:
xen_pfn_t *pfns = NULL, pfn;
uint32_t *types = NULL, type;
+ /*
+ * v2 compatibility only exists for x86 streams. This is a bit of a
+ * bodge, but it is less bad than duplicating handle_page_data() between
+ * different architectures.
+ */
+#if defined(__i386__) || defined(__x86_64__)
+ /* v2 compat. Infer the position of STATIC_DATA_END. */
+ if ( ctx->restore.format_version < 3 && !ctx->restore.seen_static_data_end )
+ {
+ rc = handle_static_data_end(ctx);
+ if ( rc )
+ {
+ ERROR("Inferred STATIC_DATA_END record failed");
+ goto err;
+ }
+ rc = -1;
+ }
+
+ if ( !ctx->restore.seen_static_data_end )
+ {
+ ERROR("No STATIC_DATA_END seen");
+ goto err;
+ }
+#endif
+
if ( rec->length < sizeof(*pages) )
{
ERROR("PAGE_DATA record truncated: length %u, min %zu",
return 0;
}
-static int handle_static_data_end(struct xc_sr_context *ctx)
+int handle_static_data_end(struct xc_sr_context *ctx)
{
xc_interface *xch = ctx->xch;
int rc = 0;
unsigned int start, end, x, fpp = PAGE_SIZE / ctx->x86.pv.width;
int rc;
+ /* v2 compat. Infer the position of STATIC_DATA_END. */
+ if ( ctx->restore.format_version < 3 && !ctx->restore.seen_static_data_end )
+ {
+ rc = handle_static_data_end(ctx);
+ if ( rc )
+ {
+ ERROR("Inferred STATIC_DATA_END record failed");
+ return rc;
+ }
+ }
+
+ if ( !ctx->restore.seen_static_data_end )
+ {
+ ERROR("No STATIC_DATA_END seen");
+ return -1;
+ }
+
if ( !ctx->x86.pv.restore.seen_pv_info )
{
ERROR("Not yet received X86_PV_INFO record");