aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/msr-index.h1
-rw-r--r--arch/x86/kvm/svm.c54
2 files changed, 54 insertions, 1 deletions
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 3cce71413d0b..485b4f1f079b 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -118,6 +118,7 @@
118 complete list. */ 118 complete list. */
119 119
120#define MSR_AMD64_PATCH_LEVEL 0x0000008b 120#define MSR_AMD64_PATCH_LEVEL 0x0000008b
121#define MSR_AMD64_TSC_RATIO 0xc0000104
121#define MSR_AMD64_NB_CFG 0xc001001f 122#define MSR_AMD64_NB_CFG 0xc001001f
122#define MSR_AMD64_PATCH_LOADER 0xc0010020 123#define MSR_AMD64_PATCH_LOADER 0xc0010020
123#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140 124#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 779b09194f03..830150099958 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -63,6 +63,8 @@ MODULE_LICENSE("GPL");
63 63
64#define DEBUGCTL_RESERVED_BITS (~(0x3fULL)) 64#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
65 65
66#define TSC_RATIO_RSVD 0xffffff0000000000ULL
67
66static bool erratum_383_found __read_mostly; 68static bool erratum_383_found __read_mostly;
67 69
68static const u32 host_save_user_msrs[] = { 70static const u32 host_save_user_msrs[] = {
@@ -136,8 +138,13 @@ struct vcpu_svm {
136 unsigned int3_injected; 138 unsigned int3_injected;
137 unsigned long int3_rip; 139 unsigned long int3_rip;
138 u32 apf_reason; 140 u32 apf_reason;
141
142 u64 tsc_ratio;
139}; 143};
140 144
145static DEFINE_PER_CPU(u64, current_tsc_ratio);
146#define TSC_RATIO_DEFAULT 0x0100000000ULL
147
141#define MSR_INVALID 0xffffffffU 148#define MSR_INVALID 0xffffffffU
142 149
143static struct svm_direct_access_msrs { 150static struct svm_direct_access_msrs {
@@ -560,6 +567,10 @@ static int has_svm(void)
560 567
561static void svm_hardware_disable(void *garbage) 568static void svm_hardware_disable(void *garbage)
562{ 569{
570 /* Make sure we clean up behind us */
571 if (static_cpu_has(X86_FEATURE_TSCRATEMSR))
572 wrmsrl(MSR_AMD64_TSC_RATIO, TSC_RATIO_DEFAULT);
573
563 cpu_svm_disable(); 574 cpu_svm_disable();
564} 575}
565 576
@@ -601,6 +612,11 @@ static int svm_hardware_enable(void *garbage)
601 612
602 wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT); 613 wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT);
603 614
615 if (static_cpu_has(X86_FEATURE_TSCRATEMSR)) {
616 wrmsrl(MSR_AMD64_TSC_RATIO, TSC_RATIO_DEFAULT);
617 __get_cpu_var(current_tsc_ratio) = TSC_RATIO_DEFAULT;
618 }
619
604 svm_init_erratum_383(); 620 svm_init_erratum_383();
605 621
606 return 0; 622 return 0;
@@ -843,6 +859,32 @@ static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
843 seg->base = 0; 859 seg->base = 0;
844} 860}
845 861
862static u64 __scale_tsc(u64 ratio, u64 tsc)
863{
864 u64 mult, frac, _tsc;
865
866 mult = ratio >> 32;
867 frac = ratio & ((1ULL << 32) - 1);
868
869 _tsc = tsc;
870 _tsc *= mult;
871 _tsc += (tsc >> 32) * frac;
872 _tsc += ((tsc & ((1ULL << 32) - 1)) * frac) >> 32;
873
874 return _tsc;
875}
876
877static u64 svm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
878{
879 struct vcpu_svm *svm = to_svm(vcpu);
880 u64 _tsc = tsc;
881
882 if (svm->tsc_ratio != TSC_RATIO_DEFAULT)
883 _tsc = __scale_tsc(svm->tsc_ratio, tsc);
884
885 return _tsc;
886}
887
846static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) 888static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
847{ 889{
848 struct vcpu_svm *svm = to_svm(vcpu); 890 struct vcpu_svm *svm = to_svm(vcpu);
@@ -1037,6 +1079,8 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
1037 goto out; 1079 goto out;
1038 } 1080 }
1039 1081
1082 svm->tsc_ratio = TSC_RATIO_DEFAULT;
1083
1040 err = kvm_vcpu_init(&svm->vcpu, kvm, id); 1084 err = kvm_vcpu_init(&svm->vcpu, kvm, id);
1041 if (err) 1085 if (err)
1042 goto free_svm; 1086 goto free_svm;
@@ -1130,6 +1174,12 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
1130 1174
1131 for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++) 1175 for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
1132 rdmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]); 1176 rdmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
1177
1178 if (static_cpu_has(X86_FEATURE_TSCRATEMSR) &&
1179 svm->tsc_ratio != __get_cpu_var(current_tsc_ratio)) {
1180 __get_cpu_var(current_tsc_ratio) = svm->tsc_ratio;
1181 wrmsrl(MSR_AMD64_TSC_RATIO, svm->tsc_ratio);
1182 }
1133} 1183}
1134 1184
1135static void svm_vcpu_put(struct kvm_vcpu *vcpu) 1185static void svm_vcpu_put(struct kvm_vcpu *vcpu)
@@ -2784,7 +2834,9 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
2784 case MSR_IA32_TSC: { 2834 case MSR_IA32_TSC: {
2785 struct vmcb *vmcb = get_host_vmcb(svm); 2835 struct vmcb *vmcb = get_host_vmcb(svm);
2786 2836
2787 *data = vmcb->control.tsc_offset + native_read_tsc(); 2837 *data = vmcb->control.tsc_offset +
2838 svm_scale_tsc(vcpu, native_read_tsc());
2839
2788 break; 2840 break;
2789 } 2841 }
2790 case MSR_STAR: 2842 case MSR_STAR: