diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/cpufeature.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/msr-index.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/cpuid.c | 2 | ||||
-rw-r--r-- | arch/x86/kvm/cpuid.h | 8 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 8 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 9 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 22 |
8 files changed, 53 insertions, 0 deletions
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 8c297aa53eef..602c4764614d 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
@@ -202,6 +202,7 @@ | |||
202 | 202 | ||
203 | /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ | 203 | /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ |
204 | #define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ | 204 | #define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ |
205 | #define X86_FEATURE_TSC_ADJUST (9*32+ 1) /* TSC adjustment MSR 0x3b */ | ||
205 | #define X86_FEATURE_BMI1 (9*32+ 3) /* 1st group bit manipulation extensions */ | 206 | #define X86_FEATURE_BMI1 (9*32+ 3) /* 1st group bit manipulation extensions */ |
206 | #define X86_FEATURE_HLE (9*32+ 4) /* Hardware Lock Elision */ | 207 | #define X86_FEATURE_HLE (9*32+ 4) /* Hardware Lock Elision */ |
207 | #define X86_FEATURE_AVX2 (9*32+ 5) /* AVX2 instructions */ | 208 | #define X86_FEATURE_AVX2 (9*32+ 5) /* AVX2 instructions */ |
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 56c5dca9d78d..dc87b65e9c3a 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -444,6 +444,7 @@ struct kvm_vcpu_arch { | |||
444 | s8 virtual_tsc_shift; | 444 | s8 virtual_tsc_shift; |
445 | u32 virtual_tsc_mult; | 445 | u32 virtual_tsc_mult; |
446 | u32 virtual_tsc_khz; | 446 | u32 virtual_tsc_khz; |
447 | s64 ia32_tsc_adjust_msr; | ||
447 | 448 | ||
448 | atomic_t nmi_queued; /* unprocessed asynchronous NMIs */ | 449 | atomic_t nmi_queued; /* unprocessed asynchronous NMIs */ |
449 | unsigned nmi_pending; /* NMI queued after currently running handler */ | 450 | unsigned nmi_pending; /* NMI queued after currently running handler */ |
@@ -711,6 +712,7 @@ struct kvm_x86_ops { | |||
711 | bool (*has_wbinvd_exit)(void); | 712 | bool (*has_wbinvd_exit)(void); |
712 | 713 | ||
713 | void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale); | 714 | void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale); |
715 | u64 (*read_tsc_offset)(struct kvm_vcpu *vcpu); | ||
714 | void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset); | 716 | void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset); |
715 | 717 | ||
716 | u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc); | 718 | u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc); |
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 7f0edceb7563..c2dea36dd7ac 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h | |||
@@ -236,6 +236,7 @@ | |||
236 | #define MSR_IA32_EBL_CR_POWERON 0x0000002a | 236 | #define MSR_IA32_EBL_CR_POWERON 0x0000002a |
237 | #define MSR_EBC_FREQUENCY_ID 0x0000002c | 237 | #define MSR_EBC_FREQUENCY_ID 0x0000002c |
238 | #define MSR_IA32_FEATURE_CONTROL 0x0000003a | 238 | #define MSR_IA32_FEATURE_CONTROL 0x0000003a |
239 | #define MSR_IA32_TSC_ADJUST 0x0000003b | ||
239 | 240 | ||
240 | #define FEATURE_CONTROL_LOCKED (1<<0) | 241 | #define FEATURE_CONTROL_LOCKED (1<<0) |
241 | #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) | 242 | #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) |
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index ec79e773342e..52f6166ef92c 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c | |||
@@ -320,6 +320,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
320 | if (index == 0) { | 320 | if (index == 0) { |
321 | entry->ebx &= kvm_supported_word9_x86_features; | 321 | entry->ebx &= kvm_supported_word9_x86_features; |
322 | cpuid_mask(&entry->ebx, 9); | 322 | cpuid_mask(&entry->ebx, 9); |
323 | // TSC_ADJUST is emulated | ||
324 | entry->ebx |= F(TSC_ADJUST); | ||
323 | } else | 325 | } else |
324 | entry->ebx = 0; | 326 | entry->ebx = 0; |
325 | entry->eax = 0; | 327 | entry->eax = 0; |
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index a10e46016851..3a8b50474477 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h | |||
@@ -28,6 +28,14 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) | |||
28 | return best && (best->ecx & bit(X86_FEATURE_XSAVE)); | 28 | return best && (best->ecx & bit(X86_FEATURE_XSAVE)); |
29 | } | 29 | } |
30 | 30 | ||
31 | static inline bool guest_cpuid_has_tsc_adjust(struct kvm_vcpu *vcpu) | ||
32 | { | ||
33 | struct kvm_cpuid_entry2 *best; | ||
34 | |||
35 | best = kvm_find_cpuid_entry(vcpu, 7, 0); | ||
36 | return best && (best->ebx & bit(X86_FEATURE_TSC_ADJUST)); | ||
37 | } | ||
38 | |||
31 | static inline bool guest_cpuid_has_smep(struct kvm_vcpu *vcpu) | 39 | static inline bool guest_cpuid_has_smep(struct kvm_vcpu *vcpu) |
32 | { | 40 | { |
33 | struct kvm_cpuid_entry2 *best; | 41 | struct kvm_cpuid_entry2 *best; |
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index fc22e58d23b7..dcb79527e7aa 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -1009,6 +1009,13 @@ static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale) | |||
1009 | svm->tsc_ratio = ratio; | 1009 | svm->tsc_ratio = ratio; |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | static u64 svm_read_tsc_offset(struct kvm_vcpu *vcpu) | ||
1013 | { | ||
1014 | struct vcpu_svm *svm = to_svm(vcpu); | ||
1015 | |||
1016 | return svm->vmcb->control.tsc_offset; | ||
1017 | } | ||
1018 | |||
1012 | static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) | 1019 | static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) |
1013 | { | 1020 | { |
1014 | struct vcpu_svm *svm = to_svm(vcpu); | 1021 | struct vcpu_svm *svm = to_svm(vcpu); |
@@ -4304,6 +4311,7 @@ static struct kvm_x86_ops svm_x86_ops = { | |||
4304 | .has_wbinvd_exit = svm_has_wbinvd_exit, | 4311 | .has_wbinvd_exit = svm_has_wbinvd_exit, |
4305 | 4312 | ||
4306 | .set_tsc_khz = svm_set_tsc_khz, | 4313 | .set_tsc_khz = svm_set_tsc_khz, |
4314 | .read_tsc_offset = svm_read_tsc_offset, | ||
4307 | .write_tsc_offset = svm_write_tsc_offset, | 4315 | .write_tsc_offset = svm_write_tsc_offset, |
4308 | .adjust_tsc_offset = svm_adjust_tsc_offset, | 4316 | .adjust_tsc_offset = svm_adjust_tsc_offset, |
4309 | .compute_tsc_offset = svm_compute_tsc_offset, | 4317 | .compute_tsc_offset = svm_compute_tsc_offset, |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 45ffa32352f1..2fd2046dc94c 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -1884,6 +1884,11 @@ static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale) | |||
1884 | WARN(1, "user requested TSC rate below hardware speed\n"); | 1884 | WARN(1, "user requested TSC rate below hardware speed\n"); |
1885 | } | 1885 | } |
1886 | 1886 | ||
1887 | static u64 vmx_read_tsc_offset(struct kvm_vcpu *vcpu) | ||
1888 | { | ||
1889 | return vmcs_read64(TSC_OFFSET); | ||
1890 | } | ||
1891 | |||
1887 | /* | 1892 | /* |
1888 | * writes 'offset' into guest's timestamp counter offset register | 1893 | * writes 'offset' into guest's timestamp counter offset register |
1889 | */ | 1894 | */ |
@@ -2266,6 +2271,9 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |||
2266 | } | 2271 | } |
2267 | ret = kvm_set_msr_common(vcpu, msr_info); | 2272 | ret = kvm_set_msr_common(vcpu, msr_info); |
2268 | break; | 2273 | break; |
2274 | case MSR_IA32_TSC_ADJUST: | ||
2275 | ret = kvm_set_msr_common(vcpu, msr_info); | ||
2276 | break; | ||
2269 | case MSR_TSC_AUX: | 2277 | case MSR_TSC_AUX: |
2270 | if (!vmx->rdtscp_enabled) | 2278 | if (!vmx->rdtscp_enabled) |
2271 | return 1; | 2279 | return 1; |
@@ -7345,6 +7353,7 @@ static struct kvm_x86_ops vmx_x86_ops = { | |||
7345 | .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit, | 7353 | .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit, |
7346 | 7354 | ||
7347 | .set_tsc_khz = vmx_set_tsc_khz, | 7355 | .set_tsc_khz = vmx_set_tsc_khz, |
7356 | .read_tsc_offset = vmx_read_tsc_offset, | ||
7348 | .write_tsc_offset = vmx_write_tsc_offset, | 7357 | .write_tsc_offset = vmx_write_tsc_offset, |
7349 | .adjust_tsc_offset = vmx_adjust_tsc_offset, | 7358 | .adjust_tsc_offset = vmx_adjust_tsc_offset, |
7350 | .compute_tsc_offset = vmx_compute_tsc_offset, | 7359 | .compute_tsc_offset = vmx_compute_tsc_offset, |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 95f66136f2d5..b0b8abe688ce 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -831,6 +831,7 @@ static u32 msrs_to_save[] = { | |||
831 | static unsigned num_msrs_to_save; | 831 | static unsigned num_msrs_to_save; |
832 | 832 | ||
833 | static const u32 emulated_msrs[] = { | 833 | static const u32 emulated_msrs[] = { |
834 | MSR_IA32_TSC_ADJUST, | ||
834 | MSR_IA32_TSCDEADLINE, | 835 | MSR_IA32_TSCDEADLINE, |
835 | MSR_IA32_MISC_ENABLE, | 836 | MSR_IA32_MISC_ENABLE, |
836 | MSR_IA32_MCG_STATUS, | 837 | MSR_IA32_MCG_STATUS, |
@@ -1135,6 +1136,12 @@ void kvm_track_tsc_matching(struct kvm_vcpu *vcpu) | |||
1135 | #endif | 1136 | #endif |
1136 | } | 1137 | } |
1137 | 1138 | ||
1139 | static void update_ia32_tsc_adjust_msr(struct kvm_vcpu *vcpu, s64 offset) | ||
1140 | { | ||
1141 | u64 curr_offset = kvm_x86_ops->read_tsc_offset(vcpu); | ||
1142 | vcpu->arch.ia32_tsc_adjust_msr += offset - curr_offset; | ||
1143 | } | ||
1144 | |||
1138 | void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) | 1145 | void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) |
1139 | { | 1146 | { |
1140 | struct kvm *kvm = vcpu->kvm; | 1147 | struct kvm *kvm = vcpu->kvm; |
@@ -1222,6 +1229,8 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) | |||
1222 | vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec; | 1229 | vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec; |
1223 | vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write; | 1230 | vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write; |
1224 | 1231 | ||
1232 | if (guest_cpuid_has_tsc_adjust(vcpu) && !msr->host_initiated) | ||
1233 | update_ia32_tsc_adjust_msr(vcpu, offset); | ||
1225 | kvm_x86_ops->write_tsc_offset(vcpu, offset); | 1234 | kvm_x86_ops->write_tsc_offset(vcpu, offset); |
1226 | raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); | 1235 | raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); |
1227 | 1236 | ||
@@ -1918,6 +1927,15 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |||
1918 | case MSR_IA32_TSCDEADLINE: | 1927 | case MSR_IA32_TSCDEADLINE: |
1919 | kvm_set_lapic_tscdeadline_msr(vcpu, data); | 1928 | kvm_set_lapic_tscdeadline_msr(vcpu, data); |
1920 | break; | 1929 | break; |
1930 | case MSR_IA32_TSC_ADJUST: | ||
1931 | if (guest_cpuid_has_tsc_adjust(vcpu)) { | ||
1932 | if (!msr_info->host_initiated) { | ||
1933 | u64 adj = data - vcpu->arch.ia32_tsc_adjust_msr; | ||
1934 | kvm_x86_ops->adjust_tsc_offset(vcpu, adj, true); | ||
1935 | } | ||
1936 | vcpu->arch.ia32_tsc_adjust_msr = data; | ||
1937 | } | ||
1938 | break; | ||
1921 | case MSR_IA32_MISC_ENABLE: | 1939 | case MSR_IA32_MISC_ENABLE: |
1922 | vcpu->arch.ia32_misc_enable_msr = data; | 1940 | vcpu->arch.ia32_misc_enable_msr = data; |
1923 | break; | 1941 | break; |
@@ -2277,6 +2295,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | |||
2277 | case MSR_IA32_TSCDEADLINE: | 2295 | case MSR_IA32_TSCDEADLINE: |
2278 | data = kvm_get_lapic_tscdeadline_msr(vcpu); | 2296 | data = kvm_get_lapic_tscdeadline_msr(vcpu); |
2279 | break; | 2297 | break; |
2298 | case MSR_IA32_TSC_ADJUST: | ||
2299 | data = (u64)vcpu->arch.ia32_tsc_adjust_msr; | ||
2300 | break; | ||
2280 | case MSR_IA32_MISC_ENABLE: | 2301 | case MSR_IA32_MISC_ENABLE: |
2281 | data = vcpu->arch.ia32_misc_enable_msr; | 2302 | data = vcpu->arch.ia32_misc_enable_msr; |
2282 | break; | 2303 | break; |
@@ -6607,6 +6628,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | |||
6607 | if (!zalloc_cpumask_var(&vcpu->arch.wbinvd_dirty_mask, GFP_KERNEL)) | 6628 | if (!zalloc_cpumask_var(&vcpu->arch.wbinvd_dirty_mask, GFP_KERNEL)) |
6608 | goto fail_free_mce_banks; | 6629 | goto fail_free_mce_banks; |
6609 | 6630 | ||
6631 | vcpu->arch.ia32_tsc_adjust_msr = 0x0; | ||
6610 | kvm_async_pf_hash_reset(vcpu); | 6632 | kvm_async_pf_hash_reset(vcpu); |
6611 | kvm_pmu_init(vcpu); | 6633 | kvm_pmu_init(vcpu); |
6612 | 6634 | ||