From: Melody Wang <[email protected]>

Enable Restricted Injection in an SEV-SNP guest by setting the corresponding
bit in the VMSA SEV features field (SEV_FEATURES[3]) from QEMU.

Add Restricted Injection to the supported hypervisor features.

Co-developed-by: Thomas Lendacky <[email protected]>
Signed-off-by: Thomas Lendacky <[email protected]>
Signed-off-by: Melody Wang <[email protected]>
Signed-off-by: Joerg Roedel <[email protected]>
---
 arch/x86/include/asm/cpufeatures.h |  1 +
 arch/x86/include/asm/sev-common.h  |  1 +
 arch/x86/kvm/svm/sev.c             | 26 +++++++++++++++++++++++++-
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/cpufeatures.h 
b/arch/x86/include/asm/cpufeatures.h
index 1d506e5d6f46..41af7bd2473c 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -453,6 +453,7 @@
 #define X86_FEATURE_SNP_SECURE_TSC     (19*32+ 8) /* SEV-SNP Secure TSC */
 #define X86_FEATURE_V_TSC_AUX          (19*32+ 9) /* Virtual TSC_AUX */
 #define X86_FEATURE_SME_COHERENT       (19*32+10) /* hardware-enforced cache 
coherency */
+#define X86_FEATURE_RESTRICTED_INJECTION (19*32+12) /* Restricted Injection */
 #define X86_FEATURE_DEBUG_SWAP         (19*32+14) /* "debug_swap" SEV-ES full 
debug state swap support */
 #define X86_FEATURE_RMPREAD            (19*32+21) /* RMPREAD instruction */
 #define X86_FEATURE_SEGMENTED_RMP      (19*32+23) /* Segmented RMP support */
diff --git a/arch/x86/include/asm/sev-common.h 
b/arch/x86/include/asm/sev-common.h
index 01a6e4dbe423..ee17a3541b55 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -136,6 +136,7 @@ enum psc_op {
 
 #define GHCB_HV_FT_SNP                 BIT_ULL(0)
 #define GHCB_HV_FT_SNP_AP_CREATION     BIT_ULL(1)
+#define GHCB_HV_FT_SNP_RINJ            (BIT_ULL(2) | 
GHCB_HV_FT_SNP_AP_CREATION)
 #define GHCB_HV_FT_SNP_MULTI_VMPL      BIT_ULL(5)
 
 /*
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 6d5d66563b0d..369fb1e36f58 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -39,7 +39,9 @@
 #define GHCB_VERSION_MAX       2ULL
 #define GHCB_VERSION_MIN       1ULL
 
-#define GHCB_HV_FT_SUPPORTED   (GHCB_HV_FT_SNP | GHCB_HV_FT_SNP_AP_CREATION)
+#define GHCB_HV_FT_SUPPORTED   (GHCB_HV_FT_SNP |               \
+                                GHCB_HV_FT_SNP_AP_CREATION |   \
+                                GHCB_HV_FT_SNP_RINJ)
 
 /*
  * The GHCB spec essentially states that all non-zero error codes other than
@@ -63,6 +65,10 @@ module_param_named(sev_es, sev_es_enabled, bool, 0444);
 static bool __ro_after_init sev_snp_enabled = true;
 module_param_named(sev_snp, sev_snp_enabled, bool, 0444);
 
+/* enable/disable SEV-SNP Restricted Injection support */
+static bool sev_snp_restricted_injection_enabled = true;
+module_param_named(restricted_injection, sev_snp_restricted_injection_enabled, 
bool, 0444);
+
 static unsigned int __ro_after_init nr_ciphertext_hiding_asids;
 module_param_named(ciphertext_hiding_asids, nr_ciphertext_hiding_asids, uint, 
0444);
 
@@ -3223,6 +3229,12 @@ void __init sev_hardware_setup(void)
 
        if (sev_snp_enabled && tsc_khz && 
cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC))
                sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC;
+
+       if (!sev_snp_enabled || 
!cpu_feature_enabled(X86_FEATURE_RESTRICTED_INJECTION))
+               sev_snp_restricted_injection_enabled = false;
+
+       if (sev_snp_restricted_injection_enabled)
+               sev_supported_vmsa_features |= 
SVM_SEV_FEAT_RESTRICTED_INJECTION;
 }
 
 void sev_hardware_unsetup(void)
@@ -4773,10 +4785,20 @@ void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm)
                vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f));
 }
 
+static void sev_snp_init_vmcb(struct vcpu_svm *svm)
+{
+       struct kvm_sev_info *sev = &to_kvm_svm(svm->vcpu.kvm)->sev_info;
+
+       /* V_NMI is not supported when Restricted Injection is enabled */
+       if (sev->vmsa_features & SVM_SEV_FEAT_RESTRICTED_INJECTION)
+               svm->vmcb->control.int_ctl &= ~V_NMI_ENABLE_MASK;
+}
+
 static void sev_es_init_vmcb(struct vcpu_svm *svm, bool init_event)
 {
        struct kvm_sev_info *sev = to_kvm_sev_info(svm->vcpu.kvm);
        struct vmcb *vmcb = svm->vmcb01.ptr;
+       struct kvm_vcpu *vcpu = &svm->vcpu;
 
        svm->vmcb->control.misc_ctl |= SVM_MISC_ENABLE_SEV_ES;
 
@@ -4843,6 +4865,8 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm, bool 
init_event)
                set_ghcb_msr(svm, GHCB_MSR_SEV_INFO((__u64)sev->ghcb_version,
                                                    GHCB_VERSION_MIN,
                                                    sev_enc_bit));
+       if (is_sev_snp_guest(vcpu))
+               sev_snp_init_vmcb(svm);
 }
 
 void sev_init_vmcb(struct vcpu_svm *svm, bool init_event)
-- 
2.53.0


Reply via email to