From: Paul Durrant <pdurr...@amazon.com>

If the shared_info PFN cache has already been initialized then the content
of the shared_info page needs to be re-initialized whenever the guest
mode is (re)set.
Setting the guest mode is either done explicitly by the VMM via the
KVM_XEN_ATTR_TYPE_LONG_MODE attribute, or implicitly when the guest writes
the MSR to set up the hypercall page.

Signed-off-by: Paul Durrant <pdurr...@amazon.com>
Reviewed-by: David Woodhouse <d...@amazon.co.uk>
---
Cc: Sean Christopherson <sea...@google.com>
Cc: Paolo Bonzini <pbonz...@redhat.com>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Borislav Petkov <b...@alien8.de>
Cc: Dave Hansen <dave.han...@linux.intel.com>
Cc: "H. Peter Anvin" <h...@zytor.com>
Cc: David Woodhouse <dw...@infradead.org>
Cc: x...@kernel.org

v13:
 - Patch title change.

v12:
 - Fix missing update of return value if mode is not actually changed.

v11:
 - Drop the hunk removing the call to kvm_xen_shared_info_init() when
   KVM_XEN_ATTR_TYPE_SHARED_INFO is set; it was a mistake and causes self-
   test failures.

v10:
 - New in this version.
---
 arch/x86/kvm/xen.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 031e98d88ba2..52edf676c471 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -625,8 +625,16 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct 
kvm_xen_hvm_attr *data)
                } else {
                        mutex_lock(&kvm->arch.xen.xen_lock);
                        kvm->arch.xen.long_mode = !!data->u.long_mode;
+
+                       /*
+                        * Re-initialize shared_info to put the wallclock in the
+                        * correct place. Whilst it's not necessary to do this
+                        * unless the mode is actually changed, it does no harm
+                        * to make the call anyway.
+                        */
+                       r = kvm->arch.xen.shinfo_cache.active ?
+                               kvm_xen_shared_info_init(kvm) : 0;
                        mutex_unlock(&kvm->arch.xen.xen_lock);
-                       r = 0;
                }
                break;
 
@@ -1101,9 +1109,24 @@ int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, 
u64 data)
        u32 page_num = data & ~PAGE_MASK;
        u64 page_addr = data & PAGE_MASK;
        bool lm = is_long_mode(vcpu);
+       int r = 0;
+
+       mutex_lock(&kvm->arch.xen.xen_lock);
+       if (kvm->arch.xen.long_mode != lm) {
+               kvm->arch.xen.long_mode = lm;
+
+               /*
+                * Re-initialize shared_info to put the wallclock in the
+                * correct place.
+                */
+               if (kvm->arch.xen.shinfo_cache.active &&
+                   kvm_xen_shared_info_init(kvm))
+                       r = 1;
+       }
+       mutex_unlock(&kvm->arch.xen.xen_lock);
 
-       /* Latch long_mode for shared_info pages etc. */
-       vcpu->kvm->arch.xen.long_mode = lm;
+       if (r)
+               return r;
 
        /*
         * If Xen hypercall intercept is enabled, fill the hypercall
-- 
2.39.2


Reply via email to