Re: [PATCH v4 3/7] KVM: SVM: Inject #HV when Restricted Injection is active

Tom Lendacky
2026-04-28T19:17:31Z

On 4/24/26 12:42, Melody Wang wrote:
> When Restricted Injection is active, only #HV exceptions can be injected into
> the SEV-SNP guest. Detect that, and then follow the #HV doorbell communication
> from the GHCB specification to inject the interrupt or exception.
>
> Co-developed-by: Thomas Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Thomas Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Melody Wang <huibo.wang@amd.com>
> ---
> arch/x86/kvm/svm/sev.c | 164 +++++++++++++++++++++++++++++++++++++++++
> arch/x86/kvm/svm/svm.c | 14 +++-
> arch/x86/kvm/svm/svm.h | 21 ++++++
> 3 files changed, 197 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index f09c4236fb5e..509a4f8b5073 100644

> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index 4ab58307bf75..b4627884c36f 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -55,6 +55,10 @@ extern int tsc_aux_uret_slot __ro_after_init;
>
> extern struct kvm_x86_ops svm_x86_ops __initdata;
>
> +enum inject_type {
> + INJECT_IRQ,
> +};
> +
> /*
> * Clean bits in VMCB.
> * VMCB_ALL_CLEAN_MASK might also need to
> @@ -968,6 +972,17 @@ void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
> int sev_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, bool is_private);
> struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu);
> void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa);
> +bool sev_snp_queue_exception(struct kvm_vcpu *vcpu);
> +bool sev_snp_inject(enum inject_type type, struct kvm_vcpu *vcpu);
> +void sev_snp_cancel_injection(struct kvm_vcpu *vcpu);
> +bool sev_snp_blocked(enum inject_type type, struct kvm_vcpu *vcpu);
> +static inline bool sev_snp_is_rinj_active(struct kvm_vcpu *vcpu)
> +{
> + struct kvm_sev_info *sev = &to_kvm_svm(vcpu->kvm)->sev_info;

You can use to_kvm_sev_info() here.

Thanks,
Tom

> +
> + return is_sev_snp_guest(vcpu) &&
> + (sev->vmsa_features & SVM_SEV_FEAT_RESTRICTED_INJECTION);
> +};
> #else
> static inline struct page *snp_safe_alloc_page_node(int node, gfp_t gfp)
> {
> @@ -1005,6 +1020,12 @@ static inline struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
> return NULL;
> }
> static inline void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa) {}
> +
> +static inline bool sev_snp_queue_exception(struct kvm_vcpu *vcpu) { return false; }
> +static inline bool sev_snp_inject(enum inject_type type, struct kvm_vcpu *vcpu) { return false; }
> +static inline void sev_snp_cancel_injection(struct kvm_vcpu *vcpu) {}
> +static inline bool sev_snp_blocked(enum inject_type type, struct kvm_vcpu *vcpu) { return false; }
> +static inline bool sev_snp_is_rinj_active(struct kvm_vcpu *vcpu) { return false; }
> #endif
>
> /* vmenter.S */