[RFC PATCH v5 8/8] KVM: SVM: Enable Restricted Injection for an SEV-SNP guest

From: Melody Wang

Date: Sun Nov 08 2026 - 22:24:07 EST


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 <thomas.lendacky@xxxxxxx>
Signed-off-by: Thomas Lendacky <thomas.lendacky@xxxxxxx>
Signed-off-by: Melody Wang <huibo.wang@xxxxxxx>
---
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/asm/sev-common.h | 1 +
arch/x86/kvm/svm/sev.c | 21 ++++++++++++++++++++-
3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index f70ee74b5f92..c491c355fabd 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -466,6 +466,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 b7c2993f8c63..a7b290d3fd42 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -42,7 +42,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
@@ -3261,6 +3263,9 @@ 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_supported_vmsa_features |= SVM_SEV_FEAT_RESTRICTED_INJECTION;
}

void sev_hardware_unsetup(void)
@@ -4862,10 +4867,22 @@ 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;
+ svm->vmcb->control.int_ctl &= ~V_GIF_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;

@@ -4932,6 +4949,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 (sev_snp_guest(vcpu->kvm))
+ sev_snp_init_vmcb(svm);
}

void sev_init_vmcb(struct vcpu_svm *svm, bool init_event)
--
2.43.0