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>
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 +/* The space needed for saving can be per-domain or per-vcpu: */ 13.18 +#define HVMSR_PER_DOM 0 13.19 +#define HVMSR_PER_VCPU 1 13.20 13.21 -/* Syntactic sugar around that function */ 13.22 -#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load) \ 13.23 -static int __hvm_register_##_x##_save_and_restore(void) \ 13.24 -{ \ 13.25 - hvm_register_savevm(HVM_SAVE_CODE(_x), #_x, &_save, &_load); \ 13.26 - return 0; \ 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