|
@@ -831,6 +831,7 @@ static u32 msrs_to_save[] = {
|
|
|
static unsigned num_msrs_to_save;
|
|
|
|
|
|
static const u32 emulated_msrs[] = {
|
|
|
+ MSR_IA32_TSC_ADJUST,
|
|
|
MSR_IA32_TSCDEADLINE,
|
|
|
MSR_IA32_MISC_ENABLE,
|
|
|
MSR_IA32_MCG_STATUS,
|
|
@@ -1135,6 +1136,12 @@ void kvm_track_tsc_matching(struct kvm_vcpu *vcpu)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+static void update_ia32_tsc_adjust_msr(struct kvm_vcpu *vcpu, s64 offset)
|
|
|
+{
|
|
|
+ u64 curr_offset = kvm_x86_ops->read_tsc_offset(vcpu);
|
|
|
+ vcpu->arch.ia32_tsc_adjust_msr += offset - curr_offset;
|
|
|
+}
|
|
|
+
|
|
|
void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|
|
{
|
|
|
struct kvm *kvm = vcpu->kvm;
|
|
@@ -1222,6 +1229,8 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|
|
vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec;
|
|
|
vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write;
|
|
|
|
|
|
+ if (guest_cpuid_has_tsc_adjust(vcpu) && !msr->host_initiated)
|
|
|
+ update_ia32_tsc_adjust_msr(vcpu, offset);
|
|
|
kvm_x86_ops->write_tsc_offset(vcpu, offset);
|
|
|
raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
|
|
|
|
|
@@ -1918,6 +1927,15 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|
|
case MSR_IA32_TSCDEADLINE:
|
|
|
kvm_set_lapic_tscdeadline_msr(vcpu, data);
|
|
|
break;
|
|
|
+ case MSR_IA32_TSC_ADJUST:
|
|
|
+ if (guest_cpuid_has_tsc_adjust(vcpu)) {
|
|
|
+ if (!msr_info->host_initiated) {
|
|
|
+ u64 adj = data - vcpu->arch.ia32_tsc_adjust_msr;
|
|
|
+ kvm_x86_ops->adjust_tsc_offset(vcpu, adj, true);
|
|
|
+ }
|
|
|
+ vcpu->arch.ia32_tsc_adjust_msr = data;
|
|
|
+ }
|
|
|
+ break;
|
|
|
case MSR_IA32_MISC_ENABLE:
|
|
|
vcpu->arch.ia32_misc_enable_msr = data;
|
|
|
break;
|
|
@@ -2277,6 +2295,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
|
|
|
case MSR_IA32_TSCDEADLINE:
|
|
|
data = kvm_get_lapic_tscdeadline_msr(vcpu);
|
|
|
break;
|
|
|
+ case MSR_IA32_TSC_ADJUST:
|
|
|
+ data = (u64)vcpu->arch.ia32_tsc_adjust_msr;
|
|
|
+ break;
|
|
|
case MSR_IA32_MISC_ENABLE:
|
|
|
data = vcpu->arch.ia32_misc_enable_msr;
|
|
|
break;
|
|
@@ -6607,6 +6628,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
|
|
|
if (!zalloc_cpumask_var(&vcpu->arch.wbinvd_dirty_mask, GFP_KERNEL))
|
|
|
goto fail_free_mce_banks;
|
|
|
|
|
|
+ vcpu->arch.ia32_tsc_adjust_msr = 0x0;
|
|
|
kvm_async_pf_hash_reset(vcpu);
|
|
|
kvm_pmu_init(vcpu);
|
|
|
|