Set the FRED_VIRT_ENABLE bit (bit 4) in the misc_ctl2 field of the VMCB to enable FRED virtualization. This enables hardware to automatically save and restore the FRED MSRs on VMRUN and #VMEXIT. Set the bit in svm_vcpu_after_set_cpuid() when FRED is exposed to the guest, and clear it otherwise. FRED virtualization requires vNMI to handle guest NMIs correctly, so, clear FRED when vNMI is unavailable. Signed-off-by: Shivansh Dhiman --- Changes in v3: * Renamed FRED_VIRT_ENABLE_MASK to SVM_MISC2_ENABLE_V_FRED. * Set the bit in misc_ctl2, the current name of the VMCB field. * Removed the unconditional kvm_cpu_cap_clear(X86_FEATURE_FRED). * Clear FRED when vNMI is unavailable (Andrew Cooper). Changes in v2: * Confined the enabling of vFRED to svm_vcpu_after_set_cpuid() only (Sean Christopherson). --- arch/x86/include/asm/svm.h | 1 + arch/x86/kvm/svm/svm.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index 1a6d4509b05b..288a8a78f1c7 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -250,6 +250,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area { #define SVM_MISC2_ENABLE_V_LBR BIT_ULL(0) #define SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE BIT_ULL(1) +#define SVM_MISC2_ENABLE_V_FRED BIT_ULL(4) #define SVM_TSC_RATIO_RSVD 0xffffff0000000000ULL #define SVM_TSC_RATIO_MIN 0x0000000000000001ULL diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 86a3ba54aab2..25dd379725d4 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4912,6 +4912,11 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) if (guest_cpuid_is_intel_compatible(vcpu)) guest_cpu_cap_clear(vcpu, X86_FEATURE_V_VMSAVE_VMLOAD); + if (guest_cpu_cap_has(vcpu, X86_FEATURE_FRED)) + svm->vmcb->control.misc_ctl2 |= SVM_MISC2_ENABLE_V_FRED; + else + svm->vmcb->control.misc_ctl2 &= ~SVM_MISC2_ENABLE_V_FRED; + if (is_sev_guest(vcpu)) sev_vcpu_after_set_cpuid(svm); } @@ -5675,9 +5680,6 @@ static __init void svm_set_cpu_caps(void) kvm_cpu_cap_clear(X86_FEATURE_IBT); - /* SVM FRED virtualization not implemented yet */ - kvm_cpu_cap_clear(X86_FEATURE_FRED); - /* CPUID 0x80000001 and 0x8000000A (SVM features) */ if (nested) { kvm_cpu_cap_set(X86_FEATURE_SVM); @@ -5751,6 +5753,9 @@ static __init void svm_set_cpu_caps(void) /* CPUID 0x8000001F (SME/SEV features) */ sev_set_cpu_caps(); + if (!vnmi) + kvm_cpu_cap_clear(X86_FEATURE_FRED); + /* * Clear capabilities that are automatically configured by common code, * but that require explicit SVM support (that isn't yet implemented). -- 2.43.0