]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KVM: x86/xen: update wallclock region
authorJoao Martins <joao.m.martins@oracle.com>
Thu, 28 Jun 2018 19:06:43 +0000 (15:06 -0400)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Sat, 12 Dec 2020 19:04:11 +0000 (19:04 +0000)
Wallclock on Xen is written in the shared_info page.

To that purpose, export kvm_write_wall_clock() and pass on the GPA of
its location to populate the shared_info wall clock data.

Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/kvm/xen.c

index 975ef5d6dda1fb74cdab17829d04b4d8b9f37e9a..64016443159c0316f2f0ca8b8742444beac59aa7 100644 (file)
@@ -1921,15 +1921,14 @@ static s64 get_kvmclock_base_ns(void)
 }
 #endif
 
-static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
+void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock, int sec_hi_ofs)
 {
        int version;
        int r;
        struct pvclock_wall_clock wc;
+       u32 wc_sec_hi;
        u64 wall_nsec;
 
-       kvm->arch.wall_clock = wall_clock;
-
        if (!wall_clock)
                return;
 
@@ -1958,6 +1957,12 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
 
        kvm_write_guest(kvm, wall_clock, &wc, sizeof(wc));
 
+       if (sec_hi_ofs) {
+               wc_sec_hi = wall_nsec >> 32;
+               kvm_write_guest(kvm, wall_clock + sec_hi_ofs,
+                               &wc_sec_hi, sizeof(wc_sec_hi));
+       }
+
        version++;
        kvm_write_guest(kvm, wall_clock, &version, sizeof(version));
 }
@@ -3115,13 +3120,15 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE2))
                        return 1;
 
-               kvm_write_wall_clock(vcpu->kvm, data);
+               vcpu->kvm->arch.wall_clock = data;
+               kvm_write_wall_clock(vcpu->kvm, data, 0);
                break;
        case MSR_KVM_WALL_CLOCK:
                if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE))
                        return 1;
 
-               kvm_write_wall_clock(vcpu->kvm, data);
+               vcpu->kvm->arch.wall_clock = data;
+               kvm_write_wall_clock(vcpu->kvm, data, 0);
                break;
        case MSR_KVM_SYSTEM_TIME_NEW:
                if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE2))
index e7ca622a468f5f14538f10b6bbed473f30108b49..cf8778410015f9b9bda96ce957c6cfb8f1558893 100644 (file)
@@ -246,6 +246,7 @@ static inline bool kvm_vcpu_latch_init(struct kvm_vcpu *vcpu)
        return is_smm(vcpu) || kvm_x86_ops.apic_init_signal_blocked(vcpu);
 }
 
+void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock, int sec_hi_ofs);
 void kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
 
 void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr);
index 9dd9c42842b8f0caf40913a49af8a8e3ef5476da..e5117a6117370368ff0ae7d2f863928b08c2acc5 100644 (file)
 
 static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
 {
+       gpa_t gpa = gfn_to_gpa(gfn);
+       int wc_ofs, sec_hi_ofs;
        int ret;
 
        ret = kvm_gfn_to_hva_cache_init(kvm, &kvm->arch.xen.shinfo_cache,
-                                       gfn_to_gpa(gfn), PAGE_SIZE);
+                                       gpa, PAGE_SIZE);
        if (ret)
                return ret;
 
        kvm->arch.xen.shinfo_set = true;
+
+       /* Paranoia checks on the 32-bit struct layout */
+       BUILD_BUG_ON(offsetof(struct compat_shared_info, wc) != 0x900);
+       BUILD_BUG_ON(offsetof(struct compat_shared_info, arch.wc_sec_hi) != 0x924);
+       BUILD_BUG_ON(offsetof(struct pvclock_vcpu_time_info, version) != 0);
+
+       /* 32-bit location by default */
+       wc_ofs = offsetof(struct compat_shared_info, wc);
+       sec_hi_ofs = offsetof(struct compat_shared_info, arch.wc_sec_hi);
+
+#ifdef CONFIG_X86_64
+       /* Paranoia checks on the 64-bit struct layout */
+       BUILD_BUG_ON(offsetof(struct shared_info, wc) != 0xc00);
+       BUILD_BUG_ON(offsetof(struct shared_info, wc_sec_hi) != 0xc0c);
+
+       if (kvm->arch.xen.long_mode) {
+               wc_ofs = offsetof(struct shared_info, wc);
+               sec_hi_ofs = offsetof(struct shared_info, wc_sec_hi);
+       }
+#endif
+
+       kvm_write_wall_clock(kvm, gpa + wc_ofs, sec_hi_ofs - wc_ofs);
+       kvm_make_all_cpus_request(kvm, KVM_REQ_MASTERCLOCK_UPDATE);
+
        return 0;
 }