aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_restore.c4
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_save.c3
-rw-r--r--tools/libxc/xc_domain_restore.c49
-rw-r--r--tools/libxc/xc_domain_save.c13
-rw-r--r--tools/libxc/xenguest.h9
-rw-r--r--tools/libxc/xg_save_restore.h1
-rw-r--r--tools/libxl/libxl_create.c1
-rw-r--r--tools/libxl/libxl_dom.c35
-rw-r--r--tools/libxl/libxl_internal.h1
-rw-r--r--tools/libxl/libxl_types.idl1
-rw-r--r--tools/libxl/xl_cmdimpl.c6
-rw-r--r--tools/python/xen/lowlevel/checkpoint/libcheckpoint.c15
-rw-r--r--tools/xcutils/xc_restore.c3
-rw-r--r--tools/xcutils/xc_save.c2
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);