/* * restore_ops function. Sets extra hvm parameters and seeds the grant table. */ static int x86_hvm_stream_complete(struct xc_sr_context *ctx) { xc_interface *xch = ctx->xch; int rc; rc = xc_hvm_param_set(xch, ctx->domid, HVM_PARAM_STORE_EVTCHN, ctx->restore.xenstore_evtchn); if ( rc ) { PERROR("Failed to set HVM_PARAM_STORE_EVTCHN"); return rc; } rc = xc_hvm_param_set(xch, ctx->domid, HVM_PARAM_CONSOLE_EVTCHN, ctx->restore.console_evtchn); if ( rc ) { PERROR("Failed to set HVM_PARAM_CONSOLE_EVTCHN"); return rc; } rc = xc_domain_hvm_setcontext(xch, ctx->domid, ctx->x86_hvm.restore.context, ctx->x86_hvm.restore.contextsz); if ( rc < 0 ) { PERROR("Unable to restore HVM context"); return rc; } rc = xc_dom_gnttab_hvm_seed(xch, ctx->domid, ctx->restore.console_gfn, ctx->restore.xenstore_gfn, ctx->restore.console_domid, ctx->restore.xenstore_domid); if ( rc ) { PERROR("Failed to seed grant table"); return rc; } #ifdef XG_LIBXL_HVM_COMPAT rc = handle_qemu(ctx); if ( rc ) { ERROR("Failed to dump qemu"); return rc; } #endif return rc; }
/* * Process an HVM_PARAMS record from the stream. */ static int handle_hvm_params(struct xc_sr_context *ctx, struct xc_sr_record *rec) { xc_interface *xch = ctx->xch; struct xc_sr_rec_hvm_params *hdr = rec->data; struct xc_sr_rec_hvm_params_entry *entry = hdr->param; unsigned int i; int rc; if ( rec->length < sizeof(*hdr) || rec->length < sizeof(*hdr) + hdr->count * sizeof(*entry) ) { ERROR("hvm_params record is too short"); return -1; } for ( i = 0; i < hdr->count; i++, entry++ ) { switch ( entry->index ) { case HVM_PARAM_CONSOLE_PFN: ctx->restore.console_gfn = entry->value; xc_clear_domain_page(xch, ctx->domid, entry->value); break; case HVM_PARAM_STORE_PFN: ctx->restore.xenstore_gfn = entry->value; xc_clear_domain_page(xch, ctx->domid, entry->value); break; case HVM_PARAM_IOREQ_PFN: case HVM_PARAM_BUFIOREQ_PFN: xc_clear_domain_page(xch, ctx->domid, entry->value); break; } rc = xc_hvm_param_set(xch, ctx->domid, entry->index, entry->value); if ( rc < 0 ) { PERROR("set HVM param %"PRId64" = 0x%016"PRIx64, entry->index, entry->value); return rc; } } return 0; }
/* * Process an HVM_PARAMS record from the stream. */ static int handle_hvm_params(struct xc_sr_context *ctx, struct xc_sr_record *rec) { xc_interface *xch = ctx->xch; struct xc_sr_rec_hvm_params *hdr = rec->data; struct xc_sr_rec_hvm_params_entry *entry = hdr->param; unsigned int i; int rc; if ( rec->length < sizeof(*hdr) ) { ERROR("HVM_PARAMS record truncated: length %u, header size %zu", rec->length, sizeof(*hdr)); return -1; } if ( rec->length != (sizeof(*hdr) + hdr->count * sizeof(*entry)) ) { ERROR("HVM_PARAMS record truncated: header %zu, count %u, " "expected len %zu, got %u", sizeof(*hdr), hdr->count, hdr->count * sizeof(*entry), rec->length); return -1; } /* * Tolerate empty records. Older sending sides used to accidentally * generate them. */ if ( hdr->count == 0 ) { DBGPRINTF("Skipping empty HVM_PARAMS record\n"); return 0; } for ( i = 0; i < hdr->count; i++, entry++ ) { switch ( entry->index ) { case HVM_PARAM_CONSOLE_PFN: ctx->restore.console_gfn = entry->value; xc_clear_domain_page(xch, ctx->domid, entry->value); break; case HVM_PARAM_STORE_PFN: ctx->restore.xenstore_gfn = entry->value; xc_clear_domain_page(xch, ctx->domid, entry->value); break; case HVM_PARAM_IOREQ_PFN: case HVM_PARAM_BUFIOREQ_PFN: xc_clear_domain_page(xch, ctx->domid, entry->value); break; } rc = xc_hvm_param_set(xch, ctx->domid, entry->index, entry->value); if ( rc < 0 ) { PERROR("set HVM param %"PRId64" = 0x%016"PRIx64, entry->index, entry->value); return rc; } } return 0; }