| From foo@baz Tue Aug 14 16:14:56 CEST 2018 |
| From: Tom Lendacky <thomas.lendacky@amd.com> |
| Date: Sat, 24 Feb 2018 00:18:20 +0100 |
| Subject: KVM: SVM: Add MSR-based feature support for serializing LFENCE |
| |
| From: Tom Lendacky <thomas.lendacky@amd.com> |
| |
| commit d1d93fa90f1afa926cb060b7f78ab01a65705b4d upstream |
| |
| In order to determine if LFENCE is a serializing instruction on AMD |
| processors, MSR 0xc0011029 (MSR_F10H_DECFG) must be read and the state |
| of bit 1 checked. This patch will add support to allow a guest to |
| properly make this determination. |
| |
| Add the MSR feature callback operation to svm.c and add MSR 0xc0011029 |
| to the list of MSR-based features. If LFENCE is serializing, then the |
| feature is supported, allowing the hypervisor to set the value of the |
| MSR that guest will see. Support is also added to write (hypervisor only) |
| and read the MSR value for the guest. A write by the guest will result in |
| a #GP. A read by the guest will return the value as set by the host. In |
| this way, the support to expose the feature to the guest is controlled by |
| the hypervisor. |
| |
| Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/kvm/svm.c | 36 +++++++++++++++++++++++++++++++++++- |
| arch/x86/kvm/x86.c | 1 + |
| 2 files changed, 36 insertions(+), 1 deletion(-) |
| |
| --- a/arch/x86/kvm/svm.c |
| +++ b/arch/x86/kvm/svm.c |
| @@ -175,6 +175,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]; |
| @@ -3487,7 +3489,18 @@ static int cr8_write_interception(struct |
| |
| 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) |
| @@ -3592,6 +3605,9 @@ static int svm_get_msr(struct kvm_vcpu * |
| 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); |
| } |
| @@ -3780,6 +3796,24 @@ static int svm_set_msr(struct kvm_vcpu * |
| 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); |
| --- a/arch/x86/kvm/x86.c |
| +++ b/arch/x86/kvm/x86.c |
| @@ -1013,6 +1013,7 @@ static unsigned num_emulated_msrs; |
| * can be used by a hypervisor to validate requested CPU features. |
| */ |
| static u32 msr_based_features[] = { |
| + MSR_F10H_DECFG, |
| }; |
| |
| static unsigned int num_msr_based_features; |