[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v5 RFC 12/14] tools/libxc: x86 HVM restore code
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx> Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx> --- tools/libxc/saverestore/common.h | 1 + tools/libxc/saverestore/restore_x86_hvm.c | 280 +++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 tools/libxc/saverestore/restore_x86_hvm.c diff --git a/tools/libxc/saverestore/common.h b/tools/libxc/saverestore/common.h index 9e70ed6..e16e0de 100644 --- a/tools/libxc/saverestore/common.h +++ b/tools/libxc/saverestore/common.h @@ -251,6 +251,7 @@ extern struct save_ops save_ops_x86_pv; extern struct save_ops save_ops_x86_hvm; extern struct restore_ops restore_ops_x86_pv; +extern struct restore_ops restore_ops_x86_hvm; struct record { diff --git a/tools/libxc/saverestore/restore_x86_hvm.c b/tools/libxc/saverestore/restore_x86_hvm.c new file mode 100644 index 0000000..299d77f --- /dev/null +++ b/tools/libxc/saverestore/restore_x86_hvm.c @@ -0,0 +1,280 @@ +#include <assert.h> + +#include "common_x86.h" + +/* TODO: remove */ +static int handle_toolstack(struct context *ctx, struct record *rec) +{ + xc_interface *xch = ctx->xch; + int rc; + + if ( !ctx->restore.callbacks || !ctx->restore.callbacks->toolstack_restore ) + return 0; + + rc = ctx->restore.callbacks->toolstack_restore(ctx->domid, rec->data, rec->length, + ctx->restore.callbacks->data); + if ( rc < 0 ) + PERROR("restoring toolstack"); + return rc; +} + +/* + * Process an HVM_CONTEXT record from the stream. + */ +static int handle_hvm_context(struct context *ctx, struct record *rec) +{ + xc_interface *xch = ctx->xch; + int rc; + + rc = xc_domain_hvm_setcontext(xch, ctx->domid, rec->data, rec->length); + if ( rc < 0 ) + PERROR("Unable to restore HVM context"); + return rc; +} + +/* + * Process an HVM_PARAMS record from the stream. + */ +static int handle_hvm_params(struct context *ctx, struct record *rec) +{ + xc_interface *xch = ctx->xch; + struct rec_hvm_params *hdr = rec->data; + struct 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_mfn = entry->value; + xc_clear_domain_page(xch, ctx->domid, entry->value); + break; + case HVM_PARAM_STORE_PFN: + ctx->restore.xenstore_mfn = 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_set_hvm_param(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; +} + +/* TODO: remove */ +static int dump_qemu(struct context *ctx) +{ + xc_interface *xch = ctx->xch; + char qemusig[21], path[256]; + uint32_t qlen; + void *qbuf = NULL; + int rc = -1; + FILE *fp = NULL; + + if ( read_exact(ctx->fd, qemusig, sizeof(qemusig)) ) + { + PERROR("Error reading QEMU signature"); + goto out; + } + + if ( memcmp(qemusig, "DeviceModelRecord0002", sizeof(qemusig)) ) + { + qemusig[20] = '\0'; + ERROR("Invalid device model state signature %s", qemusig); + goto out; + } + + if ( read_exact(ctx->fd, &qlen, sizeof(qlen)) ) + { + PERROR("Error reading QEMU record length"); + goto out; + } + + qbuf = malloc(qlen); + if ( !qbuf ) + { + PERROR("no memory for device model state"); + goto out; + } + + if ( read_exact(ctx->fd, qbuf, qlen) ) + { + PERROR("Error reading device model state"); + goto out; + } + + sprintf(path, XC_DEVICE_MODEL_RESTORE_FILE".%u", ctx->domid); + fp = fopen(path, "wb"); + if ( !fp ) + { + PERROR("Failed to open '%s' for writing", path); + goto out; + } + + DPRINTF("Writing %u bytes of QEMU data", qlen); + if ( fwrite(qbuf, 1, qlen, fp) != qlen ) + { + PERROR("Failed to write %u bytes of QEMU data", qlen); + goto out; + } + + rc = 0; + + out: + if ( fp ) + fclose(fp); + free(qbuf); + + return rc; +} + +/* + * restore_ops function. + */ +static int x86_hvm_localise_page(struct context *ctx, uint32_t type, void *page) +{ + /* no-op */ + return 0; +} + +/* + * restore_ops function. Confirms the stream matches the domain. + */ +static int x86_hvm_setup(struct context *ctx) +{ + xc_interface *xch = ctx->xch; + + if ( ctx->restore.guest_type != DHDR_TYPE_X86_HVM ) + { + ERROR("Unable to restore %s domain into an x86_hvm domain", + dhdr_type_to_str(ctx->restore.guest_type)); + return -1; + } + else if ( ctx->restore.guest_page_size != PAGE_SIZE ) + { + ERROR("Invalid page size %d for x86_hvm domains", + ctx->restore.guest_page_size); + return -1; + } + + return 0; +} + +/* + * restore_ops function. + */ +static int x86_hvm_process_record(struct context *ctx, struct record *rec) +{ + xc_interface *xch = ctx->xch; + + switch ( rec->type ) + { + case REC_TYPE_TSC_INFO: + return handle_tsc_info(ctx, rec); + + case REC_TYPE_HVM_CONTEXT: + return handle_hvm_context(ctx, rec); + + case REC_TYPE_HVM_PARAMS: + return handle_hvm_params(ctx, rec); + + case REC_TYPE_TOOLSTACK: + return handle_toolstack(ctx, rec); + + default: + if ( rec->type & REC_TYPE_OPTIONAL ) + { + IPRINTF("Ignoring optional record (0x%"PRIx32", %s)", + rec->type, rec_type_to_str(rec->type)); + return 0; + } + + ERROR("Invalid record type (0x%"PRIx32", %s) for x86_hvm domains", + rec->type, rec_type_to_str(rec->type)); + return -1; + } +} + +/* + * restore_ops function. Sets extra hvm parameters and seeds the grant table. + */ +static int x86_hvm_stream_complete(struct context *ctx) +{ + xc_interface *xch = ctx->xch; + int rc; + + rc = xc_set_hvm_param(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_dom_gnttab_hvm_seed(xch, ctx->domid, + ctx->restore.console_mfn, + ctx->restore.xenstore_mfn, + ctx->restore.console_domid, + ctx->restore.xenstore_domid); + if ( rc ) + { + PERROR("Failed to seed grant table"); + return rc; + } + + /* + * FIXME: reading the device model state from the stream should be + * done by libxl. + */ + rc = dump_qemu(ctx); + if ( rc ) + { + ERROR("Failed to dump qemu"); + return rc; + } + + return rc; +} + +static int x86_hvm_cleanup(struct context *ctx) +{ + /* no-op */ + return 0; +} + +struct restore_ops restore_ops_x86_hvm = +{ + .localise_page = x86_hvm_localise_page, + .setup = x86_hvm_setup, + .process_record = x86_hvm_process_record, + .stream_complete = x86_hvm_stream_complete, + .cleanup = x86_hvm_cleanup, +}; + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |