diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2015-01-20 12:54:52 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-01-20 14:38:39 -0500 |
commit | 54750f2cf042c42b4223d67b1bd20138464bde0e (patch) | |
tree | e7914883c6452ee68f2b8f7e583db12d2afbe955 /arch/x86/kvm | |
parent | 69b0049a89ad418cd68aa59e7f1e6619a04a4a6f (diff) |
KVM: x86: workaround SuSE's 2.6.16 pvclock vs masterclock issue
SuSE's 2.6.16 kernel fails to boot if the delta between tsc_timestamp
and rdtsc is larger than a given threshold:
* If we get more than the below threshold into the future, we rerequest
* the real time from the host again which has only little offset then
* that we need to adjust using the TSC.
*
* For now that threshold is 1/5th of a jiffie. That should be good
* enough accuracy for completely broken systems, but also give us swing
* to not call out to the host all the time.
*/
#define PVCLOCK_DELTA_MAX ((1000000000ULL / HZ) / 5)
Disable masterclock support (which increases said delta) in case the
boot vcpu does not use MSR_KVM_SYSTEM_TIME_NEW.
Upstreams kernels which support pvclock vsyscalls (and therefore make
use of PVCLOCK_STABLE_BIT) use MSR_KVM_SYSTEM_TIME_NEW.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/x86.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index dcb996bfafa4..917672f8034a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -1542,7 +1542,8 @@ static void pvclock_update_vm_gtod_copy(struct kvm *kvm) | |||
1542 | &ka->master_cycle_now); | 1542 | &ka->master_cycle_now); |
1543 | 1543 | ||
1544 | ka->use_master_clock = host_tsc_clocksource && vcpus_matched | 1544 | ka->use_master_clock = host_tsc_clocksource && vcpus_matched |
1545 | && !backwards_tsc_observed; | 1545 | && !backwards_tsc_observed |
1546 | && !ka->boot_vcpu_runs_old_kvmclock; | ||
1546 | 1547 | ||
1547 | if (ka->use_master_clock) | 1548 | if (ka->use_master_clock) |
1548 | atomic_set(&kvm_guest_has_master_clock, 1); | 1549 | atomic_set(&kvm_guest_has_master_clock, 1); |
@@ -2174,8 +2175,20 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |||
2174 | case MSR_KVM_SYSTEM_TIME_NEW: | 2175 | case MSR_KVM_SYSTEM_TIME_NEW: |
2175 | case MSR_KVM_SYSTEM_TIME: { | 2176 | case MSR_KVM_SYSTEM_TIME: { |
2176 | u64 gpa_offset; | 2177 | u64 gpa_offset; |
2178 | struct kvm_arch *ka = &vcpu->kvm->arch; | ||
2179 | |||
2177 | kvmclock_reset(vcpu); | 2180 | kvmclock_reset(vcpu); |
2178 | 2181 | ||
2182 | if (vcpu->vcpu_id == 0 && !msr_info->host_initiated) { | ||
2183 | bool tmp = (msr == MSR_KVM_SYSTEM_TIME); | ||
2184 | |||
2185 | if (ka->boot_vcpu_runs_old_kvmclock != tmp) | ||
2186 | set_bit(KVM_REQ_MASTERCLOCK_UPDATE, | ||
2187 | &vcpu->requests); | ||
2188 | |||
2189 | ka->boot_vcpu_runs_old_kvmclock = tmp; | ||
2190 | } | ||
2191 | |||
2179 | vcpu->arch.time = data; | 2192 | vcpu->arch.time = data; |
2180 | kvm_make_request(KVM_REQ_GLOBAL_CLOCK_UPDATE, vcpu); | 2193 | kvm_make_request(KVM_REQ_GLOBAL_CLOCK_UPDATE, vcpu); |
2181 | 2194 | ||