]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KVM: x86/xen: Use gfn_to_pfn_cache for vcpu_time_info
authorDavid Woodhouse <dwmw@amazon.co.uk>
Wed, 9 Feb 2022 17:45:26 +0000 (17:45 +0000)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Thu, 24 Feb 2022 10:10:05 +0000 (10:10 +0000)
This switches the final pvclock to kvm_setup_pvclock_pfncache() and now
the old kvm_setup_pvclock_page() can be removed.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/x86.c
arch/x86/kvm/xen.c

index 2b5a1a0bdcd46c1b1697ddc3ac46a950c3ac51d8..0361e6f3dac0fe4c821296232c73949109ac9f54 100644 (file)
@@ -600,9 +600,8 @@ struct kvm_vcpu_hv {
 struct kvm_vcpu_xen {
        u64 hypercall_rip;
        u32 current_runstate;
-       bool vcpu_time_info_set;
        struct gfn_to_pfn_cache vcpu_info_cache;
-       struct gfn_to_hva_cache vcpu_time_info_cache;
+       struct gfn_to_pfn_cache vcpu_time_info_cache;
        struct gfn_to_pfn_cache runstate_cache;
        u64 last_steal;
        u64 runstate_entry_time;
index 9147408ddb1e27c5fbc9e8ab535b2738e6a4d97d..5a00b65f8da08d6cbbb5da1dc0e306a14e2cf079 100644 (file)
@@ -2994,65 +2994,6 @@ static void kvm_setup_guest_pvclock(struct kvm_vcpu *v,
        trace_kvm_pvclock_update(v->vcpu_id, &vcpu->hv_clock);
 }
 
-static void kvm_setup_pvclock_page(struct kvm_vcpu *v,
-                                  struct gfn_to_hva_cache *cache,
-                                  unsigned int offset)
-{
-       struct kvm_vcpu_arch *vcpu = &v->arch;
-       struct pvclock_vcpu_time_info guest_hv_clock;
-
-       if (unlikely(kvm_read_guest_offset_cached(v->kvm, cache,
-               &guest_hv_clock, offset, sizeof(guest_hv_clock))))
-               return;
-
-       /* This VCPU is paused, but it's legal for a guest to read another
-        * VCPU's kvmclock, so we really have to follow the specification where
-        * it says that version is odd if data is being modified, and even after
-        * it is consistent.
-        *
-        * Version field updates must be kept separate.  This is because
-        * kvm_write_guest_cached might use a "rep movs" instruction, and
-        * writes within a string instruction are weakly ordered.  So there
-        * are three writes overall.
-        *
-        * As a small optimization, only write the version field in the first
-        * and third write.  The vcpu->pv_time cache is still valid, because the
-        * version field is the first in the struct.
-        */
-       BUILD_BUG_ON(offsetof(struct pvclock_vcpu_time_info, version) != 0);
-
-       if (guest_hv_clock.version & 1)
-               ++guest_hv_clock.version;  /* first time write, random junk */
-
-       vcpu->hv_clock.version = guest_hv_clock.version + 1;
-       kvm_write_guest_offset_cached(v->kvm, cache,
-                                     &vcpu->hv_clock, offset,
-                                     sizeof(vcpu->hv_clock.version));
-
-       smp_wmb();
-
-       /* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
-       vcpu->hv_clock.flags |= (guest_hv_clock.flags & PVCLOCK_GUEST_STOPPED);
-
-       if (vcpu->pvclock_set_guest_stopped_request) {
-               vcpu->hv_clock.flags |= PVCLOCK_GUEST_STOPPED;
-               vcpu->pvclock_set_guest_stopped_request = false;
-       }
-
-       trace_kvm_pvclock_update(v->vcpu_id, &vcpu->hv_clock);
-
-       kvm_write_guest_offset_cached(v->kvm, cache,
-                                     &vcpu->hv_clock, offset,
-                                     sizeof(vcpu->hv_clock));
-
-       smp_wmb();
-
-       vcpu->hv_clock.version++;
-       kvm_write_guest_offset_cached(v->kvm, cache,
-                                    &vcpu->hv_clock, offset,
-                                    sizeof(vcpu->hv_clock.version));
-}
-
 static int kvm_guest_time_update(struct kvm_vcpu *v)
 {
        unsigned long flags, tgt_tsc_khz;
@@ -3144,8 +3085,8 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
        if (vcpu->xen.vcpu_info_cache.active)
                kvm_setup_guest_pvclock(v, &vcpu->xen.vcpu_info_cache,
                                        offsetof(struct compat_vcpu_info, time));
-       if (vcpu->xen.vcpu_time_info_set)
-               kvm_setup_pvclock_page(v, &vcpu->xen.vcpu_time_info_cache, 0);
+       if (vcpu->xen.vcpu_time_info_cache.active)
+               kvm_setup_guest_pvclock(v, &vcpu->xen.vcpu_time_info_cache, 0);
        if (!v->vcpu_idx)
                kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock);
        return 0;
index cde98cf82def83a5f2c16b45e3bfc577b33fceec..83c810748bd7486223ab33b398389b9185972bef 100644 (file)
@@ -466,25 +466,19 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
 
        case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO:
                if (data->u.gpa == GPA_INVALID) {
-                       vcpu->arch.xen.vcpu_time_info_set = false;
+                       kvm_gfn_to_pfn_cache_destroy(vcpu->kvm,
+                                                    &vcpu->arch.xen.vcpu_time_info_cache);
                        r = 0;
                        break;
                }
 
-               /* It must fit within a single page */
-               if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct pvclock_vcpu_time_info) > PAGE_SIZE) {
-                       r = -EINVAL;
-                       break;
-               }
-
-               r = kvm_gfn_to_hva_cache_init(vcpu->kvm,
+               r = kvm_gfn_to_pfn_cache_init(vcpu->kvm,
                                              &vcpu->arch.xen.vcpu_time_info_cache,
-                                             data->u.gpa,
-                                             sizeof(struct pvclock_vcpu_time_info));
-               if (!r) {
-                       vcpu->arch.xen.vcpu_time_info_set = true;
+                                             NULL, KVM_HOST_USES_PFN, data->u.gpa,
+                                             sizeof(struct pvclock_vcpu_time_info),
+                                             false);
+               if (!r)
                        kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
-               }
                break;
 
        case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR:
@@ -626,7 +620,7 @@ int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
                break;
 
        case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO:
-               if (vcpu->arch.xen.vcpu_time_info_set)
+               if (vcpu->arch.xen.vcpu_time_info_cache.active)
                        data->u.gpa = vcpu->arch.xen.vcpu_time_info_cache.gpa;
                else
                        data->u.gpa = GPA_INVALID;
@@ -1072,4 +1066,7 @@ void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
        vcpu->arch.xen.vcpu_info_cache.dirty = false;
        kvm_gfn_to_pfn_cache_destroy(vcpu->kvm,
                                     &vcpu->arch.xen.vcpu_info_cache);
+       vcpu->arch.xen.vcpu_time_info_cache.dirty = false;
+       kvm_gfn_to_pfn_cache_destroy(vcpu->kvm,
+                                    &vcpu->arch.xen.vcpu_time_info_cache);
 }