aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2011-04-07 15:40:02 +0100
committerKeir Fraser <keir@xen.org>2011-04-07 15:40:02 +0100
commit5b713d432463659eb64488976a385aa7e64279d9 (patch)
treedb7f3c6679e1fc1b4362272cfc71707b00c8a5cd
parent19dcac71b39cb11f74b083dd5c9327362ea94476 (diff)
downloadxen-5b713d432463659eb64488976a385aa7e64279d9.tar.gz
xen-5b713d432463659eb64488976a385aa7e64279d9.tar.bz2
xen-5b713d432463659eb64488976a385aa7e64279d9.zip
hvm save: Introduce hvm_load_entry_zeroextend().
In certain cases this will allow us to load old HVM save images where an HVM saved chunk has subsequently been extended with new fields. Rather than fail to load the chunk, we can pad the extended structure with zeroes, if the caller knows how to handle that. Signed-off-by: Keir Fraser <keir@xen.org> Acked-by: Tim Deegan <Tim.Deegan@citrix.com> xen-unstable changeset: 22524:1f08b2932a52 xen-unstable date: Wed Dec 15 10:21:05 2010 +0000
-rw-r--r--xen/arch/x86/hvm/hpet.c2
-rw-r--r--xen/common/hvm/save.c14
-rw-r--r--xen/include/xen/hvm/save.h17
3 files changed, 22 insertions, 11 deletions
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index 25acad8e3e..fecfff253e 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -546,7 +546,7 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h)
spin_lock(&hp->lock);
/* Reload the HPET registers */
- if ( _hvm_check_entry(h, HVM_SAVE_CODE(HPET), HVM_SAVE_LENGTH(HPET)) )
+ if ( _hvm_check_entry(h, HVM_SAVE_CODE(HPET), HVM_SAVE_LENGTH(HPET), 1) )
{
spin_unlock(&hp->lock);
return -EINVAL;
diff --git a/xen/common/hvm/save.c b/xen/common/hvm/save.c
index 7a312dbfe8..24c7227e70 100644
--- a/xen/common/hvm/save.c
+++ b/xen/common/hvm/save.c
@@ -272,7 +272,7 @@ void _hvm_write_entry(struct hvm_domain_context *h,
}
int _hvm_check_entry(struct hvm_domain_context *h,
- uint16_t type, uint32_t len)
+ uint16_t type, uint32_t len, bool_t strict_length)
{
struct hvm_save_descriptor *d
= (struct hvm_save_descriptor *)&h->data[h->cur];
@@ -283,7 +283,8 @@ int _hvm_check_entry(struct hvm_domain_context *h,
"for type %u\n", len, type);
return -1;
}
- if ( (type != d->typecode) || (len != d->length) )
+ if ( (type != d->typecode) || (len < d->length) ||
+ (strict_length && (len != d->length)) )
{
gdprintk(XENLOG_WARNING,
"HVM restore mismatch: expected type %u length %u, "
@@ -297,8 +298,13 @@ int _hvm_check_entry(struct hvm_domain_context *h,
void _hvm_read_entry(struct hvm_domain_context *h,
void *dest, uint32_t dest_len)
{
- memcpy(dest, &h->data[h->cur], dest_len);
- h->cur += 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;
}
/*
diff --git a/xen/include/xen/hvm/save.h b/xen/include/xen/hvm/save.h
index 8fc322d6e5..512311fd55 100644
--- a/xen/include/xen/hvm/save.h
+++ b/xen/include/xen/hvm/save.h
@@ -48,7 +48,7 @@ void _hvm_write_entry(struct hvm_domain_context *h,
/* 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);
+ 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,
@@ -58,12 +58,17 @@ void _hvm_read_entry(struct hvm_domain_context *h,
* 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) ({ \
- int r; \
- r = _hvm_check_entry((_h), HVM_SAVE_CODE(_x), HVM_SAVE_LENGTH(_x)); \
- if ( r == 0 ) \
- _hvm_read_entry((_h), (_dst), HVM_SAVE_LENGTH(_x)); \
+#define _hvm_load_entry(_x, _h, _dst, _strict) ({ \
+ int r; \
+ r = _hvm_check_entry((_h), HVM_SAVE_CODE(_x), \
+ HVM_SAVE_LENGTH(_x), (_strict)); \
+ if ( r == 0 ) \
+ _hvm_read_entry((_h), (_dst), HVM_SAVE_LENGTH(_x)); \
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)