Re: [PATCH 02/60] KVM: SVM: Add support for the SEV-SNP #HV doorbell page NAE event

Tom Lendacky <[email protected]>
Newsgroups org.infradead.lists.kvm-riscv,dev.linux.lists.coconut-svsm,dev.linux.lists.kvmarm,dev.linux.lists.loongarch,org.kernel.vger.kvm,org.kernel.vger.linux-kernel,org.kernel.vger.linux-mips,org.ozlabs.lists.linuxppc-dev
Message-ID <[email protected]>
On 6/10/26 08:28, Tom Lendacky wrote:
> On 6/8/26 09:41, Jörg Rödel wrote:
>> From: Melody Wang <[email protected]>
>>
>> To support Restricted Injection, the SEV-SNP guest must register a doorbell
>> page for use with #HV. This is done using the #HV doorbell page NAE event.
>>
>> This event consists of four actions: GET_PREFERRED, SET, QUERY, CLEAR.
>> Implement it per the GHCB specification.
>>
>> 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/uapi/asm/svm.h |  5 +++
>>  arch/x86/kvm/svm/sev.c          | 71 +++++++++++++++++++++++++++++++++
>>  arch/x86/kvm/svm/svm.c          |  3 ++
>>  arch/x86/kvm/svm/svm.h          |  2 +
>>  4 files changed, 81 insertions(+)
>>
>> diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h
>> index 010a45c9f614..d84a13ac4627 100644
>> --- a/arch/x86/include/uapi/asm/svm.h
>> +++ b/arch/x86/include/uapi/asm/svm.h
>> @@ -117,6 +117,11 @@
>>  #define SVM_VMGEXIT_AP_CREATE_ON_INIT		0
>>  #define SVM_VMGEXIT_AP_CREATE			1
>>  #define SVM_VMGEXIT_AP_DESTROY			2
>> +#define SVM_VMGEXIT_HVDB_PAGE			0x80000014ull
>> +#define SVM_VMGEXIT_HVDB_GET_PREFERRED		0
>> +#define SVM_VMGEXIT_HVDB_SET			1
>> +#define SVM_VMGEXIT_HVDB_QUERY			2
>> +#define SVM_VMGEXIT_HVDB_CLEAR			3
>>  #define SVM_VMGEXIT_SNP_RUN_VMPL		0x80000018ull
>>  #define SVM_VMGEXIT_SAVIC			0x8000001aull
>>  #define SVM_VMGEXIT_SAVIC_REGISTER_GPA		0
>> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
>> index 6c6a6d663e29..b9ad1169cb2c 100644
>> --- a/arch/x86/kvm/svm/sev.c
>> +++ b/arch/x86/kvm/svm/sev.c
>> @@ -3522,6 +3522,10 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
>>  		    control->exit_info_1 == control->exit_info_2)
>>  			goto vmgexit_err;
>>  		break;
>> +	case SVM_VMGEXIT_HVDB_PAGE:
>> +		if (!is_sev_snp_guest(vcpu))

I think it should also be validated that Restricted Injection is enabled
for the guest as well - either here or in the sev_snp_hv_doorbell_page()
function.

Thanks,
Tom

>> +			goto vmgexit_err;
>> +		break;
>>  	default:
>>  		reason = GHCB_ERR_INVALID_EVENT;
>>  		goto vmgexit_err;
>> @@ -4341,6 +4345,65 @@ static int snp_handle_ext_guest_req(struct vcpu_svm *svm, gpa_t req_gpa, gpa_t r
>>  	return 1; /* resume guest */
>>  }
>>  
>> +static int sev_snp_hv_doorbell_page(struct vcpu_svm *svm)
>> +{
>> +	struct kvm_vcpu *vcpu = &svm->vcpu;
>> +	struct kvm_host_map hvdb_map;
>> +	gpa_t hvdb_gpa;
>> +	u64 request;
>> +
>> +	if (!is_sev_snp_guest(vcpu))
>> +		return -EINVAL;
>> +
>> +	request = svm->vmcb->control.exit_info_1;
>> +	hvdb_gpa = svm->vmcb->control.exit_info_2;
>> +
>> +	switch (request) {
>> +	case SVM_VMGEXIT_HVDB_GET_PREFERRED:
>> +		ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, ~0ULL);
>> +		break;
>> +	case SVM_VMGEXIT_HVDB_SET:
>> +		svm->sev_es.hvdb_gpa = INVALID_PAGE;
>> +
>> +		if (!PAGE_ALIGNED(hvdb_gpa)) {
>> +			vcpu_unimpl(vcpu, "vmgexit: unaligned #HV doorbell page address [%#llx] from guest\n",
>> +				    hvdb_gpa);
>> +			return -EINVAL;
>> +		}
>> +
>> +		if (!page_address_valid(vcpu, hvdb_gpa)) {
>> +			vcpu_unimpl(vcpu, "vmgexit: invalid #HV doorbell page address [%#llx] from guest\n",
>> +				    hvdb_gpa);
>> +			return -EINVAL;
>> +		}
>> +
>> +		/* Map and unmap the GPA just to be sure the GPA is valid */
>> +		if (kvm_vcpu_map(vcpu, gpa_to_gfn(hvdb_gpa), &hvdb_map)) {
>> +			vcpu_unimpl(vcpu, "vmgexit: error mapping #HV doorbell page [%#llx] from guest\n",
>> +				    hvdb_gpa);
>> +			return -EINVAL;
>> +		}
>> +		kvm_vcpu_unmap(vcpu, &hvdb_map);
>> +
>> +		svm->sev_es.hvdb_gpa = hvdb_gpa;
>> +		fallthrough;
>> +	case SVM_VMGEXIT_HVDB_QUERY:
>> +		ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, svm->sev_es.hvdb_gpa);
>> +		break;
>> +	case SVM_VMGEXIT_HVDB_CLEAR:
>> +		svm->sev_es.hvdb_gpa = INVALID_PAGE;
>> +		break;
>> +	default:
>> +		svm->sev_es.hvdb_gpa = INVALID_PAGE;
>> +
>> +		vcpu_unimpl(vcpu, "vmgexit: invalid #HV doorbell page request [%#llx] from guest\n",
>> +			    request);
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>  static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm)
>>  {
>>  	struct vmcb_control_area *control = &svm->vmcb->control;
>> @@ -4617,6 +4680,14 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
>>  	case SVM_VMGEXIT_EXT_GUEST_REQUEST:
>>  		ret = snp_handle_ext_guest_req(svm, control->exit_info_1, control->exit_info_2);
>>  		break;
>> +	case SVM_VMGEXIT_HVDB_PAGE:
>> +		if (sev_snp_hv_doorbell_page(svm)) {
>> +			ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
>> +			ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT);
>> +		}
>> +
>> +		ret = 1;
>> +		break;
>>  	case SVM_VMGEXIT_UNSUPPORTED_EVENT:
>>  		vcpu_unimpl(vcpu,
>>  			    "vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n",
>> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
>> index e02a38da5296..7981e7583384 100644
>> --- a/arch/x86/kvm/svm/svm.c
>> +++ b/arch/x86/kvm/svm/svm.c
>> @@ -1277,6 +1277,9 @@ static void __svm_vcpu_reset(struct kvm_vcpu *vcpu)
>>  
>>  	svm->nmi_masked = false;
>>  	svm->awaiting_iret_completion = false;
>> +
>> +	if (is_sev_es_guest(vcpu))
> 
> Shouldn't this be is_sev_snp_guest() ?
> 
> Thanks,
> Tom
> 
>> +		svm->sev_es.hvdb_gpa = INVALID_PAGE;
>>  }
>>  
>>  static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
>> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
>> index 5137416be593..fb956c37c941 100644
>> --- a/arch/x86/kvm/svm/svm.h
>> +++ b/arch/x86/kvm/svm/svm.h
>> @@ -270,6 +270,8 @@ struct vcpu_sev_es_state {
>>  	gpa_t snp_vmsa_gpa;
>>  	bool snp_ap_waiting_for_reset;
>>  	bool snp_has_guest_vmsa;
>> +
>> +	gpa_t hvdb_gpa;
>>  };
>>  
>>  struct vcpu_svm {
> 


-- 
kvm-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kvm-riscv
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.