aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorZachary Amsden <zamsden@redhat.com>2009-09-29 17:38:35 -0400
committerAvi Kivity <avi@redhat.com>2009-12-03 02:32:12 -0500
commit0cca790753bf0cab4b070801a46df8e1297c17f6 (patch)
tree9b2887a5f00872248875ecd001d03e36e425f97a /arch/x86/kvm/x86.c
parentb820cc0ca20fdcf8014d8e57421cf29095e39392 (diff)
KVM: Kill the confusing tsc_ref_khz and ref_freq variables
They are globals, not clearly protected by any ordering or locking, and vulnerable to various startup races. Instead, for variable TSC machines, register the cpufreq notifier and get the TSC frequency directly from the cpufreq machinery. Not only is it always right, it is also perfectly accurate, as no error prone measurement is required. On such machines, when a new CPU online is brought online, it isn't clear what frequency it will start with, and it may not correspond to the reference, thus in hardware_enable we clear the cpu_tsc_khz variable to zero and make sure it is set before running on a VCPU. Signed-off-by: Zachary Amsden <zamsden@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6a31dfb8849c..6f758567831a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1326,6 +1326,8 @@ out:
1326void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) 1326void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
1327{ 1327{
1328 kvm_x86_ops->vcpu_load(vcpu, cpu); 1328 kvm_x86_ops->vcpu_load(vcpu, cpu);
1329 if (unlikely(per_cpu(cpu_tsc_khz, cpu) == 0))
1330 per_cpu(cpu_tsc_khz, cpu) = cpufreq_quick_get(cpu);
1329 kvm_request_guest_time_update(vcpu); 1331 kvm_request_guest_time_update(vcpu);
1330} 1332}
1331 1333
@@ -3063,9 +3065,6 @@ static void bounce_off(void *info)
3063 /* nothing */ 3065 /* nothing */
3064} 3066}
3065 3067
3066static unsigned int ref_freq;
3067static unsigned long tsc_khz_ref;
3068
3069static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val, 3068static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
3070 void *data) 3069 void *data)
3071{ 3070{
@@ -3074,14 +3073,11 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
3074 struct kvm_vcpu *vcpu; 3073 struct kvm_vcpu *vcpu;
3075 int i, send_ipi = 0; 3074 int i, send_ipi = 0;
3076 3075
3077 if (!ref_freq)
3078 ref_freq = freq->old;
3079
3080 if (val == CPUFREQ_PRECHANGE && freq->old > freq->new) 3076 if (val == CPUFREQ_PRECHANGE && freq->old > freq->new)
3081 return 0; 3077 return 0;
3082 if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new) 3078 if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new)
3083 return 0; 3079 return 0;
3084 per_cpu(cpu_tsc_khz, freq->cpu) = cpufreq_scale(tsc_khz_ref, ref_freq, freq->new); 3080 per_cpu(cpu_tsc_khz, freq->cpu) = freq->new;
3085 3081
3086 spin_lock(&kvm_lock); 3082 spin_lock(&kvm_lock);
3087 list_for_each_entry(kvm, &vm_list, vm_list) { 3083 list_for_each_entry(kvm, &vm_list, vm_list) {
@@ -3122,12 +3118,14 @@ static void kvm_timer_init(void)
3122{ 3118{
3123 int cpu; 3119 int cpu;
3124 3120
3125 for_each_possible_cpu(cpu)
3126 per_cpu(cpu_tsc_khz, cpu) = tsc_khz;
3127 if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) { 3121 if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
3128 tsc_khz_ref = tsc_khz;
3129 cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block, 3122 cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,
3130 CPUFREQ_TRANSITION_NOTIFIER); 3123 CPUFREQ_TRANSITION_NOTIFIER);
3124 for_each_online_cpu(cpu)
3125 per_cpu(cpu_tsc_khz, cpu) = cpufreq_get(cpu);
3126 } else {
3127 for_each_possible_cpu(cpu)
3128 per_cpu(cpu_tsc_khz, cpu) = tsc_khz;
3131 } 3129 }
3132} 3130}
3133 3131
@@ -4700,6 +4698,14 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
4700 4698
4701int kvm_arch_hardware_enable(void *garbage) 4699int kvm_arch_hardware_enable(void *garbage)
4702{ 4700{
4701 /*
4702 * Since this may be called from a hotplug notifcation,
4703 * we can't get the CPU frequency directly.
4704 */
4705 if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
4706 int cpu = raw_smp_processor_id();
4707 per_cpu(cpu_tsc_khz, cpu) = 0;
4708 }
4703 return kvm_x86_ops->hardware_enable(garbage); 4709 return kvm_x86_ops->hardware_enable(garbage);
4704} 4710}
4705 4711