aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-03-25 04:44:49 -0400
committerAvi Kivity <avi@redhat.com>2011-05-11 07:57:05 -0400
commit4051b18801f5b47bb0369feefdc80e57819d0ddf (patch)
treeac0b50efc768bbf7bfe42fcd70e9d97bf46185b9
parent8f6055cbaf68cbd9ff2692a2cfa691b43629ccd4 (diff)
KVM: X86: Implement call-back to propagate virtual_tsc_khz
This patch implements a call-back into the architecture code to allow the propagation of changes to the virtual tsc_khz of the vcpu. On SVM it updates the tsc_ratio variable, on VMX it does nothing. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/kvm/svm.c33
-rw-r--r--arch/x86/kvm/vmx.c11
3 files changed, 45 insertions, 0 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index e3aaa02ca032..f3a7116f802f 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -606,6 +606,7 @@ struct kvm_x86_ops {
606 606
607 bool (*has_wbinvd_exit)(void); 607 bool (*has_wbinvd_exit)(void);
608 608
609 void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz);
609 void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset); 610 void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
610 611
611 void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2); 612 void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 830150099958..a39fde4f5fe8 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -885,6 +885,38 @@ static u64 svm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
885 return _tsc; 885 return _tsc;
886} 886}
887 887
888static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
889{
890 struct vcpu_svm *svm = to_svm(vcpu);
891 u64 ratio;
892 u64 khz;
893
894 /* TSC scaling supported? */
895 if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR))
896 return;
897
898 /* TSC-Scaling disabled or guest TSC same frequency as host TSC? */
899 if (user_tsc_khz == 0) {
900 vcpu->arch.virtual_tsc_khz = 0;
901 svm->tsc_ratio = TSC_RATIO_DEFAULT;
902 return;
903 }
904
905 khz = user_tsc_khz;
906
907 /* TSC scaling required - calculate ratio */
908 ratio = khz << 32;
909 do_div(ratio, tsc_khz);
910
911 if (ratio == 0 || ratio & TSC_RATIO_RSVD) {
912 WARN_ONCE(1, "Invalid TSC ratio - virtual-tsc-khz=%u\n",
913 user_tsc_khz);
914 return;
915 }
916 vcpu->arch.virtual_tsc_khz = user_tsc_khz;
917 svm->tsc_ratio = ratio;
918}
919
888static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) 920static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
889{ 921{
890 struct vcpu_svm *svm = to_svm(vcpu); 922 struct vcpu_svm *svm = to_svm(vcpu);
@@ -4159,6 +4191,7 @@ static struct kvm_x86_ops svm_x86_ops = {
4159 4191
4160 .has_wbinvd_exit = svm_has_wbinvd_exit, 4192 .has_wbinvd_exit = svm_has_wbinvd_exit,
4161 4193
4194 .set_tsc_khz = svm_set_tsc_khz,
4162 .write_tsc_offset = svm_write_tsc_offset, 4195 .write_tsc_offset = svm_write_tsc_offset,
4163 .adjust_tsc_offset = svm_adjust_tsc_offset, 4196 .adjust_tsc_offset = svm_adjust_tsc_offset,
4164 4197
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 3dfefe3bcd05..e19c7a5473d5 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1161,6 +1161,16 @@ static u64 guest_read_tsc(void)
1161} 1161}
1162 1162
1163/* 1163/*
1164 * Empty call-back. Needs to be implemented when VMX enables the SET_TSC_KHZ
1165 * ioctl. In this case the call-back should update internal vmx state to make
1166 * the changes effective.
1167 */
1168static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
1169{
1170 /* Nothing to do here */
1171}
1172
1173/*
1164 * writes 'offset' into guest's timestamp counter offset register 1174 * writes 'offset' into guest's timestamp counter offset register
1165 */ 1175 */
1166static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) 1176static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
@@ -4497,6 +4507,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
4497 4507
4498 .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit, 4508 .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,
4499 4509
4510 .set_tsc_khz = vmx_set_tsc_khz,
4500 .write_tsc_offset = vmx_write_tsc_offset, 4511 .write_tsc_offset = vmx_write_tsc_offset,
4501 .adjust_tsc_offset = vmx_adjust_tsc_offset, 4512 .adjust_tsc_offset = vmx_adjust_tsc_offset,
4502 4513