diff mbox series

[v2,1/5] x86/HVM: introduce hvm_point_entry()

Message ID 9810305d-4b36-4e23-b807-a7a00f0ba6b6@suse.com (mailing list archive)
State Superseded
Headers show
Series x86/HVM: load state checking | expand

Commit Message

Jan Beulich Nov. 16, 2023, 1:46 p.m. UTC
... 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>
---
v2: New.

Comments

Andrew Cooper Nov. 21, 2023, 9:30 p.m. UTC | #1
On 16/11/2023 1:46 pm, Jan Beulich wrote:
> ... 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>

I really do hate all of this logic and most of it wants to live in
userspace, but this an improvement.

The only thing I'm a little concerned with is the name. 
hvm_read_entry() clearly consumes an entry, while hvm_point_entry()
does, but doesn't obviously convey this at a glance.

Ideally I'd say that hvm_{get,copy}_entry() would be better nomeclature,
as both have at least a vague implication of unmarshalling and one
clearly is making a separate copy.

Thoughts?

~Andrew
Jan Beulich Nov. 22, 2023, 9:34 a.m. UTC | #2
On 21.11.2023 22:30, Andrew Cooper wrote:
> On 16/11/2023 1:46 pm, Jan Beulich wrote:
>> ... 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>

Thanks.

> I really do hate all of this logic and most of it wants to live in
> userspace, but this an improvement.
> 
> The only thing I'm a little concerned with is the name. 
> hvm_read_entry() clearly consumes an entry, while hvm_point_entry()
> does, but doesn't obviously convey this at a glance.
> 
> Ideally I'd say that hvm_{get,copy}_entry() would be better nomeclature,
> as both have at least a vague implication of unmarshalling and one
> clearly is making a separate copy.

I'm fine renaming the new one to hvm_get_entry(). For the existing one,
"copy" may be marginally better than "read" / "load", but then it doesn't
indicate direction (i.e. somewhat collides with hvm_{write,load}_entry()).
So I'd want to leave those as they are.

Jan
Andrew Cooper Nov. 22, 2023, 9:54 a.m. UTC | #3
On 22/11/2023 9:34 am, Jan Beulich wrote:
> On 21.11.2023 22:30, Andrew Cooper wrote:
>> On 16/11/2023 1:46 pm, Jan Beulich wrote:
>>> ... 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>
> Thanks.
>
>> I really do hate all of this logic and most of it wants to live in
>> userspace, but this an improvement.
>>
>> The only thing I'm a little concerned with is the name. 
>> hvm_read_entry() clearly consumes an entry, while hvm_point_entry()
>> does, but doesn't obviously convey this at a glance.
>>
>> Ideally I'd say that hvm_{get,copy}_entry() would be better nomeclature,
>> as both have at least a vague implication of unmarshalling and one
>> clearly is making a separate copy.
> I'm fine renaming the new one to hvm_get_entry(). For the existing one,
> "copy" may be marginally better than "read" / "load", but then it doesn't
> indicate direction (i.e. somewhat collides with hvm_{write,load}_entry()).
> So I'd want to leave those as they are.

Ok, get/read/write make a reasonably-ok set of names.

~Andrew
diff mbox series

Patch

--- 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_point_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_point_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_point_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__ */