From: Wei Liu Date: Mon, 21 Aug 2017 14:09:11 +0000 (+0100) Subject: xen: move hvm save code under common to x86 X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~1619 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=108896d73e5a95a99bbebb1d68e0a656cf93b703;p=xen.git xen: move hvm save code under common to x86 The code is only used by x86 at this point. Merge common/hvm/save.c into x86 hvm/save.c. Move the headers and fix up inclusions. Remove the now empty common/hvm directory. Also fix some issues while moving: 1. removing trailing spaces; 2. fix multi-line comment; 3. make "i" in hvm_save unsigned int; 4. add some blank lines to separate sections of code; 5. change bool_t to bool. Signed-off-by: Wei Liu Acked-by: Jan Beulich --- diff --git a/xen/arch/x86/cpu/mcheck/vmce.c b/xen/arch/x86/cpu/mcheck/vmce.c index 62faae49c6..9c460c7c6c 100644 --- a/xen/arch/x86/cpu/mcheck/vmce.c +++ b/xen/arch/x86/cpu/mcheck/vmce.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/xen/arch/x86/cpu/vpmu_amd.c b/xen/arch/x86/cpu/vpmu_amd.c index b3c3697a68..5efc39b4eb 100644 --- a/xen/arch/x86/cpu/vpmu_amd.c +++ b/xen/arch/x86/cpu/vpmu_amd.c @@ -22,11 +22,11 @@ */ #include -#include #include #include #include #include +#include #include #include diff --git a/xen/arch/x86/hvm/save.c b/xen/arch/x86/hvm/save.c index f7d4999073..8984a23a88 100644 --- a/xen/arch/x86/hvm/save.c +++ b/xen/arch/x86/hvm/save.c @@ -20,7 +20,11 @@ * this program; If not, see . */ +#include +#include + #include + #include void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr) @@ -78,6 +82,310 @@ int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr) return 0; } +/* List of handlers for various HVM save and restore types */ +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 __init hvm_register_savevm(uint16_t typecode, + const char *name, + hvm_save_handler save_state, + hvm_load_handler load_state, + size_t size, int kind) +{ + ASSERT(typecode <= HVM_SAVE_CODE_MAX); + ASSERT(hvm_sr_handlers[typecode].save == NULL); + ASSERT(hvm_sr_handlers[typecode].load == NULL); + 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; +} + +/* + * Extract a single instance of a save record, by marshalling all records of + * that type and copying out the one we need. + */ +int hvm_save_one(struct domain *d, unsigned int typecode, unsigned int instance, + XEN_GUEST_HANDLE_64(uint8) handle, uint64_t *bufsz) +{ + int rv; + hvm_domain_context_t ctxt = { }; + const struct hvm_save_descriptor *desc; + + if ( d->is_dying || + typecode > HVM_SAVE_CODE_MAX || + hvm_sr_handlers[typecode].size < sizeof(*desc) || + !hvm_sr_handlers[typecode].save ) + return -EINVAL; + + ctxt.size = hvm_sr_handlers[typecode].size; + if ( hvm_sr_handlers[typecode].kind == HVMSR_PER_VCPU ) + ctxt.size *= d->max_vcpus; + ctxt.data = xmalloc_bytes(ctxt.size); + if ( !ctxt.data ) + return -ENOMEM; + + if ( (rv = hvm_sr_handlers[typecode].save(d, &ctxt)) != 0 ) + printk(XENLOG_G_ERR "HVM%d save: failed to save type %"PRIu16" (%d)\n", + d->domain_id, typecode, rv); + else if ( rv = -ENOENT, ctxt.cur >= sizeof(*desc) ) + { + uint32_t off; + + for ( off = 0; off <= (ctxt.cur - sizeof(*desc)); off += desc->length ) + { + desc = (void *)(ctxt.data + off); + /* Move past header */ + off += sizeof(*desc); + if ( ctxt.cur < desc->length || + off > ctxt.cur - desc->length ) + break; + if ( instance == desc->instance ) + { + rv = 0; + if ( guest_handle_is_null(handle) ) + *bufsz = desc->length; + else if ( *bufsz < desc->length ) + rv = -ENOBUFS; + else if ( copy_to_guest(handle, ctxt.data + off, desc->length) ) + rv = -EFAULT; + else + *bufsz = desc->length; + break; + } + } + } + + xfree(ctxt.data); + return rv; +} + +int hvm_save(struct domain *d, hvm_domain_context_t *h) +{ + char *c; + struct hvm_save_header hdr; + struct hvm_save_end end; + hvm_save_handler handler; + unsigned int i; + + if ( d->is_dying ) + return -EINVAL; + + hdr.magic = HVM_FILE_MAGIC; + hdr.version = HVM_FILE_VERSION; + + /* Save xen changeset */ + c = strrchr(xen_changeset(), ':'); + if ( c ) + hdr.changeset = simple_strtoll(c, NULL, 16); + else + hdr.changeset = -1ULL; /* Unknown */ + + arch_hvm_save(d, &hdr); + + if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 ) + { + printk(XENLOG_G_ERR "HVM%d save: failed to write header\n", + d->domain_id); + return -EFAULT; + } + + /* Save all available kinds of state */ + for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) + { + handler = hvm_sr_handlers[i].save; + if ( handler != NULL ) + { + printk(XENLOG_G_INFO "HVM%d save: %s\n", + d->domain_id, hvm_sr_handlers[i].name); + if ( handler(d, h) != 0 ) + { + printk(XENLOG_G_ERR + "HVM%d save: failed to save type %"PRIu16"\n", + d->domain_id, i); + return -EFAULT; + } + } + } + + /* Save an end-of-file marker */ + if ( hvm_save_entry(END, 0, h, &end) != 0 ) + { + /* Run out of data */ + printk(XENLOG_G_ERR "HVM%d save: no room for end marker\n", + d->domain_id); + return -EFAULT; + } + + /* Save macros should not have let us overrun */ + ASSERT(h->cur <= h->size); + return 0; +} + +int hvm_load(struct domain *d, hvm_domain_context_t *h) +{ + struct hvm_save_header hdr; + struct hvm_save_descriptor *desc; + hvm_load_handler handler; + struct vcpu *v; + + if ( d->is_dying ) + return -EINVAL; + + /* Read the save header, which must be first */ + if ( hvm_load_entry(HEADER, h, &hdr) != 0 ) + return -1; + + if ( arch_hvm_load(d, &hdr) ) + return -1; + + /* Down all the vcpus: we only re-enable the ones that had state saved. */ + for_each_vcpu(d, v) + if ( test_and_set_bit(_VPF_down, &v->pause_flags) ) + vcpu_sleep_nosync(v); + + for ( ; ; ) + { + if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) ) + { + /* Run out of data */ + printk(XENLOG_G_ERR + "HVM%d restore: save did not end with a null entry\n", + d->domain_id); + return -1; + } + + /* Read the typecode of the next entry and check for the end-marker */ + desc = (struct hvm_save_descriptor *)(&h->data[h->cur]); + if ( desc->typecode == 0 ) + return 0; + + /* Find the handler for this entry */ + if ( (desc->typecode > HVM_SAVE_CODE_MAX) || + ((handler = hvm_sr_handlers[desc->typecode].load) == NULL) ) + { + printk(XENLOG_G_ERR "HVM%d restore: unknown entry typecode %u\n", + d->domain_id, desc->typecode); + return -1; + } + + /* Load the entry */ + printk(XENLOG_G_INFO "HVM%d restore: %s %"PRIu16"\n", d->domain_id, + hvm_sr_handlers[desc->typecode].name, desc->instance); + if ( handler(d, h) != 0 ) + { + printk(XENLOG_G_ERR "HVM%d restore: failed to load entry %u/%u\n", + d->domain_id, desc->typecode, desc->instance); + return -1; + } + } + + /* Not reached */ +} + +int _hvm_init_entry(struct hvm_domain_context *h, uint16_t tc, uint16_t inst, + uint32_t len) +{ + struct hvm_save_descriptor *d + = (struct hvm_save_descriptor *)&h->data[h->cur]; + + if ( h->size - h->cur < len + sizeof (*d) ) + { + printk(XENLOG_G_WARNING "HVM save: no room for" + " %"PRIu32" + %zu bytes for typecode %"PRIu16"\n", + len, sizeof(*d), tc); + return -1; + } + + d->typecode = tc; + d->instance = inst; + d->length = len; + h->cur += sizeof(*d); + + return 0; +} + +void _hvm_write_entry(struct hvm_domain_context *h, void *src, + uint32_t src_len) +{ + memcpy(&h->data[h->cur], src, src_len); + h->cur += src_len; +} + +int _hvm_check_entry(struct hvm_domain_context *h, uint16_t type, uint32_t len, + bool strict_length) +{ + struct hvm_save_descriptor *d + = (struct hvm_save_descriptor *)&h->data[h->cur]; + + if ( sizeof(*d) > h->size - h->cur) + { + printk(XENLOG_G_WARNING + "HVM restore: not enough data left to read %zu bytes " + "for type %u header\n", sizeof(*d), type); + return -1; + } + + if ( (type != d->typecode) || + (strict_length ? (len != d->length) : (len < d->length)) || + (d->length > (h->size - h->cur - sizeof(*d))) ) + { + printk(XENLOG_G_WARNING + "HVM restore mismatch: expected %s type %u length %u, " + "saw type %u length %u. %zu bytes remaining\n", + strict_length ? "strict" : "zeroextended", type, len, + d->typecode, d->length, h->size - h->cur - sizeof(*d)); + return -1; + } + + h->cur += sizeof(*d); + + return 0; +} + +void _hvm_read_entry(struct hvm_domain_context *h, void *dest, + uint32_t dest_len) +{ + struct hvm_save_descriptor *d + = (struct hvm_save_descriptor *)&h->data[h->cur - sizeof(*d)]; + + BUG_ON(d->length > dest_len); + + memcpy(dest, &h->data[h->cur], d->length); + + if ( d->length < dest_len ) + memset((char *)dest + d->length, 0, dest_len - d->length); + + h->cur += d->length; +} + /* * Local variables: * mode: C diff --git a/xen/common/Makefile b/xen/common/Makefile index 26c5a64337..39e2614546 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -74,8 +74,6 @@ tmem-y := tmem.o tmem_xen.o tmem_control.o tmem-$(CONFIG_COMPAT) += compat/tmem_xen.o obj-$(CONFIG_TMEM) += $(tmem-y) -subdir-$(CONFIG_X86) += hvm - subdir-$(CONFIG_GCOV) += gcov subdir-y += libelf diff --git a/xen/common/hvm/Makefile b/xen/common/hvm/Makefile deleted file mode 100644 index a464a57d52..0000000000 --- a/xen/common/hvm/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += save.o diff --git a/xen/common/hvm/save.c b/xen/common/hvm/save.c deleted file mode 100644 index 1a7135ee31..0000000000 --- a/xen/common/hvm/save.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * hvm/save.c: Save and restore HVM guest's emulated hardware state. - * - * Copyright (c) 2004, Intel Corporation. - * Copyright (c) 2007, XenSource Inc. - * Copyright (c) 2007, Isaku Yamahata - * VA Linux Systems Japan K.K. - * split arch generic part - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; If not, see . - */ - -#include -#include -#include -#include -#include - -#include - -/* List of handlers for various HVM save and restore types */ -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 __init hvm_register_savevm(uint16_t typecode, - const char *name, - hvm_save_handler save_state, - hvm_load_handler load_state, - size_t size, int kind) -{ - ASSERT(typecode <= HVM_SAVE_CODE_MAX); - ASSERT(hvm_sr_handlers[typecode].save == NULL); - ASSERT(hvm_sr_handlers[typecode].load == NULL); - 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; -} - -/* Extract a single instance of a save record, by marshalling all - * records of that type and copying out the one we need. */ -int hvm_save_one(struct domain *d, unsigned int typecode, unsigned int instance, - XEN_GUEST_HANDLE_64(uint8) handle, uint64_t *bufsz) -{ - int rv; - hvm_domain_context_t ctxt = { }; - const struct hvm_save_descriptor *desc; - - if ( d->is_dying || - typecode > HVM_SAVE_CODE_MAX || - hvm_sr_handlers[typecode].size < sizeof(*desc) || - !hvm_sr_handlers[typecode].save ) - return -EINVAL; - - ctxt.size = hvm_sr_handlers[typecode].size; - if ( hvm_sr_handlers[typecode].kind == HVMSR_PER_VCPU ) - ctxt.size *= d->max_vcpus; - ctxt.data = xmalloc_bytes(ctxt.size); - if ( !ctxt.data ) - return -ENOMEM; - - if ( (rv = hvm_sr_handlers[typecode].save(d, &ctxt)) != 0 ) - printk(XENLOG_G_ERR "HVM%d save: failed to save type %"PRIu16" (%d)\n", - d->domain_id, typecode, rv); - else if ( rv = -ENOENT, ctxt.cur >= sizeof(*desc) ) - { - uint32_t off; - - for ( off = 0; off <= (ctxt.cur - sizeof(*desc)); off += desc->length ) - { - desc = (void *)(ctxt.data + off); - /* Move past header */ - off += sizeof(*desc); - if ( ctxt.cur < desc->length || - off > ctxt.cur - desc->length ) - break; - if ( instance == desc->instance ) - { - rv = 0; - if ( guest_handle_is_null(handle) ) - *bufsz = desc->length; - else if ( *bufsz < desc->length ) - rv = -ENOBUFS; - else if ( copy_to_guest(handle, ctxt.data + off, desc->length) ) - rv = -EFAULT; - else - *bufsz = desc->length; - break; - } - } - } - - xfree(ctxt.data); - return rv; -} - -int hvm_save(struct domain *d, hvm_domain_context_t *h) -{ - char *c; - struct hvm_save_header hdr; - struct hvm_save_end end; - hvm_save_handler handler; - uint16_t i; - - if ( d->is_dying ) - return -EINVAL; - - hdr.magic = HVM_FILE_MAGIC; - hdr.version = HVM_FILE_VERSION; - - /* Save xen changeset */ - c = strrchr(xen_changeset(), ':'); - if ( c ) - hdr.changeset = simple_strtoll(c, NULL, 16); - else - hdr.changeset = -1ULL; /* Unknown */ - - arch_hvm_save(d, &hdr); - - if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 ) - { - printk(XENLOG_G_ERR "HVM%d save: failed to write header\n", - d->domain_id); - return -EFAULT; - } - - /* Save all available kinds of state */ - for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) - { - handler = hvm_sr_handlers[i].save; - if ( handler != NULL ) - { - printk(XENLOG_G_INFO "HVM%d save: %s\n", - d->domain_id, hvm_sr_handlers[i].name); - if ( handler(d, h) != 0 ) - { - printk(XENLOG_G_ERR - "HVM%d save: failed to save type %"PRIu16"\n", - d->domain_id, i); - return -EFAULT; - } - } - } - - /* Save an end-of-file marker */ - if ( hvm_save_entry(END, 0, h, &end) != 0 ) - { - /* Run out of data */ - printk(XENLOG_G_ERR "HVM%d save: no room for end marker\n", - d->domain_id); - return -EFAULT; - } - - /* Save macros should not have let us overrun */ - ASSERT(h->cur <= h->size); - return 0; -} - -int hvm_load(struct domain *d, hvm_domain_context_t *h) -{ - struct hvm_save_header hdr; - struct hvm_save_descriptor *desc; - hvm_load_handler handler; - struct vcpu *v; - - if ( d->is_dying ) - return -EINVAL; - - /* Read the save header, which must be first */ - if ( hvm_load_entry(HEADER, h, &hdr) != 0 ) - return -1; - - if ( arch_hvm_load(d, &hdr) ) - return -1; - - /* Down all the vcpus: we only re-enable the ones that had state saved. */ - for_each_vcpu(d, v) - if ( test_and_set_bit(_VPF_down, &v->pause_flags) ) - vcpu_sleep_nosync(v); - - for ( ; ; ) - { - if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) ) - { - /* Run out of data */ - printk(XENLOG_G_ERR - "HVM%d restore: save did not end with a null entry\n", - d->domain_id); - return -1; - } - - /* Read the typecode of the next entry and check for the end-marker */ - desc = (struct hvm_save_descriptor *)(&h->data[h->cur]); - if ( desc->typecode == 0 ) - return 0; - - /* Find the handler for this entry */ - if ( (desc->typecode > HVM_SAVE_CODE_MAX) || - ((handler = hvm_sr_handlers[desc->typecode].load) == NULL) ) - { - printk(XENLOG_G_ERR "HVM%d restore: unknown entry typecode %u\n", - d->domain_id, desc->typecode); - return -1; - } - - /* Load the entry */ - printk(XENLOG_G_INFO "HVM%d restore: %s %"PRIu16"\n", d->domain_id, - hvm_sr_handlers[desc->typecode].name, desc->instance); - if ( handler(d, h) != 0 ) - { - printk(XENLOG_G_ERR "HVM%d restore: failed to load entry %u/%u\n", - d->domain_id, desc->typecode, desc->instance); - return -1; - } - } - - /* Not reached */ -} - -int _hvm_init_entry(struct hvm_domain_context *h, - uint16_t tc, uint16_t inst, uint32_t len) -{ - struct hvm_save_descriptor *d - = (struct hvm_save_descriptor *)&h->data[h->cur]; - if ( h->size - h->cur < len + sizeof (*d) ) - { - printk(XENLOG_G_WARNING "HVM save: no room for" - " %"PRIu32" + %zu bytes for typecode %"PRIu16"\n", - len, sizeof(*d), tc); - return -1; - } - d->typecode = tc; - d->instance = inst; - d->length = len; - h->cur += sizeof(*d); - return 0; -} - -void _hvm_write_entry(struct hvm_domain_context *h, - void *src, uint32_t src_len) -{ - memcpy(&h->data[h->cur], src, src_len); - h->cur += src_len; -} - -int _hvm_check_entry(struct hvm_domain_context *h, - uint16_t type, uint32_t len, bool_t strict_length) -{ - struct hvm_save_descriptor *d - = (struct hvm_save_descriptor *)&h->data[h->cur]; - if ( sizeof(*d) > h->size - h->cur) - { - printk(XENLOG_G_WARNING - "HVM restore: not enough data left to read %zu bytes " - "for type %u header\n", sizeof(*d), type); - return -1; - } - if ( (type != d->typecode) || - (strict_length ? (len != d->length) : (len < d->length)) || - (d->length > (h->size - h->cur - sizeof(*d))) ) - { - printk(XENLOG_G_WARNING - "HVM restore mismatch: expected %s type %u length %u, " - "saw type %u length %u. %zu bytes remaining\n", - strict_length ? "strict" : "zeroextended", type, len, - d->typecode, d->length, h->size - h->cur - sizeof(*d)); - return -1; - } - h->cur += sizeof(*d); - return 0; -} - -void _hvm_read_entry(struct hvm_domain_context *h, - void *dest, uint32_t dest_len) -{ - struct hvm_save_descriptor *d - = (struct hvm_save_descriptor *)&h->data[h->cur - sizeof(*d)]; - BUG_ON(d->length > dest_len); - memcpy(dest, &h->data[h->cur], d->length); - if ( d->length < dest_len ) - memset((char *)dest + d->length, 0, dest_len - d->length); - h->cur += d->length; -} - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-x86/hvm/save.h b/xen/include/asm-x86/hvm/save.h new file mode 100644 index 0000000000..f889e8fe1d --- /dev/null +++ b/xen/include/asm-x86/hvm/save.h @@ -0,0 +1,144 @@ +/* + * save.h: HVM support routines for save/restore + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; If not, see . + */ + +#ifndef __XEN_HVM_SAVE_H__ +#define __XEN_HVM_SAVE_H__ + +#include +#include +#include +#include + +/* Marshalling and unmarshalling uses a buffer with size and cursor. */ +typedef struct hvm_domain_context { + uint32_t cur; + uint32_t size; + uint8_t *data; +} hvm_domain_context_t; + +/* Marshalling an entry: check space and fill in the header */ +int _hvm_init_entry(struct hvm_domain_context *h, + uint16_t tc, uint16_t inst, uint32_t len); + +/* Marshalling: copy the contents in a type-safe way */ +void _hvm_write_entry(struct hvm_domain_context *h, + void *src, uint32_t src_len); + +/* Marshalling: init and copy; evaluates to zero on success */ +#define hvm_save_entry(_x, _inst, _h, _src) ({ \ + int r; \ + r = _hvm_init_entry((_h), HVM_SAVE_CODE(_x), \ + (_inst), HVM_SAVE_LENGTH(_x)); \ + if ( r == 0 ) \ + _hvm_write_entry((_h), (_src), HVM_SAVE_LENGTH(_x)); \ + r; }) + +/* Unmarshalling: test an entry's size and typecode and record the instance */ +int _hvm_check_entry(struct hvm_domain_context *h, + uint16_t type, uint32_t len, bool_t strict_length); + +/* Unmarshalling: copy the contents in a type-safe way */ +void _hvm_read_entry(struct hvm_domain_context *h, + void *dest, uint32_t dest_len); + +/* + * Unmarshalling: check, then copy. Evaluates to zero on success. This load + * function requires the save entry to be the same size as the dest structure. + */ +#define _hvm_load_entry(_x, _h, _dst, _strict) ({ \ + int r; \ + struct hvm_save_descriptor *desc \ + = (struct hvm_save_descriptor *)&(_h)->data[(_h)->cur]; \ + if ( (r = _hvm_check_entry((_h), HVM_SAVE_CODE(_x), \ + HVM_SAVE_LENGTH(_x), (_strict))) == 0 ) \ + { \ + _hvm_read_entry((_h), (_dst), HVM_SAVE_LENGTH(_x)); \ + if ( HVM_SAVE_HAS_COMPAT(_x) && \ + desc->length != HVM_SAVE_LENGTH(_x) ) \ + r = HVM_SAVE_FIX_COMPAT(_x, (_dst), desc->length); \ + } \ + else if (HVM_SAVE_HAS_COMPAT(_x) \ + && (r = _hvm_check_entry((_h), HVM_SAVE_CODE(_x), \ + HVM_SAVE_LENGTH_COMPAT(_x), (_strict))) == 0 ) { \ + _hvm_read_entry((_h), (_dst), HVM_SAVE_LENGTH_COMPAT(_x)); \ + r = HVM_SAVE_FIX_COMPAT(_x, (_dst), desc->length); \ + } \ + r; }) + +#define hvm_load_entry(_x, _h, _dst) \ + _hvm_load_entry(_x, _h, _dst, 1) +#define hvm_load_entry_zeroextend(_x, _h, _dst) \ + _hvm_load_entry(_x, _h, _dst, 0) + +/* Unmarshalling: what is the instance ID of the next entry? */ +static inline uint16_t hvm_load_instance(struct hvm_domain_context *h) +{ + struct hvm_save_descriptor *d + = (struct hvm_save_descriptor *)&h->data[h->cur]; + return d->instance; +} + +/* Handler types for different types of save-file entry. + * The save handler may save multiple instances of a type into the buffer; + * the load handler will be called once for each instance found when + * restoring. Both return non-zero on error. */ +typedef int (*hvm_save_handler) (struct domain *d, + hvm_domain_context_t *h); +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, + * 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, + 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 __init __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_save_one(struct domain *d, unsigned int typecode, unsigned int instance, + XEN_GUEST_HANDLE_64(uint8) handle, uint64_t *bufsz); +int hvm_load(struct domain *d, hvm_domain_context_t *h); + +/* Arch-specific definitions. */ +struct hvm_save_header; +void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr); +int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr); + +#endif /* __XEN_HVM_SAVE_H__ */ diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h index 8a1252b29e..b18dbb6d43 100644 --- a/xen/include/asm-x86/hvm/support.h +++ b/xen/include/asm-x86/hvm/support.h @@ -22,7 +22,7 @@ #include #include -#include +#include #include #ifndef NDEBUG diff --git a/xen/include/xen/hvm/save.h b/xen/include/xen/hvm/save.h deleted file mode 100644 index f889e8fe1d..0000000000 --- a/xen/include/xen/hvm/save.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * save.h: HVM support routines for save/restore - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; If not, see . - */ - -#ifndef __XEN_HVM_SAVE_H__ -#define __XEN_HVM_SAVE_H__ - -#include -#include -#include -#include - -/* Marshalling and unmarshalling uses a buffer with size and cursor. */ -typedef struct hvm_domain_context { - uint32_t cur; - uint32_t size; - uint8_t *data; -} hvm_domain_context_t; - -/* Marshalling an entry: check space and fill in the header */ -int _hvm_init_entry(struct hvm_domain_context *h, - uint16_t tc, uint16_t inst, uint32_t len); - -/* Marshalling: copy the contents in a type-safe way */ -void _hvm_write_entry(struct hvm_domain_context *h, - void *src, uint32_t src_len); - -/* Marshalling: init and copy; evaluates to zero on success */ -#define hvm_save_entry(_x, _inst, _h, _src) ({ \ - int r; \ - r = _hvm_init_entry((_h), HVM_SAVE_CODE(_x), \ - (_inst), HVM_SAVE_LENGTH(_x)); \ - if ( r == 0 ) \ - _hvm_write_entry((_h), (_src), HVM_SAVE_LENGTH(_x)); \ - r; }) - -/* Unmarshalling: test an entry's size and typecode and record the instance */ -int _hvm_check_entry(struct hvm_domain_context *h, - uint16_t type, uint32_t len, bool_t strict_length); - -/* Unmarshalling: copy the contents in a type-safe way */ -void _hvm_read_entry(struct hvm_domain_context *h, - void *dest, uint32_t dest_len); - -/* - * Unmarshalling: check, then copy. Evaluates to zero on success. This load - * function requires the save entry to be the same size as the dest structure. - */ -#define _hvm_load_entry(_x, _h, _dst, _strict) ({ \ - int r; \ - struct hvm_save_descriptor *desc \ - = (struct hvm_save_descriptor *)&(_h)->data[(_h)->cur]; \ - if ( (r = _hvm_check_entry((_h), HVM_SAVE_CODE(_x), \ - HVM_SAVE_LENGTH(_x), (_strict))) == 0 ) \ - { \ - _hvm_read_entry((_h), (_dst), HVM_SAVE_LENGTH(_x)); \ - if ( HVM_SAVE_HAS_COMPAT(_x) && \ - desc->length != HVM_SAVE_LENGTH(_x) ) \ - r = HVM_SAVE_FIX_COMPAT(_x, (_dst), desc->length); \ - } \ - else if (HVM_SAVE_HAS_COMPAT(_x) \ - && (r = _hvm_check_entry((_h), HVM_SAVE_CODE(_x), \ - HVM_SAVE_LENGTH_COMPAT(_x), (_strict))) == 0 ) { \ - _hvm_read_entry((_h), (_dst), HVM_SAVE_LENGTH_COMPAT(_x)); \ - r = HVM_SAVE_FIX_COMPAT(_x, (_dst), desc->length); \ - } \ - r; }) - -#define hvm_load_entry(_x, _h, _dst) \ - _hvm_load_entry(_x, _h, _dst, 1) -#define hvm_load_entry_zeroextend(_x, _h, _dst) \ - _hvm_load_entry(_x, _h, _dst, 0) - -/* Unmarshalling: what is the instance ID of the next entry? */ -static inline uint16_t hvm_load_instance(struct hvm_domain_context *h) -{ - struct hvm_save_descriptor *d - = (struct hvm_save_descriptor *)&h->data[h->cur]; - return d->instance; -} - -/* Handler types for different types of save-file entry. - * The save handler may save multiple instances of a type into the buffer; - * the load handler will be called once for each instance found when - * restoring. Both return non-zero on error. */ -typedef int (*hvm_save_handler) (struct domain *d, - hvm_domain_context_t *h); -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, - * 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, - 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 __init __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_save_one(struct domain *d, unsigned int typecode, unsigned int instance, - XEN_GUEST_HANDLE_64(uint8) handle, uint64_t *bufsz); -int hvm_load(struct domain *d, hvm_domain_context_t *h); - -/* Arch-specific definitions. */ -struct hvm_save_header; -void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr); -int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr); - -#endif /* __XEN_HVM_SAVE_H__ */