#include <xen/delay.h>
#include <xen/smp.h>
#include <xen/mm.h>
-#include <xen/hvm/save.h>
+#include <asm/hvm/save.h>
#include <asm/processor.h>
#include <public/sysctl.h>
#include <asm/system.h>
*/
#include <xen/xenoprof.h>
-#include <xen/hvm/save.h>
#include <xen/sched.h>
#include <xen/irq.h>
#include <asm/apic.h>
#include <asm/vpmu.h>
+#include <asm/hvm/save.h>
#include <asm/hvm/vlapic.h>
#include <public/pmu.h>
* this program; If not, see <http://www.gnu.org/licenses/>.
*/
+#include <xen/guest_access.h>
+#include <xen/version.h>
+
#include <asm/hvm/support.h>
+
#include <public/hvm/save.h>
void arch_hvm_save(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
tmem-$(CONFIG_COMPAT) += compat/tmem_xen.o
obj-$(CONFIG_TMEM) += $(tmem-y)
-subdir-$(CONFIG_X86) += hvm
-
subdir-$(CONFIG_GCOV) += gcov
subdir-y += libelf
+++ /dev/null
-obj-y += save.o
+++ /dev/null
-/*
- * 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 <yamahata at valinux co jp>
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#include <xen/lib.h>
-#include <xen/version.h>
-#include <public/version.h>
-#include <xen/sched.h>
-#include <xen/guest_access.h>
-
-#include <asm/hvm/support.h>
-
-/* 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:
- */
--- /dev/null
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XEN_HVM_SAVE_H__
+#define __XEN_HVM_SAVE_H__
+
+#include <xen/types.h>
+#include <xen/init.h>
+#include <public/xen.h>
+#include <public/hvm/save.h>
+
+/* 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__ */
#include <xen/types.h>
#include <xen/sched.h>
-#include <xen/hvm/save.h>
+#include <asm/hvm/save.h>
#include <asm/processor.h>
#ifndef NDEBUG
+++ /dev/null
-/*
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __XEN_HVM_SAVE_H__
-#define __XEN_HVM_SAVE_H__
-
-#include <xen/types.h>
-#include <xen/init.h>
-#include <public/xen.h>
-#include <public/hvm/save.h>
-
-/* 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__ */