Refactor kvm_synchronize_tsc to make a new function that allows callers
to specify TSC parameters (offset, value, nanoseconds, etc.) explicitly
for the sake of participating in TSC synchronization.

Signed-off-by: Oliver Upton <oup...@google.com>
---
 arch/x86/kvm/x86.c | 105 ++++++++++++++++++++++++++-------------------
 1 file changed, 61 insertions(+), 44 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 93b449761fbe..91aea751d621 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2443,13 +2443,71 @@ static inline bool kvm_check_tsc_unstable(void)
        return check_tsc_unstable();
 }
 
+/*
+ * Infers attempts to synchronize the guest's tsc from host writes. Sets the
+ * offset for the vcpu and tracks the TSC matching generation that the vcpu
+ * participates in.
+ */
+static void __kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 offset, u64 tsc,
+                                 u64 ns, bool matched)
+{
+       struct kvm *kvm = vcpu->kvm;
+       bool already_matched;
+
+       lockdep_assert_held(&kvm->arch.tsc_write_lock);
+
+       already_matched =
+              (vcpu->arch.this_tsc_generation == kvm->arch.cur_tsc_generation);
+
+       /*
+        * We track the most recent recorded KHZ, write and time to
+        * allow the matching interval to be extended at each write.
+        */
+       kvm->arch.last_tsc_nsec = ns;
+       kvm->arch.last_tsc_write = tsc;
+       kvm->arch.last_tsc_khz = vcpu->arch.virtual_tsc_khz;
+
+       vcpu->arch.last_guest_tsc = tsc;
+
+       /* Keep track of which generation this VCPU has synchronized to */
+       vcpu->arch.this_tsc_generation = kvm->arch.cur_tsc_generation;
+       vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec;
+       vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write;
+
+       kvm_vcpu_write_tsc_offset(vcpu, offset);
+
+       if (!matched) {
+               /*
+                * We split periods of matched TSC writes into generations.
+                * For each generation, we track the original measured
+                * nanosecond time, offset, and write, so if TSCs are in
+                * sync, we can match exact offset, and if not, we can match
+                * exact software computation in compute_guest_tsc()
+                *
+                * These values are tracked in kvm->arch.cur_xxx variables.
+                */
+               kvm->arch.cur_tsc_generation++;
+               kvm->arch.cur_tsc_nsec = ns;
+               kvm->arch.cur_tsc_write = tsc;
+               kvm->arch.cur_tsc_offset = offset;
+
+               spin_lock(&kvm->arch.pvclock_gtod_sync_lock);
+               kvm->arch.nr_vcpus_matched_tsc = 0;
+       } else if (!already_matched) {
+               spin_lock(&kvm->arch.pvclock_gtod_sync_lock);
+               kvm->arch.nr_vcpus_matched_tsc++;
+       }
+
+       kvm_track_tsc_matching(vcpu);
+       spin_unlock(&kvm->arch.pvclock_gtod_sync_lock);
+}
+
 static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data)
 {
        struct kvm *kvm = vcpu->kvm;
        u64 offset, ns, elapsed;
        unsigned long flags;
-       bool matched;
-       bool already_matched;
+       bool matched = false;
        bool synchronizing = false;
 
        raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
@@ -2495,50 +2553,9 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, 
u64 data)
                        offset = kvm_compute_l1_tsc_offset(vcpu, data);
                }
                matched = true;
-               already_matched = (vcpu->arch.this_tsc_generation == 
kvm->arch.cur_tsc_generation);
-       } else {
-               /*
-                * We split periods of matched TSC writes into generations.
-                * For each generation, we track the original measured
-                * nanosecond time, offset, and write, so if TSCs are in
-                * sync, we can match exact offset, and if not, we can match
-                * exact software computation in compute_guest_tsc()
-                *
-                * These values are tracked in kvm->arch.cur_xxx variables.
-                */
-               kvm->arch.cur_tsc_generation++;
-               kvm->arch.cur_tsc_nsec = ns;
-               kvm->arch.cur_tsc_write = data;
-               kvm->arch.cur_tsc_offset = offset;
-               matched = false;
        }
 
-       /*
-        * We also track th most recent recorded KHZ, write and time to
-        * allow the matching interval to be extended at each write.
-        */
-       kvm->arch.last_tsc_nsec = ns;
-       kvm->arch.last_tsc_write = data;
-       kvm->arch.last_tsc_khz = vcpu->arch.virtual_tsc_khz;
-
-       vcpu->arch.last_guest_tsc = data;
-
-       /* Keep track of which generation this VCPU has synchronized to */
-       vcpu->arch.this_tsc_generation = kvm->arch.cur_tsc_generation;
-       vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec;
-       vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write;
-
-       kvm_vcpu_write_tsc_offset(vcpu, offset);
-
-       spin_lock_irqsave(&kvm->arch.pvclock_gtod_sync_lock, flags);
-       if (!matched) {
-               kvm->arch.nr_vcpus_matched_tsc = 0;
-       } else if (!already_matched) {
-               kvm->arch.nr_vcpus_matched_tsc++;
-       }
-
-       kvm_track_tsc_matching(vcpu);
-       spin_unlock_irqrestore(&kvm->arch.pvclock_gtod_sync_lock, flags);
+       __kvm_synchronize_tsc(vcpu, offset, data, ns, matched);
        raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
 }
 
-- 
2.32.0.605.g8dce9f2422-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to