aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_domain_restore.c
diff options
context:
space:
mode:
authorPaul Durrant <paul.durrant@citrix.com>2011-12-16 14:54:14 +0000
committerPaul Durrant <paul.durrant@citrix.com>2011-12-16 14:54:14 +0000
commit8f76fc6c983e3bf7c8c32fae2c7264f718e2b467 (patch)
treea279f798e76580f86bffe3f632a0eb276859665d /tools/libxc/xc_domain_restore.c
parentbe9b274df12d03fe2366fdbb58a37f537c3d2ff1 (diff)
downloadxen-8f76fc6c983e3bf7c8c32fae2c7264f718e2b467.tar.gz
xen-8f76fc6c983e3bf7c8c32fae2c7264f718e2b467.tar.bz2
xen-8f76fc6c983e3bf7c8c32fae2c7264f718e2b467.zip
tools: VM generation ID save/restore and migrate.
Add code to track the address of the VM generation ID buffer across a save/restore or migrate, and increment it as necessary. The address of the buffer is written into xenstore by hvmloader at boot time. It must be read from xenstore by the caller of xc_domain_save() and then written back again by the caller of xc_domain_restore(). Note that the changes to xc_save.c and xc_restore.c are merely sufficient for them to build. Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Committed-by: Ian Jackson <ian.jackson.citrix.com>
Diffstat (limited to 'tools/libxc/xc_domain_restore.c')
-rw-r--r--tools/libxc/xc_domain_restore.c49
1 files changed, 48 insertions, 1 deletions
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 */
}