From: David Woodhouse <[email protected]> Move get/put_cpu inside the use_master_clock branch since they are only needed there (for RDTSC and get_cpu_tsc_khz() to be on the same CPU).
Simplify the use_master_clock condition: the open-coded CONSTANT_TSC || cpu_tsc_khz check is unnecessary since use_master_clock can only be true when the TSC is usable. Wrap the entire use_master_clock block in #ifdef CONFIG_X86_64, since use_master_clock is never true on 32-bit (host_tsc_clocksource is only set under CONFIG_X86_64). When the clock read fails (e.g. clocksource transitioning away from TSC), fall back to the non-master-clock path (get_kvmclock_base_ns) rather than proceeding with uninitialised data or spinning in the seqcount loop. Signed-off-by: David Woodhouse <[email protected]> --- arch/x86/kvm/x86.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fce898811fe7..6983a7494fcd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3209,21 +3209,30 @@ static void get_kvmclock(struct kvm *kvm, struct kvm_clock_data *data) do { seq = read_seqcount_begin(&ka->pvclock_sc); - /* both __this_cpu_read() and rdtsc() should be on the same cpu */ - get_cpu(); - data->flags = 0; - if (ka->use_master_clock && - (static_cpu_has(X86_FEATURE_CONSTANT_TSC) || __this_cpu_read(cpu_tsc_khz))) { #ifdef CONFIG_X86_64 + if (ka->use_master_clock) { struct timespec64 ts; + /* + * The RDTSC and get_cpu_tsc_khz() must happen on + * the same CPU. + */ + get_cpu(); + if (kvm_get_walltime_and_clockread(&ts, &data->host_tsc)) { data->realtime = ts.tv_nsec + NSEC_PER_SEC * ts.tv_sec; data->flags |= KVM_CLOCK_REALTIME | KVM_CLOCK_HOST_TSC; - } else -#endif - data->host_tsc = rdtsc(); + } else { + /* + * Clock read failed (e.g. clocksource is + * transitioning away from TSC). Fall back to + * the non-master-clock path rather than + * spinning. + */ + put_cpu(); + goto fallback; + } data->flags |= KVM_CLOCK_TSC_STABLE; hv_clock.tsc_timestamp = ka->master_cycle_now; @@ -3232,11 +3241,14 @@ static void get_kvmclock(struct kvm *kvm, struct kvm_clock_data *data) &hv_clock.tsc_shift, &hv_clock.tsc_to_system_mul); data->clock = __pvclock_read_cycles(&hv_clock, data->host_tsc); - } else { + + put_cpu(); + } else +#endif + { +fallback: data->clock = get_kvmclock_base_ns() + ka->kvmclock_offset; } - - put_cpu(); } while (read_seqcount_retry(&ka->pvclock_sc, seq)); } -- 2.54.0

