|
@@ -178,6 +178,8 @@ struct vcpu_svm {
|
|
|
uint64_t sysenter_eip;
|
|
|
uint64_t tsc_aux;
|
|
|
|
|
|
+ u64 msr_decfg;
|
|
|
+
|
|
|
u64 next_rip;
|
|
|
|
|
|
u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS];
|
|
@@ -3871,7 +3873,18 @@ static int cr8_write_interception(struct vcpu_svm *svm)
|
|
|
|
|
|
static int svm_get_msr_feature(struct kvm_msr_entry *msr)
|
|
|
{
|
|
|
- return 1;
|
|
|
+ msr->data = 0;
|
|
|
+
|
|
|
+ switch (msr->index) {
|
|
|
+ case MSR_F10H_DECFG:
|
|
|
+ if (boot_cpu_has(X86_FEATURE_LFENCE_RDTSC))
|
|
|
+ msr->data |= MSR_F10H_DECFG_LFENCE_SERIALIZE;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|
@@ -3969,6 +3982,9 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|
|
msr_info->data = 0x1E;
|
|
|
}
|
|
|
break;
|
|
|
+ case MSR_F10H_DECFG:
|
|
|
+ msr_info->data = svm->msr_decfg;
|
|
|
+ break;
|
|
|
default:
|
|
|
return kvm_get_msr_common(vcpu, msr_info);
|
|
|
}
|
|
@@ -4147,6 +4163,24 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|
|
case MSR_VM_IGNNE:
|
|
|
vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
|
|
|
break;
|
|
|
+ case MSR_F10H_DECFG: {
|
|
|
+ struct kvm_msr_entry msr_entry;
|
|
|
+
|
|
|
+ msr_entry.index = msr->index;
|
|
|
+ if (svm_get_msr_feature(&msr_entry))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ /* Check the supported bits */
|
|
|
+ if (data & ~msr_entry.data)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ /* Don't allow the guest to change a bit, #GP */
|
|
|
+ if (!msr->host_initiated && (data ^ msr_entry.data))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ svm->msr_decfg = data;
|
|
|
+ break;
|
|
|
+ }
|
|
|
case MSR_IA32_APICBASE:
|
|
|
if (kvm_vcpu_apicv_active(vcpu))
|
|
|
avic_update_vapic_bar(to_svm(vcpu), data);
|