diff options
-rw-r--r-- | tools/libxc/ia64/xc_ia64_linux_restore.c | 4 | ||||
-rw-r--r-- | tools/libxc/ia64/xc_ia64_linux_save.c | 3 | ||||
-rw-r--r-- | tools/libxc/xc_domain_restore.c | 49 | ||||
-rw-r--r-- | tools/libxc/xc_domain_save.c | 13 | ||||
-rw-r--r-- | tools/libxc/xenguest.h | 9 | ||||
-rw-r--r-- | tools/libxc/xg_save_restore.h | 1 | ||||
-rw-r--r-- | tools/libxl/libxl_create.c | 1 | ||||
-rw-r--r-- | tools/libxl/libxl_dom.c | 35 | ||||
-rw-r--r-- | tools/libxl/libxl_internal.h | 1 | ||||
-rw-r--r-- | tools/libxl/libxl_types.idl | 1 | ||||
-rw-r--r-- | tools/libxl/xl_cmdimpl.c | 6 | ||||
-rw-r--r-- | tools/python/xen/lowlevel/checkpoint/libcheckpoint.c | 15 | ||||
-rw-r--r-- | tools/xcutils/xc_restore.c | 3 | ||||
-rw-r--r-- | tools/xcutils/xc_save.c | 2 |
14 files changed, 130 insertions, 13 deletions
diff --git a/tools/libxc/ia64/xc_ia64_linux_restore.c b/tools/libxc/ia64/xc_ia64_linux_restore.c index 5a915aa993..d199cbfac4 100644 --- a/tools/libxc/ia64/xc_ia64_linux_restore.c +++ b/tools/libxc/ia64/xc_ia64_linux_restore.c @@ -548,7 +548,9 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, unsigned int store_evtchn, unsigned long *store_mfn, unsigned int console_evtchn, unsigned long *console_mfn, - unsigned int hvm, unsigned int pae, int superpages) + unsigned int hvm, unsigned int pae, int superpages, + int no_incr_generationid, + unsigned long *vm_generationid_addr) { DECLARE_DOMCTL; int rc = 1; diff --git a/tools/libxc/ia64/xc_ia64_linux_save.c b/tools/libxc/ia64/xc_ia64_linux_save.c index 52b37f1017..5bb988cbd7 100644 --- a/tools/libxc/ia64/xc_ia64_linux_save.c +++ b/tools/libxc/ia64/xc_ia64_linux_save.c @@ -382,7 +382,8 @@ out: int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t max_factor, uint32_t flags, - struct save_callbacks* callbacks, int hvm) + struct save_callbacks* callbacks, int hvm, + unsigned long vm_generationid_addr) { DECLARE_DOMCTL; xc_dominfo_t info; diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index 14451d1a59..3fda6f8c68 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -681,6 +681,7 @@ typedef struct { uint64_t console_pfn; uint64_t acpi_ioport_location; uint64_t viridian; + uint64_t vm_generationid_addr; } pagebuf_t; static int pagebuf_init(pagebuf_t* buf) @@ -860,6 +861,17 @@ static int pagebuf_get_one(xc_interface *xch, struct restore_ctx *ctx, } return compbuf_size; + case XC_SAVE_ID_HVM_GENERATION_ID_ADDR: + /* Skip padding 4 bytes then read the generation id buffer location. */ + if ( RDEXACT(fd, &buf->vm_generationid_addr, sizeof(uint32_t)) || + RDEXACT(fd, &buf->vm_generationid_addr, sizeof(uint64_t)) ) + { + PERROR("error read the generation id buffer location"); + return -1; + } + DPRINTF("read generation id buffer address"); + return pagebuf_get_one(xch, ctx, buf, fd, dom); + default: if ( (count > MAX_BATCH_SIZE) || (count < 0) ) { ERROR("Max batch size exceeded (%d). Giving up.", count); @@ -1248,7 +1260,9 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx, int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, unsigned int store_evtchn, unsigned long *store_mfn, unsigned int console_evtchn, unsigned long *console_mfn, - unsigned int hvm, unsigned int pae, int superpages) + unsigned int hvm, unsigned int pae, int superpages, + int no_incr_generationid, + unsigned long *vm_generationid_addr) { DECLARE_DOMCTL; int rc = 1, frc, i, j, n, m, pae_extended_cr3 = 0, ext_vcpucontext = 0; @@ -1449,6 +1463,39 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, xc_set_hvm_param(xch, dom, HVM_PARAM_VM86_TSS, pagebuf.vm86_tss); if ( pagebuf.console_pfn ) console_pfn = pagebuf.console_pfn; + if ( pagebuf.vm_generationid_addr ) { + if ( !no_incr_generationid ) { + unsigned int offset; + unsigned char *buf; + unsigned long long generationid; + + /* + * Map the VM generation id buffer and inject the new value. + */ + + pfn = pagebuf.vm_generationid_addr >> PAGE_SHIFT; + offset = pagebuf.vm_generationid_addr & (PAGE_SIZE - 1); + + if ( (pfn >= dinfo->p2m_size) || + (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) ) + { + ERROR("generation id buffer frame is bad"); + goto out; + } + + mfn = ctx->p2m[pfn]; + buf = xc_map_foreign_range(xch, dom, PAGE_SIZE, + PROT_READ | PROT_WRITE, mfn); + + generationid = *(unsigned long long *)(buf + offset); + *(unsigned long long *)(buf + offset) = generationid + 1; + + munmap(buf, PAGE_SIZE); + } + + *vm_generationid_addr = pagebuf.vm_generationid_addr; + } + break; /* our work here is done */ } diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c index a6bb89475f..f473dd7c5c 100644 --- a/tools/libxc/xc_domain_save.c +++ b/tools/libxc/xc_domain_save.c @@ -804,7 +804,8 @@ static int save_tsc_info(xc_interface *xch, uint32_t dom, int io_fd) int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t max_factor, uint32_t flags, - struct save_callbacks* callbacks, int hvm) + struct save_callbacks* callbacks, int hvm, + unsigned long vm_generationid_addr) { xc_dominfo_t info; DECLARE_DOMCTL; @@ -1616,6 +1617,16 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter uint64_t data; } chunk = { 0, }; + chunk.id = XC_SAVE_ID_HVM_GENERATION_ID_ADDR; + chunk.data = vm_generationid_addr; + + if ( (chunk.data != 0) && + wrexact(io_fd, &chunk, sizeof(chunk)) ) + { + PERROR("Error when writing the generation id buffer location for guest"); + goto out; + } + chunk.id = XC_SAVE_ID_HVM_IDENT_PT; chunk.data = 0; xc_get_hvm_param(xch, dom, HVM_PARAM_IDENT_PT, diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 4475ee92ee..60263709ce 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -58,7 +58,8 @@ struct save_callbacks { */ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */, - struct save_callbacks* callbacks, int hvm); + struct save_callbacks* callbacks, int hvm, + unsigned long vm_generationid_addr); /** @@ -72,12 +73,16 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter * @parm hvm non-zero if this is a HVM restore * @parm pae non-zero if this HVM domain has PAE support enabled * @parm superpages non-zero to allocate guest memory with superpages + * @parm no_incr_generationid non-zero if generation id is NOT to be incremented + * @parm vm_generationid_addr returned with the address of the generation id buffer * @return 0 on success, -1 on failure */ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, unsigned int store_evtchn, unsigned long *store_mfn, unsigned int console_evtchn, unsigned long *console_mfn, - unsigned int hvm, unsigned int pae, int superpages); + unsigned int hvm, unsigned int pae, int superpages, + int no_incr_generationid, + unsigned long *vm_generationid_addr); /** * xc_domain_restore writes a file to disk that contains the device * model saved state. diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h index c5e0743dcf..6286b6814a 100644 --- a/tools/libxc/xg_save_restore.h +++ b/tools/libxc/xg_save_restore.h @@ -253,6 +253,7 @@ #define XC_SAVE_ID_HVM_VIRIDIAN -11 #define XC_SAVE_ID_COMPRESSED_DATA -12 /* Marker to indicate arrival of compressed data */ #define XC_SAVE_ID_ENABLE_COMPRESSION -13 /* Marker to enable compression logic at receiver side */ +#define XC_SAVE_ID_HVM_GENERATION_ID_ADDR -14 /* ** We process save/restore/migrate in batches of pages; the below diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index c0eaff5ef8..7b6a2f92d2 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -99,6 +99,7 @@ int libxl_init_build_info(libxl_ctx *ctx, b_info->u.hvm.vpt_align = 1; b_info->u.hvm.timer_mode = 1; b_info->u.hvm.nested_hvm = 0; + b_info->u.hvm.no_incr_generationid = 0; break; case LIBXL_DOMAIN_TYPE_PV: b_info->u.pv.slack_memkb = 8 * 1024; diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index c898d89773..a4725fea32 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -106,6 +106,7 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid, state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, 0); state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, 0); + state->vm_generationid_addr = 0; return 0; } @@ -117,7 +118,7 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid, libxl_ctx *ctx = libxl__gc_owner(gc); char *dom_path, *vm_path; xs_transaction_t t; - char **ents; + char **ents, **hvm_ents; int i; libxl_cpuid_apply_policy(ctx, domid); @@ -143,6 +144,13 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid, ? "offline" : "online"; } + hvm_ents = NULL; + if (info->type == LIBXL_DOMAIN_TYPE_HVM) { + hvm_ents = libxl__calloc(gc, 3, sizeof(char *)); + hvm_ents[0] = "hvmloader/generation-id-address"; + hvm_ents[1] = libxl__sprintf(gc, "0x%lx", state->vm_generationid_addr); + } + dom_path = libxl__xs_get_dompath(gc, domid); if (!dom_path) { return ERROR_FAIL; @@ -153,6 +161,9 @@ retry_transaction: t = xs_transaction_start(ctx->xsh); libxl__xs_writev(gc, t, dom_path, ents); + if (info->type == LIBXL_DOMAIN_TYPE_HVM) + libxl__xs_writev(gc, t, dom_path, hvm_ents); + libxl__xs_writev(gc, t, dom_path, local_ents); libxl__xs_writev(gc, t, vm_path, vms_ents); @@ -356,16 +367,19 @@ int libxl__domain_restore_common(libxl__gc *gc, uint32_t domid, /* read signature */ int rc; int hvm, pae, superpages; + int no_incr_generationid; switch (info->type) { case LIBXL_DOMAIN_TYPE_HVM: hvm = 1; superpages = 1; pae = info->u.hvm.pae; + no_incr_generationid = info->u.hvm.no_incr_generationid; break; case LIBXL_DOMAIN_TYPE_PV: hvm = 0; superpages = 0; pae = 1; + no_incr_generationid = 0; break; default: return ERROR_INVAL; @@ -373,7 +387,8 @@ int libxl__domain_restore_common(libxl__gc *gc, uint32_t domid, rc = xc_domain_restore(ctx->xch, fd, domid, state->store_port, &state->store_mfn, state->console_port, &state->console_mfn, - hvm, pae, superpages); + hvm, pae, superpages, no_incr_generationid, + &state->vm_generationid_addr); if ( rc ) { LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "restoring domain"); return ERROR_FAIL; @@ -538,12 +553,23 @@ int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd, struct save_callbacks callbacks; struct suspendinfo si; int hvm, rc = ERROR_FAIL; + unsigned long vm_generationid_addr; switch (type) { - case LIBXL_DOMAIN_TYPE_HVM: + case LIBXL_DOMAIN_TYPE_HVM: { + char *path; + char *addr; + + path = libxl__sprintf(gc, "%s/hvmloader/generation-id-address", + libxl__xs_get_dompath(gc, domid)); + addr = libxl__xs_read(gc, XBT_NULL, path); + + vm_generationid_addr = (addr) ? strtoul(addr, NULL, 0) : 0; hvm = 1; break; + } case LIBXL_DOMAIN_TYPE_PV: + vm_generationid_addr = 0; hvm = 0; break; default: @@ -581,7 +607,8 @@ int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd, callbacks.switch_qemu_logdirty = libxl__domain_suspend_common_switch_qemu_logdirty; callbacks.data = &si; - rc = xc_domain_save(ctx->xch, fd, domid, 0, 0, flags, &callbacks, hvm); + rc = xc_domain_save(ctx->xch, fd, domid, 0, 0, flags, &callbacks, + hvm, vm_generationid_addr); if ( rc ) { LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "saving domain: %s", si.guest_responded ? diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 070bae15c3..288c03cbde 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -223,6 +223,7 @@ typedef struct { uint32_t console_port; unsigned long console_mfn; + unsigned long vm_generationid_addr; } libxl__domain_build_state; _hidden int libxl__build_pre(libxl__gc *gc, uint32_t domid, diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 78a1cc6c45..574dec752a 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -184,6 +184,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("vpt_align", bool), ("timer_mode", integer), ("nested_hvm", bool), + ("no_incr_generationid", bool), ])), ("pv", Struct(None, [("kernel", libxl_file_reference), ("slack_memkb", uint32), diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 8da8b88a33..8c30de1884 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -360,6 +360,8 @@ static void printf_info(int domid, printf("\t\t\t(vpt_align %d)\n", b_info->u.hvm.vpt_align); printf("\t\t\t(timer_mode %d)\n", b_info->u.hvm.timer_mode); printf("\t\t\t(nestedhvm %d)\n", b_info->u.hvm.nested_hvm); + printf("\t\t\t(no_incr_generationid %d)\n", + b_info->u.hvm.no_incr_generationid); printf("\t\t\t(device_model %s)\n", dm_info->device_model ? : "default"); printf("\t\t\t(videoram %d)\n", dm_info->videoram); @@ -1364,6 +1366,7 @@ struct domain_create { const char *restore_file; int migrate_fd; /* -1 means none */ char **migration_domname_r; /* from malloc */ + int no_incr_generationid; }; static int freemem(libxl_domain_build_info *b_info, libxl_device_model_info *dm_info) @@ -1577,6 +1580,8 @@ static int create_domain(struct domain_create *dom_info) } } + d_config.b_info.u.hvm.no_incr_generationid = dom_info->no_incr_generationid; + if (debug || dom_info->dryrun) printf_info(-1, &d_config, &d_config.dm_info); @@ -2817,6 +2822,7 @@ static void migrate_receive(int debug, int daemonize, int monitor) dom_info.restore_file = "incoming migration stream"; dom_info.migrate_fd = 0; /* stdin */ dom_info.migration_domname_r = &migration_domname; + dom_info.no_incr_generationid = 1; rc = create_domain(&dom_info); if (rc < 0) { diff --git a/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c b/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c index aefc1cb31b..0fc433fcf9 100644 --- a/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c +++ b/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c @@ -175,6 +175,7 @@ int checkpoint_start(checkpoint_state* s, int fd, { int hvm, rc; int flags = XCFLAGS_LIVE; + unsigned long vm_generationid_addr; if (!s->domid) { s->errstr = "checkpoint state not opened"; @@ -185,16 +186,28 @@ int checkpoint_start(checkpoint_state* s, int fd, hvm = s->domtype > dt_pv; if (hvm) { + char path[128]; + char *addr; + + sprintf(path, "/local/domain/%u/hvmloader/generation-id-address", s->domid); + addr = xs_read(s->xsh, XBT_NULL, path, NULL); + + vm_generationid_addr = (addr) ? strtoul(addr, NULL, 0) : 0; + free(addr); + flags |= XCFLAGS_HVM; if (switch_qemu_logdirty(s, 1)) return -1; + } else { + vm_generationid_addr = 0; } if (remus_flags & CHECKPOINT_FLAGS_COMPRESSION) flags |= XCFLAGS_CHECKPOINT_COMPRESS; callbacks->switch_qemu_logdirty = noop_switch_logdirty; - rc = xc_domain_save(s->xch, fd, s->domid, 0, 0, flags, callbacks, hvm); + rc = xc_domain_save(s->xch, fd, s->domid, 0, 0, flags, callbacks, hvm, + vm_generationid_addr); if (hvm) switch_qemu_logdirty(s, 0); diff --git a/tools/xcutils/xc_restore.c b/tools/xcutils/xc_restore.c index 985cbecb11..63d53a88b0 100644 --- a/tools/xcutils/xc_restore.c +++ b/tools/xcutils/xc_restore.c @@ -46,7 +46,8 @@ main(int argc, char **argv) superpages = !!hvm; ret = xc_domain_restore(xch, io_fd, domid, store_evtchn, &store_mfn, - console_evtchn, &console_mfn, hvm, pae, superpages); + console_evtchn, &console_mfn, hvm, pae, superpages, + 0, NULL); if ( ret == 0 ) { diff --git a/tools/xcutils/xc_save.c b/tools/xcutils/xc_save.c index debb1bb89e..252759ea95 100644 --- a/tools/xcutils/xc_save.c +++ b/tools/xcutils/xc_save.c @@ -208,7 +208,7 @@ main(int argc, char **argv) callbacks.suspend = suspend; callbacks.switch_qemu_logdirty = switch_qemu_logdirty; ret = xc_domain_save(si.xch, io_fd, si.domid, maxit, max_f, si.flags, - &callbacks, !!(si.flags & XCFLAGS_HVM)); + &callbacks, !!(si.flags & XCFLAGS_HVM), 0); if (si.suspend_evtchn > 0) xc_suspend_evtchn_release(si.xch, si.xce, si.domid, si.suspend_evtchn); |