diff options
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 48 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 40 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | include/linux/math64.h | 51 |
5 files changed, 97 insertions, 45 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index f3354bd92364..52d1419968eb 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -1238,6 +1238,8 @@ void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm, | |||
1238 | void kvm_define_shared_msr(unsigned index, u32 msr); | 1238 | void kvm_define_shared_msr(unsigned index, u32 msr); |
1239 | int kvm_set_shared_msr(unsigned index, u64 val, u64 mask); | 1239 | int kvm_set_shared_msr(unsigned index, u64 val, u64 mask); |
1240 | 1240 | ||
1241 | u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc); | ||
1242 | |||
1241 | unsigned long kvm_get_linear_rip(struct kvm_vcpu *vcpu); | 1243 | unsigned long kvm_get_linear_rip(struct kvm_vcpu *vcpu); |
1242 | bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip); | 1244 | bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip); |
1243 | 1245 | ||
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 9c92e6f429d0..65f4f1947a62 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -212,7 +212,6 @@ static int nested_svm_intercept(struct vcpu_svm *svm); | |||
212 | static int nested_svm_vmexit(struct vcpu_svm *svm); | 212 | static int nested_svm_vmexit(struct vcpu_svm *svm); |
213 | static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, | 213 | static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, |
214 | bool has_error_code, u32 error_code); | 214 | bool has_error_code, u32 error_code); |
215 | static u64 __scale_tsc(u64 ratio, u64 tsc); | ||
216 | 215 | ||
217 | enum { | 216 | enum { |
218 | VMCB_INTERCEPTS, /* Intercept vectors, TSC offset, | 217 | VMCB_INTERCEPTS, /* Intercept vectors, TSC offset, |
@@ -892,21 +891,7 @@ static __init int svm_hardware_setup(void) | |||
892 | kvm_enable_efer_bits(EFER_FFXSR); | 891 | kvm_enable_efer_bits(EFER_FFXSR); |
893 | 892 | ||
894 | if (boot_cpu_has(X86_FEATURE_TSCRATEMSR)) { | 893 | if (boot_cpu_has(X86_FEATURE_TSCRATEMSR)) { |
895 | u64 max; | ||
896 | |||
897 | kvm_has_tsc_control = true; | 894 | kvm_has_tsc_control = true; |
898 | |||
899 | /* | ||
900 | * Make sure the user can only configure tsc_khz values that | ||
901 | * fit into a signed integer. | ||
902 | * A min value is not calculated needed because it will always | ||
903 | * be 1 on all machines and a value of 0 is used to disable | ||
904 | * tsc-scaling for the vcpu. | ||
905 | */ | ||
906 | max = min(0x7fffffffULL, __scale_tsc(tsc_khz, TSC_RATIO_MAX)); | ||
907 | |||
908 | kvm_max_guest_tsc_khz = max; | ||
909 | |||
910 | kvm_max_tsc_scaling_ratio = TSC_RATIO_MAX; | 895 | kvm_max_tsc_scaling_ratio = TSC_RATIO_MAX; |
911 | kvm_tsc_scaling_ratio_frac_bits = 32; | 896 | kvm_tsc_scaling_ratio_frac_bits = 32; |
912 | } | 897 | } |
@@ -972,31 +957,6 @@ static void init_sys_seg(struct vmcb_seg *seg, uint32_t type) | |||
972 | seg->base = 0; | 957 | seg->base = 0; |
973 | } | 958 | } |
974 | 959 | ||
975 | static u64 __scale_tsc(u64 ratio, u64 tsc) | ||
976 | { | ||
977 | u64 mult, frac, _tsc; | ||
978 | |||
979 | mult = ratio >> 32; | ||
980 | frac = ratio & ((1ULL << 32) - 1); | ||
981 | |||
982 | _tsc = tsc; | ||
983 | _tsc *= mult; | ||
984 | _tsc += (tsc >> 32) * frac; | ||
985 | _tsc += ((tsc & ((1ULL << 32) - 1)) * frac) >> 32; | ||
986 | |||
987 | return _tsc; | ||
988 | } | ||
989 | |||
990 | static u64 svm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc) | ||
991 | { | ||
992 | u64 _tsc = tsc; | ||
993 | |||
994 | if (vcpu->arch.tsc_scaling_ratio != TSC_RATIO_DEFAULT) | ||
995 | _tsc = __scale_tsc(vcpu->arch.tsc_scaling_ratio, tsc); | ||
996 | |||
997 | return _tsc; | ||
998 | } | ||
999 | |||
1000 | static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale) | 960 | static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale) |
1001 | { | 961 | { |
1002 | u64 ratio; | 962 | u64 ratio; |
@@ -1065,7 +1025,7 @@ static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool ho | |||
1065 | if (host) { | 1025 | if (host) { |
1066 | if (vcpu->arch.tsc_scaling_ratio != TSC_RATIO_DEFAULT) | 1026 | if (vcpu->arch.tsc_scaling_ratio != TSC_RATIO_DEFAULT) |
1067 | WARN_ON(adjustment < 0); | 1027 | WARN_ON(adjustment < 0); |
1068 | adjustment = svm_scale_tsc(vcpu, (u64)adjustment); | 1028 | adjustment = kvm_scale_tsc(vcpu, (u64)adjustment); |
1069 | } | 1029 | } |
1070 | 1030 | ||
1071 | svm->vmcb->control.tsc_offset += adjustment; | 1031 | svm->vmcb->control.tsc_offset += adjustment; |
@@ -1083,7 +1043,7 @@ static u64 svm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc) | |||
1083 | { | 1043 | { |
1084 | u64 tsc; | 1044 | u64 tsc; |
1085 | 1045 | ||
1086 | tsc = svm_scale_tsc(vcpu, rdtsc()); | 1046 | tsc = kvm_scale_tsc(vcpu, rdtsc()); |
1087 | 1047 | ||
1088 | return target_tsc - tsc; | 1048 | return target_tsc - tsc; |
1089 | } | 1049 | } |
@@ -3075,7 +3035,7 @@ static u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc) | |||
3075 | { | 3035 | { |
3076 | struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu)); | 3036 | struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu)); |
3077 | return vmcb->control.tsc_offset + | 3037 | return vmcb->control.tsc_offset + |
3078 | svm_scale_tsc(vcpu, host_tsc); | 3038 | kvm_scale_tsc(vcpu, host_tsc); |
3079 | } | 3039 | } |
3080 | 3040 | ||
3081 | static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | 3041 | static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) |
@@ -3085,7 +3045,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |||
3085 | switch (msr_info->index) { | 3045 | switch (msr_info->index) { |
3086 | case MSR_IA32_TSC: { | 3046 | case MSR_IA32_TSC: { |
3087 | msr_info->data = svm->vmcb->control.tsc_offset + | 3047 | msr_info->data = svm->vmcb->control.tsc_offset + |
3088 | svm_scale_tsc(vcpu, rdtsc()); | 3048 | kvm_scale_tsc(vcpu, rdtsc()); |
3089 | 3049 | ||
3090 | break; | 3050 | break; |
3091 | } | 3051 | } |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ef5b9d66cd71..1473e64cb744 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -1329,6 +1329,33 @@ static void update_ia32_tsc_adjust_msr(struct kvm_vcpu *vcpu, s64 offset) | |||
1329 | vcpu->arch.ia32_tsc_adjust_msr += offset - curr_offset; | 1329 | vcpu->arch.ia32_tsc_adjust_msr += offset - curr_offset; |
1330 | } | 1330 | } |
1331 | 1331 | ||
1332 | /* | ||
1333 | * Multiply tsc by a fixed point number represented by ratio. | ||
1334 | * | ||
1335 | * The most significant 64-N bits (mult) of ratio represent the | ||
1336 | * integral part of the fixed point number; the remaining N bits | ||
1337 | * (frac) represent the fractional part, ie. ratio represents a fixed | ||
1338 | * point number (mult + frac * 2^(-N)). | ||
1339 | * | ||
1340 | * N equals to kvm_tsc_scaling_ratio_frac_bits. | ||
1341 | */ | ||
1342 | static inline u64 __scale_tsc(u64 ratio, u64 tsc) | ||
1343 | { | ||
1344 | return mul_u64_u64_shr(tsc, ratio, kvm_tsc_scaling_ratio_frac_bits); | ||
1345 | } | ||
1346 | |||
1347 | u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc) | ||
1348 | { | ||
1349 | u64 _tsc = tsc; | ||
1350 | u64 ratio = vcpu->arch.tsc_scaling_ratio; | ||
1351 | |||
1352 | if (ratio != kvm_default_tsc_scaling_ratio) | ||
1353 | _tsc = __scale_tsc(ratio, tsc); | ||
1354 | |||
1355 | return _tsc; | ||
1356 | } | ||
1357 | EXPORT_SYMBOL_GPL(kvm_scale_tsc); | ||
1358 | |||
1332 | void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) | 1359 | void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) |
1333 | { | 1360 | { |
1334 | struct kvm *kvm = vcpu->kvm; | 1361 | struct kvm *kvm = vcpu->kvm; |
@@ -7371,8 +7398,19 @@ int kvm_arch_hardware_setup(void) | |||
7371 | if (r != 0) | 7398 | if (r != 0) |
7372 | return r; | 7399 | return r; |
7373 | 7400 | ||
7374 | if (kvm_has_tsc_control) | 7401 | if (kvm_has_tsc_control) { |
7402 | /* | ||
7403 | * Make sure the user can only configure tsc_khz values that | ||
7404 | * fit into a signed integer. | ||
7405 | * A min value is not calculated needed because it will always | ||
7406 | * be 1 on all machines. | ||
7407 | */ | ||
7408 | u64 max = min(0x7fffffffULL, | ||
7409 | __scale_tsc(kvm_max_tsc_scaling_ratio, tsc_khz)); | ||
7410 | kvm_max_guest_tsc_khz = max; | ||
7411 | |||
7375 | kvm_default_tsc_scaling_ratio = 1ULL << kvm_tsc_scaling_ratio_frac_bits; | 7412 | kvm_default_tsc_scaling_ratio = 1ULL << kvm_tsc_scaling_ratio_frac_bits; |
7413 | } | ||
7376 | 7414 | ||
7377 | kvm_init_msr_list(); | 7415 | kvm_init_msr_list(); |
7378 | return 0; | 7416 | return 0; |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 242a6d2b53ff..5706a2108f0a 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -1183,4 +1183,5 @@ void kvm_arch_irq_bypass_start(struct irq_bypass_consumer *); | |||
1183 | int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq, | 1183 | int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq, |
1184 | uint32_t guest_irq, bool set); | 1184 | uint32_t guest_irq, bool set); |
1185 | #endif /* CONFIG_HAVE_KVM_IRQ_BYPASS */ | 1185 | #endif /* CONFIG_HAVE_KVM_IRQ_BYPASS */ |
1186 | |||
1186 | #endif | 1187 | #endif |
diff --git a/include/linux/math64.h b/include/linux/math64.h index c45c089bfdac..44282ec7b682 100644 --- a/include/linux/math64.h +++ b/include/linux/math64.h | |||
@@ -142,6 +142,13 @@ static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift) | |||
142 | } | 142 | } |
143 | #endif /* mul_u64_u32_shr */ | 143 | #endif /* mul_u64_u32_shr */ |
144 | 144 | ||
145 | #ifndef mul_u64_u64_shr | ||
146 | static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift) | ||
147 | { | ||
148 | return (u64)(((unsigned __int128)a * mul) >> shift); | ||
149 | } | ||
150 | #endif /* mul_u64_u64_shr */ | ||
151 | |||
145 | #else | 152 | #else |
146 | 153 | ||
147 | #ifndef mul_u64_u32_shr | 154 | #ifndef mul_u64_u32_shr |
@@ -161,6 +168,50 @@ static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift) | |||
161 | } | 168 | } |
162 | #endif /* mul_u64_u32_shr */ | 169 | #endif /* mul_u64_u32_shr */ |
163 | 170 | ||
171 | #ifndef mul_u64_u64_shr | ||
172 | static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift) | ||
173 | { | ||
174 | union { | ||
175 | u64 ll; | ||
176 | struct { | ||
177 | #ifdef __BIG_ENDIAN | ||
178 | u32 high, low; | ||
179 | #else | ||
180 | u32 low, high; | ||
181 | #endif | ||
182 | } l; | ||
183 | } rl, rm, rn, rh, a0, b0; | ||
184 | u64 c; | ||
185 | |||
186 | a0.ll = a; | ||
187 | b0.ll = b; | ||
188 | |||
189 | rl.ll = (u64)a0.l.low * b0.l.low; | ||
190 | rm.ll = (u64)a0.l.low * b0.l.high; | ||
191 | rn.ll = (u64)a0.l.high * b0.l.low; | ||
192 | rh.ll = (u64)a0.l.high * b0.l.high; | ||
193 | |||
194 | /* | ||
195 | * Each of these lines computes a 64-bit intermediate result into "c", | ||
196 | * starting at bits 32-95. The low 32-bits go into the result of the | ||
197 | * multiplication, the high 32-bits are carried into the next step. | ||
198 | */ | ||
199 | rl.l.high = c = (u64)rl.l.high + rm.l.low + rn.l.low; | ||
200 | rh.l.low = c = (c >> 32) + rm.l.high + rn.l.high + rh.l.low; | ||
201 | rh.l.high = (c >> 32) + rh.l.high; | ||
202 | |||
203 | /* | ||
204 | * The 128-bit result of the multiplication is in rl.ll and rh.ll, | ||
205 | * shift it right and throw away the high part of the result. | ||
206 | */ | ||
207 | if (shift == 0) | ||
208 | return rl.ll; | ||
209 | if (shift < 64) | ||
210 | return (rl.ll >> shift) | (rh.ll << (64 - shift)); | ||
211 | return rh.ll >> (shift & 63); | ||
212 | } | ||
213 | #endif /* mul_u64_u64_shr */ | ||
214 | |||
164 | #endif | 215 | #endif |
165 | 216 | ||
166 | #endif /* _LINUX_MATH64_H */ | 217 | #endif /* _LINUX_MATH64_H */ |