diff options
author | Keir Fraser <keir@xen.org> | 2011-04-07 15:40:02 +0100 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2011-04-07 15:40:02 +0100 |
commit | 5b713d432463659eb64488976a385aa7e64279d9 (patch) | |
tree | db7f3c6679e1fc1b4362272cfc71707b00c8a5cd | |
parent | 19dcac71b39cb11f74b083dd5c9327362ea94476 (diff) | |
download | xen-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.c | 2 | ||||
-rw-r--r-- | xen/common/hvm/save.c | 14 | ||||
-rw-r--r-- | xen/include/xen/hvm/save.h | 17 |
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) |