ia64/xen-unstable

changeset 13865:4d7ee9f4336a

[HVM] Save/restore: dynamically calculate the size of the save buffer
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Wed Feb 07 12:41:46 2007 +0000 (2007-02-07)
parents 710aec0abb61
children 584ab4fd1ad5
files tools/libxc/xc_domain.c tools/libxc/xc_hvm_save.c xen/arch/x86/domctl.c xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/irq.c xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/save.c xen/arch/x86/hvm/vioapic.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vpic.c xen/include/asm-x86/hvm/support.h xen/include/public/domctl.h
line diff
     1.1 --- a/tools/libxc/xc_domain.c	Wed Feb 07 10:21:15 2007 +0000
     1.2 +++ b/tools/libxc/xc_domain.c	Wed Feb 07 12:41:46 2007 +0000
     1.3 @@ -252,12 +252,14 @@ int xc_domain_hvm_getcontext(int xc_hand
     1.4      domctl.u.hvmcontext.size = size;
     1.5      set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
     1.6  
     1.7 -    if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
     1.8 -        return ret;
     1.9 +    if ( ctxt_buf ) 
    1.10 +        if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
    1.11 +            return ret;
    1.12  
    1.13      ret = do_domctl(xc_handle, &domctl);
    1.14  
    1.15 -    unlock_pages(ctxt_buf, size);
    1.16 +    if ( ctxt_buf ) 
    1.17 +        unlock_pages(ctxt_buf, size);
    1.18  
    1.19      return (ret < 0 ? -1 : domctl.u.hvmcontext.size);
    1.20  }
     2.1 --- a/tools/libxc/xc_hvm_save.c	Wed Feb 07 10:21:15 2007 +0000
     2.2 +++ b/tools/libxc/xc_hvm_save.c	Wed Feb 07 12:41:46 2007 +0000
     2.3 @@ -33,12 +33,6 @@
     2.4  #include "xg_save_restore.h"
     2.5  
     2.6  /*
     2.7 - * Size of a buffer big enough to take the HVM state of a domain.
     2.8 - * Ought to calculate this a bit more carefully, or maybe ask Xen.
     2.9 - */
    2.10 -#define HVM_CTXT_SIZE 8192
    2.11 -
    2.12 -/*
    2.13  ** Default values for important tuning parameters. Can override by passing
    2.14  ** non-zero replacement values to xc_hvm_save().
    2.15  **
    2.16 @@ -286,6 +280,7 @@ int xc_hvm_save(int xc_handle, int io_fd
    2.17      unsigned long *pfn_batch = NULL;
    2.18  
    2.19      /* A copy of hvm domain context buffer*/
    2.20 +    uint32_t hvm_buf_size;
    2.21      uint8_t *hvm_buf = NULL;
    2.22  
    2.23      /* Live mapping of shared info structure */
    2.24 @@ -431,9 +426,15 @@ int xc_hvm_save(int xc_handle, int io_fd
    2.25  
    2.26      page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn);
    2.27  
    2.28 -    hvm_buf = malloc(HVM_CTXT_SIZE);
    2.29 +    hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0);
    2.30 +    if ( hvm_buf_size == -1 )
    2.31 +    {
    2.32 +        ERROR("Couldn't get HVM context size from Xen");
    2.33 +        goto out;
    2.34 +    }
    2.35 +    hvm_buf = malloc(hvm_buf_size);
    2.36  
    2.37 -    if (!to_send ||!to_skip ||!page_array ||!hvm_buf ) {
    2.38 +    if (!to_send ||!to_skip ||!page_array ||!hvm_buf) {
    2.39          ERROR("Couldn't allocate memory");
    2.40          goto out;
    2.41      }
    2.42 @@ -661,7 +662,7 @@ int xc_hvm_save(int xc_handle, int io_fd
    2.43      }
    2.44  
    2.45      if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
    2.46 -                                              HVM_CTXT_SIZE)) == -1) {
    2.47 +                                              hvm_buf_size)) == -1) {
    2.48          ERROR("HVM:Could not get hvm buffer");
    2.49          goto out;
    2.50      }
     3.1 --- a/xen/arch/x86/domctl.c	Wed Feb 07 10:21:15 2007 +0000
     3.2 +++ b/xen/arch/x86/domctl.c	Wed Feb 07 12:41:46 2007 +0000
     3.3 @@ -326,10 +326,6 @@ long arch_do_domctl(
     3.4          struct hvm_domain_context c;
     3.5          struct domain             *d;
     3.6  
     3.7 -        c.cur = 0;
     3.8 -        c.size = domctl->u.hvmcontext.size;
     3.9 -        c.data = NULL;
    3.10 -
    3.11          ret = -ESRCH;
    3.12          if ( (d = get_domain_by_id(domctl->domain)) == NULL )
    3.13              break;
    3.14 @@ -338,19 +334,38 @@ long arch_do_domctl(
    3.15          if ( !is_hvm_domain(d) ) 
    3.16              goto gethvmcontext_out;
    3.17  
    3.18 +        c.cur = 0;
    3.19 +        c.size = hvm_save_size(d);
    3.20 +        c.data = NULL;
    3.21 +
    3.22 +        if ( guest_handle_is_null(domctl->u.hvmcontext.buffer) )
    3.23 +        {
    3.24 +            /* Client is querying for the correct buffer size */
    3.25 +            domctl->u.hvmcontext.size = c.size;
    3.26 +            ret = 0;
    3.27 +            goto gethvmcontext_out;            
    3.28 +        }
    3.29 +
    3.30 +        /* Check that the client has a big enough buffer */
    3.31 +        ret = -ENOSPC;
    3.32 +        if ( domctl->u.hvmcontext.size < c.size ) 
    3.33 +            goto gethvmcontext_out;
    3.34 +
    3.35 +        /* Allocate our own marshalling buffer */
    3.36          ret = -ENOMEM;
    3.37          if ( (c.data = xmalloc_bytes(c.size)) == NULL )
    3.38              goto gethvmcontext_out;
    3.39  
    3.40          ret = hvm_save(d, &c);
    3.41  
    3.42 +        domctl->u.hvmcontext.size = c.cur;
    3.43          if ( copy_to_guest(domctl->u.hvmcontext.buffer, c.data, c.size) != 0 )
    3.44              ret = -EFAULT;
    3.45  
    3.46 +    gethvmcontext_out:
    3.47          if ( copy_to_guest(u_domctl, domctl, 1) )
    3.48              ret = -EFAULT;
    3.49  
    3.50 -    gethvmcontext_out:
    3.51          if ( c.data != NULL )
    3.52              xfree(c.data);
    3.53  
     4.1 --- a/xen/arch/x86/hvm/hpet.c	Wed Feb 07 10:21:15 2007 +0000
     4.2 +++ b/xen/arch/x86/hvm/hpet.c	Wed Feb 07 12:41:46 2007 +0000
     4.3 @@ -409,7 +409,7 @@ static int hpet_load(struct domain *d, h
     4.4      return 0;
     4.5  }
     4.6  
     4.7 -HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load);
     4.8 +HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load, 1, HVMSR_PER_DOM);
     4.9  
    4.10  void hpet_init(struct vcpu *v)
    4.11  {
     5.1 --- a/xen/arch/x86/hvm/hvm.c	Wed Feb 07 10:21:15 2007 +0000
     5.2 +++ b/xen/arch/x86/hvm/hvm.c	Wed Feb 07 12:41:46 2007 +0000
     5.3 @@ -227,7 +227,8 @@ static int hvm_load_cpu_ctxt(struct doma
     5.4      return 0;
     5.5  }
     5.6  
     5.7 -HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt);
     5.8 +HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt,
     5.9 +                          1, HVMSR_PER_VCPU);
    5.10  
    5.11  int hvm_vcpu_initialise(struct vcpu *v)
    5.12  {
     6.1 --- a/xen/arch/x86/hvm/i8254.c	Wed Feb 07 10:21:15 2007 +0000
     6.2 +++ b/xen/arch/x86/hvm/i8254.c	Wed Feb 07 12:41:46 2007 +0000
     6.3 @@ -445,7 +445,7 @@ static int pit_load(struct domain *d, hv
     6.4      return 0;
     6.5  }
     6.6  
     6.7 -HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load);
     6.8 +HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM);
     6.9  
    6.10  static void pit_reset(void *opaque)
    6.11  {
     7.1 --- a/xen/arch/x86/hvm/irq.c	Wed Feb 07 10:21:15 2007 +0000
     7.2 +++ b/xen/arch/x86/hvm/irq.c	Wed Feb 07 12:41:46 2007 +0000
     7.3 @@ -480,6 +480,9 @@ static int irq_load_link(struct domain *
     7.4      return 0;
     7.5  }
     7.6  
     7.7 -HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci);
     7.8 -HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa);
     7.9 -HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link);
    7.10 +HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci,
    7.11 +                          1, HVMSR_PER_DOM);
    7.12 +HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa, 
    7.13 +                          1, HVMSR_PER_DOM);
    7.14 +HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link,
    7.15 +                          1, HVMSR_PER_DOM);
     8.1 --- a/xen/arch/x86/hvm/rtc.c	Wed Feb 07 10:21:15 2007 +0000
     8.2 +++ b/xen/arch/x86/hvm/rtc.c	Wed Feb 07 12:41:46 2007 +0000
     8.3 @@ -417,7 +417,7 @@ static int rtc_load(struct domain *d, hv
     8.4      return 0;
     8.5  }
     8.6  
     8.7 -HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load);
     8.8 +HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load, 1, HVMSR_PER_DOM);
     8.9  
    8.10  
    8.11  void rtc_init(struct vcpu *v, int base)
     9.1 --- a/xen/arch/x86/hvm/save.c	Wed Feb 07 10:21:15 2007 +0000
     9.2 +++ b/xen/arch/x86/hvm/save.c	Wed Feb 07 12:41:46 2007 +0000
     9.3 @@ -35,13 +35,16 @@ static struct {
     9.4      hvm_save_handler save;
     9.5      hvm_load_handler load; 
     9.6      const char *name;
     9.7 +    size_t size;
     9.8 +    int kind;
     9.9  } hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, "<?>"},};
    9.10  
    9.11  /* Init-time function to add entries to that list */
    9.12  void hvm_register_savevm(uint16_t typecode, 
    9.13                           const char *name,
    9.14                           hvm_save_handler save_state,
    9.15 -                         hvm_load_handler load_state)
    9.16 +                         hvm_load_handler load_state,
    9.17 +                         size_t size, int kind)
    9.18  {
    9.19      ASSERT(typecode <= HVM_SAVE_CODE_MAX);
    9.20      ASSERT(hvm_sr_handlers[typecode].save == NULL);
    9.21 @@ -49,6 +52,28 @@ void hvm_register_savevm(uint16_t typeco
    9.22      hvm_sr_handlers[typecode].save = save_state;
    9.23      hvm_sr_handlers[typecode].load = load_state;
    9.24      hvm_sr_handlers[typecode].name = name;
    9.25 +    hvm_sr_handlers[typecode].size = size;
    9.26 +    hvm_sr_handlers[typecode].kind = kind;
    9.27 +}
    9.28 +
    9.29 +size_t hvm_save_size(struct domain *d) 
    9.30 +{
    9.31 +    struct vcpu *v;
    9.32 +    size_t sz;
    9.33 +    int i;
    9.34 +    
    9.35 +    /* Basic overhead for header and footer */
    9.36 +    sz = (2 * sizeof (struct hvm_save_descriptor)) + HVM_SAVE_LENGTH(HEADER);
    9.37 +
    9.38 +    /* Plus space for each thing we will be saving */
    9.39 +    for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) 
    9.40 +        if ( hvm_sr_handlers[i].kind == HVMSR_PER_VCPU )
    9.41 +            for_each_vcpu(d, v)
    9.42 +                sz += hvm_sr_handlers[i].size;
    9.43 +        else 
    9.44 +            sz += hvm_sr_handlers[i].size;
    9.45 +
    9.46 +    return sz;
    9.47  }
    9.48  
    9.49  
    10.1 --- a/xen/arch/x86/hvm/vioapic.c	Wed Feb 07 10:21:15 2007 +0000
    10.2 +++ b/xen/arch/x86/hvm/vioapic.c	Wed Feb 07 12:41:46 2007 +0000
    10.3 @@ -514,7 +514,7 @@ static int ioapic_load(struct domain *d,
    10.4      return 0;
    10.5  }
    10.6  
    10.7 -HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load);
    10.8 +HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load, 1, HVMSR_PER_DOM);
    10.9  
   10.10  void vioapic_init(struct domain *d)
   10.11  {
    11.1 --- a/xen/arch/x86/hvm/vlapic.c	Wed Feb 07 10:21:15 2007 +0000
    11.2 +++ b/xen/arch/x86/hvm/vlapic.c	Wed Feb 07 12:41:46 2007 +0000
    11.3 @@ -904,8 +904,10 @@ static int lapic_load_regs(struct domain
    11.4      return 0;
    11.5  }
    11.6  
    11.7 -HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden);
    11.8 -HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs);
    11.9 +HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden,
   11.10 +                          1, HVMSR_PER_VCPU);
   11.11 +HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs,
   11.12 +                          1, HVMSR_PER_VCPU);
   11.13  
   11.14  int vlapic_init(struct vcpu *v)
   11.15  {
    12.1 --- a/xen/arch/x86/hvm/vpic.c	Wed Feb 07 10:21:15 2007 +0000
    12.2 +++ b/xen/arch/x86/hvm/vpic.c	Wed Feb 07 12:41:46 2007 +0000
    12.3 @@ -440,7 +440,7 @@ static int vpic_load(struct domain *d, h
    12.4      return 0;
    12.5  }
    12.6  
    12.7 -HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load);
    12.8 +HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load, 2, HVMSR_PER_DOM);
    12.9  
   12.10  void vpic_init(struct domain *d)
   12.11  {
    13.1 --- a/xen/include/asm-x86/hvm/support.h	Wed Feb 07 10:21:15 2007 +0000
    13.2 +++ b/xen/include/asm-x86/hvm/support.h	Wed Feb 07 12:41:46 2007 +0000
    13.3 @@ -221,23 +221,37 @@ typedef int (*hvm_save_handler) (struct 
    13.4  typedef int (*hvm_load_handler) (struct domain *d,
    13.5                                   hvm_domain_context_t *h);
    13.6  
    13.7 -/* Init-time function to declare a pair of handlers for a type */
    13.8 +/* Init-time function to declare a pair of handlers for a type,
    13.9 + * and the maximum buffer space needed to save this type of state */
   13.10  void hvm_register_savevm(uint16_t typecode,
   13.11                           const char *name, 
   13.12                           hvm_save_handler save_state,
   13.13 -                         hvm_load_handler load_state);
   13.14 +                         hvm_load_handler load_state,
   13.15 +                         size_t size, int kind);
   13.16  
   13.17 -/* Syntactic sugar around that function */
   13.18 -#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load)                     \
   13.19 -static int __hvm_register_##_x##_save_and_restore(void)                 \
   13.20 -{                                                                       \
   13.21 -    hvm_register_savevm(HVM_SAVE_CODE(_x), #_x, &_save, &_load);        \
   13.22 -    return 0;                                                           \
   13.23 -}                                                                       \
   13.24 +/* The space needed for saving can be per-domain or per-vcpu: */
   13.25 +#define HVMSR_PER_DOM  0
   13.26 +#define HVMSR_PER_VCPU 1
   13.27 +
   13.28 +/* Syntactic sugar around that function: specify the max number of
   13.29 + * saves, and this calculates the size of buffer needed */
   13.30 +#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load, _num, _k)             \
   13.31 +static int __hvm_register_##_x##_save_and_restore(void)                   \
   13.32 +{                                                                         \
   13.33 +    hvm_register_savevm(HVM_SAVE_CODE(_x),                                \
   13.34 +                        #_x,                                              \
   13.35 +                        &_save,                                           \
   13.36 +                        &_load,                                           \
   13.37 +                        (_num) * (HVM_SAVE_LENGTH(_x)                     \
   13.38 +                                  + sizeof (struct hvm_save_descriptor)), \
   13.39 +                        _k);                                              \
   13.40 +    return 0;                                                             \
   13.41 +}                                                                         \
   13.42  __initcall(__hvm_register_##_x##_save_and_restore);
   13.43  
   13.44  
   13.45  /* Entry points for saving and restoring HVM domain state */
   13.46 +size_t hvm_save_size(struct domain *d);
   13.47  int hvm_save(struct domain *d, hvm_domain_context_t *h);
   13.48  int hvm_load(struct domain *d, hvm_domain_context_t *h);
   13.49  
    14.1 --- a/xen/include/public/domctl.h	Wed Feb 07 10:21:15 2007 +0000
    14.2 +++ b/xen/include/public/domctl.h	Wed Feb 07 12:41:46 2007 +0000
    14.3 @@ -390,7 +390,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_setti
    14.4  #define XEN_DOMCTL_sethvmcontext   34
    14.5  typedef struct xen_domctl_hvmcontext {
    14.6      uint32_t size; /* IN/OUT: size of buffer / bytes filled */
    14.7 -    XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT */
    14.8 +    XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT: data, or call gethvmcontext 
    14.9 +                                       * with NULL buffer to get size req'd */
   14.10  } xen_domctl_hvmcontext_t;
   14.11  DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
   14.12