aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
authorZachary Amsden <zamsden@gmail.com>2012-02-03 12:43:50 -0500
committerAvi Kivity <avi@redhat.com>2012-03-08 07:09:35 -0500
commitcc578287e3224d0da196cc1d226bdae6b068faa7 (patch)
treec4352ebbd4d35de296622a8be99d76a1a6a48793 /arch/x86/kvm/svm.c
parenta59cb29e4d81e025192550c2703f305637f016f6 (diff)
KVM: Infrastructure for software and hardware based TSC rate scaling
This requires some restructuring; rather than use 'virtual_tsc_khz' to indicate whether hardware rate scaling is in effect, we consider each VCPU to always have a virtual TSC rate. Instead, there is new logic above the vendor-specific hardware scaling that decides whether it is even necessary to use and updates all rate variables used by common code. This means we can simply query the virtual rate at any point, which is needed for software rate scaling. There is also now a threshold added to the TSC rate scaling; minor differences and variations of measured TSC rate can accidentally provoke rate scaling to be used when it is not needed. Instead, we have a tolerance variable called tsc_tolerance_ppm, which is the maximum variation from user requested rate at which scaling will be used. The default is 250ppm, which is the half the threshold for NTP adjustment, allowing for some hardware variation. In the event that hardware rate scaling is not available, we can kludge a bit by forcing TSC catchup to turn on when a faster than hardware speed has been requested, but there is nothing available yet for the reverse case; this requires a trap and emulate software implementation for RDTSC, which is still forthcoming. [avi: fix 64-bit division on i386] Signed-off-by: Zachary Amsden <zamsden@gmail.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r--arch/x86/kvm/svm.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 7bbd17cc348..e12026e5244 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -964,20 +964,25 @@ static u64 svm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
964 return _tsc; 964 return _tsc;
965} 965}
966 966
967static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz) 967static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
968{ 968{
969 struct vcpu_svm *svm = to_svm(vcpu); 969 struct vcpu_svm *svm = to_svm(vcpu);
970 u64 ratio; 970 u64 ratio;
971 u64 khz; 971 u64 khz;
972 972
973 /* TSC scaling supported? */ 973 /* Guest TSC same frequency as host TSC? */
974 if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR)) 974 if (!scale) {
975 svm->tsc_ratio = TSC_RATIO_DEFAULT;
975 return; 976 return;
977 }
976 978
977 /* TSC-Scaling disabled or guest TSC same frequency as host TSC? */ 979 /* TSC scaling supported? */
978 if (user_tsc_khz == 0) { 980 if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
979 vcpu->arch.virtual_tsc_khz = 0; 981 if (user_tsc_khz > tsc_khz) {
980 svm->tsc_ratio = TSC_RATIO_DEFAULT; 982 vcpu->arch.tsc_catchup = 1;
983 vcpu->arch.tsc_always_catchup = 1;
984 } else
985 WARN(1, "user requested TSC rate below hardware speed\n");
981 return; 986 return;
982 } 987 }
983 988
@@ -992,7 +997,6 @@ static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
992 user_tsc_khz); 997 user_tsc_khz);
993 return; 998 return;
994 } 999 }
995 vcpu->arch.virtual_tsc_khz = user_tsc_khz;
996 svm->tsc_ratio = ratio; 1000 svm->tsc_ratio = ratio;
997} 1001}
998 1002