... to accompany hvm_read_entry() when actual copying isn't desirable.
This allows to remove open-coded stream accesses from hpet_load(),
along with using the helper in hvm_load() itself.
Since arch_hvm_load()'s declaration would need changing, and since the
function is not used from elsewhere, purge the declaration. With that it
makes little sense to keep arch_hvm_save()'s around; convert that
function to static then at the same time.
In hpet_load() simplify the specific case of error return that's in
context anyway: There's no need to hold the lock when only updating a
local variable.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
v3: Rename to hvm_get_entry().
v2: New.
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -637,7 +637,7 @@ static int cf_check hpet_save(struct vcp
static int cf_check hpet_load(struct domain *d, hvm_domain_context_t *h)
{
HPETState *hp = domain_vhpet(d);
- struct hvm_hw_hpet *rec;
+ const struct hvm_hw_hpet *rec;
uint64_t cmp;
uint64_t guest_time;
int i;
@@ -645,17 +645,12 @@ static int cf_check hpet_load(struct dom
if ( !has_vhpet(d) )
return -ENODEV;
- write_lock(&hp->lock);
-
/* Reload the HPET registers */
- if ( _hvm_check_entry(h, HVM_SAVE_CODE(HPET), HVM_SAVE_LENGTH(HPET), 1) )
- {
- write_unlock(&hp->lock);
+ rec = hvm_get_entry(HPET, h);
+ if ( !rec )
return -EINVAL;
- }
- rec = (struct hvm_hw_hpet *)&h->data[h->cur];
- h->cur += HVM_SAVE_LENGTH(HPET);
+ write_lock(&hp->lock);
#define C(x) hp->hpet.x = rec->x
C(capability);
--- a/xen/arch/x86/hvm/save.c
+++ b/xen/arch/x86/hvm/save.c
@@ -15,7 +15,7 @@
#include <public/hvm/save.h>
-void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr)
+static void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr)
{
uint32_t eax, ebx, ecx, edx;
@@ -30,7 +30,7 @@ void arch_hvm_save(struct domain *d, str
d->arch.hvm.sync_tsc = rdtsc();
}
-int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr)
+static int arch_hvm_load(struct domain *d, const struct hvm_save_header *hdr)
{
uint32_t eax, ebx, ecx, edx;
@@ -277,7 +277,7 @@ int hvm_save(struct domain *d, hvm_domai
int hvm_load(struct domain *d, hvm_domain_context_t *h)
{
- struct hvm_save_header hdr;
+ const struct hvm_save_header *hdr;
struct hvm_save_descriptor *desc;
hvm_load_handler handler;
struct vcpu *v;
@@ -286,11 +286,12 @@ int hvm_load(struct domain *d, hvm_domai
if ( d->is_dying )
return -EINVAL;
- /* Read the save header, which must be first */
- if ( hvm_load_entry(HEADER, h, &hdr) != 0 )
+ /* Get at the save header, which must be first */
+ hdr = hvm_get_entry(HEADER, h);
+ if ( !hdr )
return -ENODATA;
- rc = arch_hvm_load(d, &hdr);
+ rc = arch_hvm_load(d, hdr);
if ( rc )
return rc;
--- a/xen/arch/x86/include/asm/hvm/save.h
+++ b/xen/arch/x86/include/asm/hvm/save.h
@@ -39,6 +39,21 @@ void _hvm_write_entry(struct hvm_domain_
int _hvm_check_entry(struct hvm_domain_context *h,
uint16_t type, uint32_t len, bool strict_length);
+/*
+ * Unmarshalling: check, then return pointer. Evaluates to non-NULL on success.
+ * This macro requires the save entry to be the same size as the dest structure.
+ */
+#define hvm_get_entry(x, h) ({ \
+ const void *ptr = NULL; \
+ BUILD_BUG_ON(HVM_SAVE_HAS_COMPAT(x)); \
+ if ( _hvm_check_entry(h, HVM_SAVE_CODE(x), \
+ HVM_SAVE_LENGTH(x), true) == 0 ) \
+ { \
+ ptr = &(h)->data[(h)->cur]; \
+ h->cur += HVM_SAVE_LENGTH(x); \
+ } \
+ ptr; })
+
/* Unmarshalling: copy the contents in a type-safe way */
void _hvm_read_entry(struct hvm_domain_context *h,
void *dest, uint32_t dest_len);
@@ -127,9 +142,4 @@ int hvm_save_one(struct domain *d, unsig
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__ */