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

[Xen-changelog] [xen-unstable] [HVM] Save/restore: dynamically calculate the size of the save buffer



# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1170852106 0
# Node ID 4d7ee9f4336ab57706bcb477542611006ea33447
# Parent  710aec0abb613a545ed9f2f41c7e130f1556494c
[HVM] Save/restore: dynamically calculate the size of the save buffer
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
 tools/libxc/xc_domain.c           |    8 +++++---
 tools/libxc/xc_hvm_save.c         |   21 +++++++++++----------
 xen/arch/x86/domctl.c             |   25 ++++++++++++++++++++-----
 xen/arch/x86/hvm/hpet.c           |    2 +-
 xen/arch/x86/hvm/hvm.c            |    3 ++-
 xen/arch/x86/hvm/i8254.c          |    2 +-
 xen/arch/x86/hvm/irq.c            |    9 ++++++---
 xen/arch/x86/hvm/rtc.c            |    2 +-
 xen/arch/x86/hvm/save.c           |   27 ++++++++++++++++++++++++++-
 xen/arch/x86/hvm/vioapic.c        |    2 +-
 xen/arch/x86/hvm/vlapic.c         |    6 ++++--
 xen/arch/x86/hvm/vpic.c           |    2 +-
 xen/include/asm-x86/hvm/support.h |   34 ++++++++++++++++++++++++----------
 xen/include/public/domctl.h       |    3 ++-
 14 files changed, 105 insertions(+), 41 deletions(-)

diff -r 710aec0abb61 -r 4d7ee9f4336a tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Wed Feb 07 10:21:15 2007 +0000
+++ b/tools/libxc/xc_domain.c   Wed Feb 07 12:41:46 2007 +0000
@@ -252,12 +252,14 @@ int xc_domain_hvm_getcontext(int xc_hand
     domctl.u.hvmcontext.size = size;
     set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
 
-    if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
-        return ret;
+    if ( ctxt_buf ) 
+        if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
+            return ret;
 
     ret = do_domctl(xc_handle, &domctl);
 
-    unlock_pages(ctxt_buf, size);
+    if ( ctxt_buf ) 
+        unlock_pages(ctxt_buf, size);
 
     return (ret < 0 ? -1 : domctl.u.hvmcontext.size);
 }
diff -r 710aec0abb61 -r 4d7ee9f4336a tools/libxc/xc_hvm_save.c
--- a/tools/libxc/xc_hvm_save.c Wed Feb 07 10:21:15 2007 +0000
+++ b/tools/libxc/xc_hvm_save.c Wed Feb 07 12:41:46 2007 +0000
@@ -33,12 +33,6 @@
 #include "xg_save_restore.h"
 
 /*
- * Size of a buffer big enough to take the HVM state of a domain.
- * Ought to calculate this a bit more carefully, or maybe ask Xen.
- */
-#define HVM_CTXT_SIZE 8192
-
-/*
 ** Default values for important tuning parameters. Can override by passing
 ** non-zero replacement values to xc_hvm_save().
 **
@@ -286,6 +280,7 @@ int xc_hvm_save(int xc_handle, int io_fd
     unsigned long *pfn_batch = NULL;
 
     /* A copy of hvm domain context buffer*/
+    uint32_t hvm_buf_size;
     uint8_t *hvm_buf = NULL;
 
     /* Live mapping of shared info structure */
@@ -431,9 +426,15 @@ int xc_hvm_save(int xc_handle, int io_fd
 
     page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn);
 
-    hvm_buf = malloc(HVM_CTXT_SIZE);
-
-    if (!to_send ||!to_skip ||!page_array ||!hvm_buf ) {
+    hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0);
+    if ( hvm_buf_size == -1 )
+    {
+        ERROR("Couldn't get HVM context size from Xen");
+        goto out;
+    }
+    hvm_buf = malloc(hvm_buf_size);
+
+    if (!to_send ||!to_skip ||!page_array ||!hvm_buf) {
         ERROR("Couldn't allocate memory");
         goto out;
     }
@@ -661,7 +662,7 @@ int xc_hvm_save(int xc_handle, int io_fd
     }
 
     if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
-                                              HVM_CTXT_SIZE)) == -1) {
+                                              hvm_buf_size)) == -1) {
         ERROR("HVM:Could not get hvm buffer");
         goto out;
     }
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/domctl.c     Wed Feb 07 12:41:46 2007 +0000
@@ -326,10 +326,6 @@ long arch_do_domctl(
         struct hvm_domain_context c;
         struct domain             *d;
 
-        c.cur = 0;
-        c.size = domctl->u.hvmcontext.size;
-        c.data = NULL;
-
         ret = -ESRCH;
         if ( (d = get_domain_by_id(domctl->domain)) == NULL )
             break;
@@ -338,19 +334,38 @@ long arch_do_domctl(
         if ( !is_hvm_domain(d) ) 
             goto gethvmcontext_out;
 
+        c.cur = 0;
+        c.size = hvm_save_size(d);
+        c.data = NULL;
+
+        if ( guest_handle_is_null(domctl->u.hvmcontext.buffer) )
+        {
+            /* Client is querying for the correct buffer size */
+            domctl->u.hvmcontext.size = c.size;
+            ret = 0;
+            goto gethvmcontext_out;            
+        }
+
+        /* Check that the client has a big enough buffer */
+        ret = -ENOSPC;
+        if ( domctl->u.hvmcontext.size < c.size ) 
+            goto gethvmcontext_out;
+
+        /* Allocate our own marshalling buffer */
         ret = -ENOMEM;
         if ( (c.data = xmalloc_bytes(c.size)) == NULL )
             goto gethvmcontext_out;
 
         ret = hvm_save(d, &c);
 
+        domctl->u.hvmcontext.size = c.cur;
         if ( copy_to_guest(domctl->u.hvmcontext.buffer, c.data, c.size) != 0 )
             ret = -EFAULT;
 
+    gethvmcontext_out:
         if ( copy_to_guest(u_domctl, domctl, 1) )
             ret = -EFAULT;
 
-    gethvmcontext_out:
         if ( c.data != NULL )
             xfree(c.data);
 
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/hvm/hpet.c
--- a/xen/arch/x86/hvm/hpet.c   Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/hvm/hpet.c   Wed Feb 07 12:41:46 2007 +0000
@@ -409,7 +409,7 @@ static int hpet_load(struct domain *d, h
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load);
+HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load, 1, HVMSR_PER_DOM);
 
 void hpet_init(struct vcpu *v)
 {
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Wed Feb 07 12:41:46 2007 +0000
@@ -227,7 +227,8 @@ static int hvm_load_cpu_ctxt(struct doma
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt);
+HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt,
+                          1, HVMSR_PER_VCPU);
 
 int hvm_vcpu_initialise(struct vcpu *v)
 {
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c  Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/hvm/i8254.c  Wed Feb 07 12:41:46 2007 +0000
@@ -445,7 +445,7 @@ static int pit_load(struct domain *d, hv
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load);
+HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM);
 
 static void pit_reset(void *opaque)
 {
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/hvm/irq.c    Wed Feb 07 12:41:46 2007 +0000
@@ -480,6 +480,9 @@ static int irq_load_link(struct domain *
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci);
-HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa);
-HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link);
+HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci,
+                          1, HVMSR_PER_DOM);
+HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa, 
+                          1, HVMSR_PER_DOM);
+HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link,
+                          1, HVMSR_PER_DOM);
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c    Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/hvm/rtc.c    Wed Feb 07 12:41:46 2007 +0000
@@ -417,7 +417,7 @@ static int rtc_load(struct domain *d, hv
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load);
+HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load, 1, HVMSR_PER_DOM);
 
 
 void rtc_init(struct vcpu *v, int base)
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/hvm/save.c
--- a/xen/arch/x86/hvm/save.c   Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/hvm/save.c   Wed Feb 07 12:41:46 2007 +0000
@@ -35,13 +35,16 @@ static struct {
     hvm_save_handler save;
     hvm_load_handler load; 
     const char *name;
+    size_t size;
+    int kind;
 } hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, "<?>"},};
 
 /* Init-time function to add entries to that list */
 void hvm_register_savevm(uint16_t typecode, 
                          const char *name,
                          hvm_save_handler save_state,
-                         hvm_load_handler load_state)
+                         hvm_load_handler load_state,
+                         size_t size, int kind)
 {
     ASSERT(typecode <= HVM_SAVE_CODE_MAX);
     ASSERT(hvm_sr_handlers[typecode].save == NULL);
@@ -49,6 +52,28 @@ void hvm_register_savevm(uint16_t typeco
     hvm_sr_handlers[typecode].save = save_state;
     hvm_sr_handlers[typecode].load = load_state;
     hvm_sr_handlers[typecode].name = name;
+    hvm_sr_handlers[typecode].size = size;
+    hvm_sr_handlers[typecode].kind = kind;
+}
+
+size_t hvm_save_size(struct domain *d) 
+{
+    struct vcpu *v;
+    size_t sz;
+    int i;
+    
+    /* Basic overhead for header and footer */
+    sz = (2 * sizeof (struct hvm_save_descriptor)) + HVM_SAVE_LENGTH(HEADER);
+
+    /* Plus space for each thing we will be saving */
+    for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) 
+        if ( hvm_sr_handlers[i].kind == HVMSR_PER_VCPU )
+            for_each_vcpu(d, v)
+                sz += hvm_sr_handlers[i].size;
+        else 
+            sz += hvm_sr_handlers[i].size;
+
+    return sz;
 }
 
 
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c        Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/hvm/vioapic.c        Wed Feb 07 12:41:46 2007 +0000
@@ -514,7 +514,7 @@ static int ioapic_load(struct domain *d,
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load);
+HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load, 1, HVMSR_PER_DOM);
 
 void vioapic_init(struct domain *d)
 {
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Wed Feb 07 12:41:46 2007 +0000
@@ -904,8 +904,10 @@ static int lapic_load_regs(struct domain
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden);
-HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs);
+HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden,
+                          1, HVMSR_PER_VCPU);
+HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs,
+                          1, HVMSR_PER_VCPU);
 
 int vlapic_init(struct vcpu *v)
 {
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/arch/x86/hvm/vpic.c
--- a/xen/arch/x86/hvm/vpic.c   Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/arch/x86/hvm/vpic.c   Wed Feb 07 12:41:46 2007 +0000
@@ -440,7 +440,7 @@ static int vpic_load(struct domain *d, h
     return 0;
 }
 
-HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load);
+HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load, 2, HVMSR_PER_DOM);
 
 void vpic_init(struct domain *d)
 {
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/include/asm-x86/hvm/support.h
--- a/xen/include/asm-x86/hvm/support.h Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/include/asm-x86/hvm/support.h Wed Feb 07 12:41:46 2007 +0000
@@ -221,23 +221,37 @@ typedef int (*hvm_load_handler) (struct 
 typedef int (*hvm_load_handler) (struct domain *d,
                                  hvm_domain_context_t *h);
 
-/* Init-time function to declare a pair of handlers for a type */
+/* Init-time function to declare a pair of handlers for a type,
+ * and the maximum buffer space needed to save this type of state */
 void hvm_register_savevm(uint16_t typecode,
                          const char *name, 
                          hvm_save_handler save_state,
-                         hvm_load_handler load_state);
-
-/* Syntactic sugar around that function */
-#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load)                     \
-static int __hvm_register_##_x##_save_and_restore(void)                 \
-{                                                                       \
-    hvm_register_savevm(HVM_SAVE_CODE(_x), #_x, &_save, &_load);        \
-    return 0;                                                           \
-}                                                                       \
+                         hvm_load_handler load_state,
+                         size_t size, int kind);
+
+/* The space needed for saving can be per-domain or per-vcpu: */
+#define HVMSR_PER_DOM  0
+#define HVMSR_PER_VCPU 1
+
+/* Syntactic sugar around that function: specify the max number of
+ * saves, and this calculates the size of buffer needed */
+#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load, _num, _k)             \
+static int __hvm_register_##_x##_save_and_restore(void)                   \
+{                                                                         \
+    hvm_register_savevm(HVM_SAVE_CODE(_x),                                \
+                        #_x,                                              \
+                        &_save,                                           \
+                        &_load,                                           \
+                        (_num) * (HVM_SAVE_LENGTH(_x)                     \
+                                  + sizeof (struct hvm_save_descriptor)), \
+                        _k);                                              \
+    return 0;                                                             \
+}                                                                         \
 __initcall(__hvm_register_##_x##_save_and_restore);
 
 
 /* Entry points for saving and restoring HVM domain state */
+size_t hvm_save_size(struct domain *d);
 int hvm_save(struct domain *d, hvm_domain_context_t *h);
 int hvm_load(struct domain *d, hvm_domain_context_t *h);
 
diff -r 710aec0abb61 -r 4d7ee9f4336a xen/include/public/domctl.h
--- a/xen/include/public/domctl.h       Wed Feb 07 10:21:15 2007 +0000
+++ b/xen/include/public/domctl.h       Wed Feb 07 12:41:46 2007 +0000
@@ -390,7 +390,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_setti
 #define XEN_DOMCTL_sethvmcontext   34
 typedef struct xen_domctl_hvmcontext {
     uint32_t size; /* IN/OUT: size of buffer / bytes filled */
-    XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT */
+    XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT: data, or call gethvmcontext 
+                                       * with NULL buffer to get size req'd */
 } xen_domctl_hvmcontext_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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