[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [XEN][RFC PATCH V2 11/17] xc: modify save/restore to support multiple device models



    - add save/restore new special pages and remove unused
    - modify save file structure to allow multiple qemu states

Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
---
 tools/libxc/xc_domain_restore.c |  150 +++++++++++++++++++++++++++++----------
 tools/libxc/xc_domain_save.c    |    6 +-
 2 files changed, 116 insertions(+), 40 deletions(-)

diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index 3fe2b12..9a49ee2 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -103,6 +103,9 @@ static ssize_t rdexact(xc_interface *xch, struct 
restore_ctx *ctx,
 #else
 #define RDEXACT read_exact
 #endif
+
+#define QEMUSIG_SIZE 21
+
 /*
 ** In the state file (or during transfer), all page-table pages are
 ** converted into a 'canonical' form where references to actual mfns
@@ -342,8 +345,11 @@ typedef struct {
                 uint32_t version;
                 uint64_t len;
             } qemuhdr;
-            uint32_t qemubufsize;
-            uint8_t* qemubuf;
+            uint32_t num_dms;
+            struct devmodel_buffer {
+                uint32_t size;
+                uint8_t* buf;
+            } *dmsbuf;
         } hvm;
     } u;
 } tailbuf_t;
@@ -392,63 +398,112 @@ static int compat_buffer_qemu(xc_interface *xch, struct 
restore_ctx *ctx,
         return -1;
     }
 
-    buf->qemubuf = qbuf;
-    buf->qemubufsize = dlen;
+    if ( !(buf->dmsbuf = calloc(1, sizeof(*buf->dmsbuf))) ) {
+        ERROR("Error allocating Device Model buffer");
+        free(qbuf);
+        return -1;
+    }
+
+    buf->dmsbuf[0].buf = qbuf;
+    buf->dmsbuf[0].size = dlen;
+    buf->num_dms = 1;
 
     return 0;
 }
 
 static int buffer_qemu(xc_interface *xch, struct restore_ctx *ctx,
-                       int fd, struct tailbuf_hvm *buf)
+                       uint32_t dmid, int fd, struct tailbuf_hvm *buf)
 {
     uint32_t qlen;
     uint8_t *tmp;
+    struct devmodel_buffer *dmb = &buf->dmsbuf[dmid];
 
     if ( RDEXACT(fd, &qlen, sizeof(qlen)) ) {
-        PERROR("Error reading QEMU header length");
+        PERROR("Error reading Device Model %u header length", dmid);
         return -1;
     }
 
-    if ( qlen > buf->qemubufsize ) {
-        if ( buf->qemubuf) {
-            tmp = realloc(buf->qemubuf, qlen);
+    if ( qlen > dmb->size ) {
+        if ( dmb->buf ) {
+            tmp = realloc(dmb->buf, qlen);
             if ( tmp )
-                buf->qemubuf = tmp;
+                dmb->buf = tmp;
             else {
-                ERROR("Error reallocating QEMU state buffer");
+                ERROR("Error reallocating Device Model %u state buffer", dmid);
                 return -1;
             }
         } else {
-            buf->qemubuf = malloc(qlen);
-            if ( !buf->qemubuf ) {
-                ERROR("Error allocating QEMU state buffer");
+            dmb->buf = malloc(qlen);
+            if ( !dmb->buf ) {
+                ERROR("Error allocating Device Model %u state buffer", dmid);
                 return -1;
             }
         }
     }
-    buf->qemubufsize = qlen;
+    dmb->size = qlen;
 
-    if ( RDEXACT(fd, buf->qemubuf, buf->qemubufsize) ) {
-        PERROR("Error reading QEMU state");
+    if ( RDEXACT(fd, dmb->buf, dmb->size) ) {
+        PERROR("Error reading Device Model %u state", dmid);
         return -1;
     }
 
     return 0;
 }
 
-static int dump_qemu(xc_interface *xch, uint32_t dom, struct tailbuf_hvm *buf)
+static int buffer_device_models(xc_interface *xch, struct restore_ctx *ctx,
+                                int fd, struct tailbuf_hvm *buf)
+{
+    uint32_t i, num_dms;
+    unsigned char qemusig[QEMUSIG_SIZE + 1];
+    int ret = 0;
+
+    if ( RDEXACT(fd, &num_dms, sizeof(num_dms)) ) {
+        PERROR("Error reading num dms");
+        return -1;
+    }
+
+    if ( !(buf->dmsbuf = calloc(num_dms, sizeof (*buf->dmsbuf))) ) {
+        PERROR("Error allocating Device Model buffers");
+        return -1;
+    }
+
+    buf->num_dms = num_dms;
+
+    for ( i = 0; i < num_dms; i++ ) {
+        if ( RDEXACT(fd, qemusig, QEMUSIG_SIZE) ) {
+            PERROR("Error reading Device Model %u signature", i);
+            return -1;
+        }
+
+        if ( memcmp(qemusig, "DeviceModelRecord0002", QEMUSIG_SIZE) ) {
+            qemusig[QEMUSIG_SIZE] = '\0';
+            ERROR("Invalid Device Model %u signature: %s", i, qemusig);
+            return -1;
+        }
+
+        ret = buffer_qemu(xch, ctx, i, fd, buf);
+        if ( ret )
+            return ret;
+    }
+
+    return 0;
+}
+
+static int dump_qemu(xc_interface *xch, uint32_t dom,
+                     uint32_t dmid, struct tailbuf_hvm *buf)
 {
     int saved_errno;
     char path[256];
     FILE *fp;
+    struct devmodel_buffer *dmb = &buf->dmsbuf[dmid];
 
-    sprintf(path, XC_DEVICE_MODEL_RESTORE_FILE".%u", dom);
+    sprintf(path, XC_DEVICE_MODEL_RESTORE_FILE".%u.%u", dom, dmid);
     fp = fopen(path, "wb");
     if ( !fp )
         return -1;
 
-    DPRINTF("Writing %d bytes of QEMU data\n", buf->qemubufsize);
-    if ( fwrite(buf->qemubuf, 1, buf->qemubufsize, fp) != buf->qemubufsize) {
+    DPRINTF("Writing %d bytes of Device Model %u data\n", dmb->size, dmid);
+    if ( fwrite(dmb->buf, 1, dmb->size, fp) != dmb->size ) {
         saved_errno = errno;
         fclose(fp);
         errno = saved_errno;
@@ -467,7 +522,7 @@ static int buffer_tail_hvm(xc_interface *xch, struct 
restore_ctx *ctx,
                            int vcpuextstate, uint32_t vcpuextstate_size)
 {
     uint8_t *tmp;
-    unsigned char qemusig[21];
+    unsigned char qemusig[QEMUSIG_SIZE + 1];
 
     if ( RDEXACT(fd, buf->magicpfns, sizeof(buf->magicpfns)) ) {
         PERROR("Error reading magic PFNs");
@@ -504,7 +559,7 @@ static int buffer_tail_hvm(xc_interface *xch, struct 
restore_ctx *ctx,
         return -1;
     }
 
-    if ( RDEXACT(fd, qemusig, sizeof(qemusig)) ) {
+    if ( RDEXACT(fd, qemusig, QEMUSIG_SIZE) ) {
         PERROR("Error reading QEMU signature");
         return -1;
     }
@@ -517,13 +572,22 @@ static int buffer_tail_hvm(xc_interface *xch, struct 
restore_ctx *ctx,
      * live-migration QEMU record and Remus which includes a length
      * prefix
      */
-    if ( !memcmp(qemusig, "QemuDeviceModelRecord", sizeof(qemusig)) )
+    if ( !memcmp(qemusig, "QemuDeviceModelRecord", QEMUSIG_SIZE) )
         return compat_buffer_qemu(xch, ctx, fd, buf);
-    else if ( !memcmp(qemusig, "DeviceModelRecord0002", sizeof(qemusig)) ||
-              !memcmp(qemusig, "RemusDeviceModelState", sizeof(qemusig)) )
-        return buffer_qemu(xch, ctx, fd, buf);
+    else if ( !memcmp(qemusig, "DeviceModelRecord0002", QEMUSIG_SIZE) ||
+              !memcmp(qemusig, "RemusDeviceModelState", QEMUSIG_SIZE) )
+    {
+        if ( !(buf->dmsbuf = calloc(1, sizeof (*buf->dmsbuf))) ) {
+            PERROR("Error allocating Device Model buffer");
+            return -1;
+        }
+        return buffer_qemu(xch, ctx, 0, fd, buf);
+    }
+    else if ( !memcmp(qemusig, "DeviceModelRecords001", QEMUSIG_SIZE) ) {
+        return buffer_device_models(xch, ctx, fd, buf);
+   }
 
-    qemusig[20] = '\0';
+    qemusig[QEMUSIG_SIZE] = '\0';
     ERROR("Invalid QEMU signature: %s", qemusig);
     return -1;
 }
@@ -629,13 +693,18 @@ static int buffer_tail(xc_interface *xch, struct 
restore_ctx *ctx,
 
 static void tailbuf_free_hvm(struct tailbuf_hvm *buf)
 {
+    uint32_t i;
+
     if ( buf->hvmbuf ) {
         free(buf->hvmbuf);
         buf->hvmbuf = NULL;
     }
-    if ( buf->qemubuf ) {
-        free(buf->qemubuf);
-        buf->qemubuf = NULL;
+
+    for (i = 0; i < buf->num_dms; i++)
+    {
+        if (buf->dmsbuf[i].buf)
+            free(buf->dmsbuf[i].buf);
+        buf->dmsbuf[i].buf = NULL;
     }
 }
 
@@ -2137,10 +2206,17 @@ int xc_domain_restore(xc_interface *xch, int io_fd, 
uint32_t dom,
         }
     }
 
-    /* Dump the QEMU state to a state file for QEMU to load */
-    if ( dump_qemu(xch, dom, &tailbuf.u.hvm) ) {
-        PERROR("Error dumping QEMU state to file");
-        goto out;
+    /**
+     * Dump the each Device Model state to a state file for the Device
+     * Model to load
+     */
+    for ( i = 0; i < tailbuf.u.hvm.num_dms; i++)
+    {
+        if ( dump_qemu(xch, dom, i, &tailbuf.u.hvm) )
+        {
+            PERROR("Error dumping Device Model %u state to file", i);
+            goto out;
+        }
     }
 
     /* These comms pages need to be zeroed at the start of day */
@@ -2153,9 +2229,9 @@ int xc_domain_restore(xc_interface *xch, int io_fd, 
uint32_t dom,
     }
 
     if ( (frc = xc_set_hvm_param(xch, dom,
-                                 HVM_PARAM_IOREQ_PFN, 
tailbuf.u.hvm.magicpfns[0]))
+                                 HVM_PARAM_IO_PFN_FIRST, 
tailbuf.u.hvm.magicpfns[0]))
          || (frc = xc_set_hvm_param(xch, dom,
-                                    HVM_PARAM_BUFIOREQ_PFN, 
tailbuf.u.hvm.magicpfns[1]))
+                                    HVM_PARAM_IO_PFN_LAST, 
tailbuf.u.hvm.magicpfns[1]))
          || (frc = xc_set_hvm_param(xch, dom,
                                     HVM_PARAM_STORE_PFN, 
tailbuf.u.hvm.magicpfns[2]))
          || (frc = xc_set_hvm_param(xch, dom,
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index c359649..2aa7a28 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -862,7 +862,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t 
dom, uint32_t max_iter
     uint8_t *hvm_buf = NULL;
 
     /* HVM: magic frames for ioreqs and xenstore comms. */
-    uint64_t magic_pfns[3]; /* ioreq_pfn, bufioreq_pfn, store_pfn */
+    uint64_t magic_pfns[3]; /* io_pfn_first , io_pfn_last, store_pfn */
 
     unsigned long mfn;
 
@@ -1787,9 +1787,9 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t 
dom, uint32_t max_iter
 
         /* Save magic-page locations. */
         memset(magic_pfns, 0, sizeof(magic_pfns));
-        xc_get_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN,
+        xc_get_hvm_param(xch, dom, HVM_PARAM_IO_PFN_FIRST,
                          (unsigned long *)&magic_pfns[0]);
-        xc_get_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN,
+        xc_get_hvm_param(xch, dom, HVM_PARAM_IO_PFN_LAST,
                          (unsigned long *)&magic_pfns[1]);
         xc_get_hvm_param(xch, dom, HVM_PARAM_STORE_PFN,
                          (unsigned long *)&magic_pfns[2]);
-- 
Julien Grall


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.