]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KVM: x86/xen: setup pvclock updates
authorJoao Martins <joao.m.martins@oracle.com>
Fri, 1 Feb 2019 18:01:45 +0000 (13:01 -0500)
committerJoao Martins <joao.m.martins@oracle.com>
Wed, 20 Feb 2019 17:30:52 +0000 (12:30 -0500)
This means when we set shared_info page GPA, and request a master
clock update. This will trigger all vcpus to update their respective
shared pvclock data with guests. We follow a similar approach
as Hyper-V and KVM and adjust it accordingly.

Note however that Xen differs a little on how pvclock pages are set up.
Specifically KVM assumes 4K page alignment and pvclock data starts in
the beginning of the page. Whereas Xen you can place that information
anywhere in the page.

Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
arch/x86/kvm/x86.c
arch/x86/kvm/xen.c
arch/x86/kvm/xen.h

index 1eda9630418036d27274b549df364e2d082207da..6eb2afaa2af2688c449c8c020d1b02a43884b8ed 100644 (file)
@@ -2211,6 +2211,8 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 
        if (vcpu->pv_time_enabled)
                kvm_setup_pvclock_page(v);
+       if (ka->xen.shinfo)
+               kvm_xen_setup_pvclock_page(v);
        if (v == kvm_get_vcpu(v->kvm, 0))
                kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock);
        return 0;
index 4df223bd3cd7a3753deecde4de521e25abbfd6ef..b4bd1949656eb6de7f4af0a41ded6164f91dcef5 100644 (file)
@@ -29,9 +29,56 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
        shared_info = page_to_virt(page);
        memset(shared_info, 0, sizeof(struct shared_info));
        kvm->arch.xen.shinfo = shared_info;
+
+       kvm_make_all_cpus_request(kvm, KVM_REQ_MASTERCLOCK_UPDATE);
        return 0;
 }
 
+void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v)
+{
+       struct kvm_vcpu_arch *vcpu = &v->arch;
+       struct pvclock_vcpu_time_info *guest_hv_clock;
+       unsigned int offset;
+
+       if (v->vcpu_id >= MAX_VIRT_CPUS)
+               return;
+
+       offset = offsetof(struct vcpu_info, time);
+       offset += offsetof(struct shared_info, vcpu_info);
+       offset += v->vcpu_id * sizeof(struct vcpu_info);
+
+       guest_hv_clock = (struct pvclock_vcpu_time_info *)
+               (((void *)v->kvm->arch.xen.shinfo) + offset);
+
+       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;
+       guest_hv_clock->version = 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);
+
+       *guest_hv_clock = vcpu->hv_clock;
+
+       smp_wmb();
+
+       vcpu->hv_clock.version++;
+
+       guest_hv_clock->version = vcpu->hv_clock.version;
+}
+
 int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
 {
        int r = -ENOENT;
index bb38edf383fe55117bb48b1ce7ba79f1db75e12e..827c9390da34afe8f3f01477de7448dd7f3ec108 100644 (file)
@@ -3,6 +3,7 @@
 #ifndef __ARCH_X86_KVM_XEN_H__
 #define __ARCH_X86_KVM_XEN_H__
 
+void kvm_xen_setup_pvclock_page(struct kvm_vcpu *vcpu);
 int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
 int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
 bool kvm_xen_hypercall_enabled(struct kvm *kvm);