Re: [PATCH 3/4] kvm: svm: Support guest-provided VMSA for launching

Sean Christopherson <[email protected]> Tue, 23 Jun 2026 14:07:59 -0700
Newsgroups dev.linux.lists.coconut-svsm,org.kernel.vger.kvm,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On Thu, Jun 11, 2026, J=C3=B6rg R=C3=B6del wrote:
> From: Joerg Roedel <[email protected]>
>=20
> Introduce a way to provide a guest GPA as the initial BSP VMSA and
> avoid allocating KVM-managed VMSAs in this case. Only one
> guest-provided VMSA is supported at the moment as IGVM also only

No.  Design uAPI that makes sense for KVM and is extensible.  If it turns o=
ut
that allowing exactly one VMSA is the simplest, most logical approach, then=
 so
be it.  But "thing X only needs Y" isn't sufficient justification.

But I'm not remotely convinced that hacking in BSP-only support like this i=
s
the way to go.  This entire approach is convoluted, as is the code.  E.g. t=
he
below iterates over all vCPUs, but then only actually does anything for vcp=
u_idx=3D0.
And the ioctl is VM-scoped, but really operates on a vCPU.

At a (very rough) glance, I don't see any reason we can't have a vCPU-scope=
d
ioctl to effectively mimic SVM_VMGEXIT_AP_CREATE.

> supports to set a single VMSA.
>=20
> Signed-off-by: Joerg Roedel <[email protected]>
> ---
>  arch/x86/kvm/svm/sev.c | 62 ++++++++++++++++++++++++++++++------------
>  arch/x86/kvm/svm/svm.h |  1 +
>  2 files changed, 45 insertions(+), 18 deletions(-)
>=20
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 350bb97c32c0..88db83b3ff8e 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -726,6 +726,7 @@ static int __sev_guest_init(struct kvm *kvm, struct k=
vm_sev_cmd *argp,
> =20
>  	INIT_LIST_HEAD(&sev->regions_list);
>  	INIT_LIST_HEAD(&sev->mirror_vms);
> +	sev->initial_vmsa_gpa =3D INVALID_PAGE;
>  	sev->need_init =3D false;
> =20
>  	kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_SEV);
> @@ -2680,6 +2681,46 @@ static int snp_launch_update(struct kvm *kvm, stru=
ct kvm_sev_cmd *argp)
>  	return 0;
>  }
> =20
> +static int snp_init_guest_vmsa(struct kvm_vcpu *vcpu, gpa_t vmsa_gpa)
> +{
> +	/* Only one initial guest VMSA can exist (per IGVM) - so it belongs to =
the BSP */
> +	if (vcpu->vcpu_idx !=3D 0)
> +		return 0;
> +
> +	/* VMSA already private and encrypted via LAUNCH_UPDATE */
> +	sev_es_set_guest_vmsa(vcpu, vmsa_gpa);
> +
> +	return 0;
> +}
> +
> +static int snp_init_kvm_vmsa(struct kvm_vcpu *vcpu,
> +			     struct sev_data_snp_launch_update *data,
> +			     struct kvm_sev_cmd *argp)
> +{
> +	struct vcpu_svm *svm =3D to_svm(vcpu);
> +	int ret;
> +	void *vmsa;
> +
> +	ret =3D sev_es_sync_vmsa(svm);
> +	if (ret)
> +		return ret;
> +
> +	vmsa =3D sev_es_vmsa_ref(vcpu);
> +
> +	ret =3D sev_es_vcpu_vmsa_make_private(vcpu);
> +	if (ret)
> +		return ret;
> +
> +	/* Issue the SNP command to encrypt the VMSA */
> +	data->address =3D __sme_pa(vmsa);
> +	ret =3D __sev_issue_cmd(argp->sev_fd, SEV_CMD_SNP_LAUNCH_UPDATE,
> +			      data, &argp->error);
> +	if (ret)
> +		sev_snp_vcpu_reclaim_vmsa(vcpu);
> +
> +	return ret;

Separate code movement from new functi0onality.

> +}
> +
>  static int snp_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *a=
rgp)
>  {
>  	struct kvm_sev_info *sev =3D to_kvm_sev_info(kvm);
> @@ -2700,28 +2741,13 @@ static int snp_launch_update_vmsa(struct kvm *kvm=
, struct kvm_sev_cmd *argp)
> =20
>  	kvm_for_each_vcpu(i, vcpu, kvm) {
>  		struct vcpu_svm *svm =3D to_svm(vcpu);
> -		void *vmsa;
> =20
> -		ret =3D sev_es_sync_vmsa(svm);
> +		ret =3D VALID_PAGE(sev->initial_vmsa_gpa) ?
> +			snp_init_guest_vmsa(vcpu, sev->initial_vmsa_gpa) :
> +			snp_init_kvm_vmsa(vcpu, &data, argp);
>  		if (ret)
>  			goto out;
> =20
> -		vmsa =3D sev_es_vmsa_ref(vcpu);
> -
> -		ret =3D sev_es_vcpu_vmsa_make_private(vcpu);
> -		if (ret)
> -			goto out;
> -
> -		/* Issue the SNP command to encrypt the VMSA */
> -		data.address =3D __sme_pa(vmsa);
> -		ret =3D __sev_issue_cmd(argp->sev_fd, SEV_CMD_SNP_LAUNCH_UPDATE,
> -				      &data, &argp->error);
> -		if (ret) {
> -			sev_snp_vcpu_reclaim_vmsa(vcpu);
> -
> -			goto out;
> -		}
> -
>  		svm->vcpu.arch.guest_state_protected =3D true;
> =20
>  		/* VMSA encrypted - put it into the VMCB */
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index 3d4799f09b23..cc7e84c230bb 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -117,6 +117,7 @@ struct kvm_sev_info {
>  	struct mutex guest_req_mutex; /* Must acquire before using bounce buffe=
rs */
>  	cpumask_var_t have_run_cpus; /* CPUs that have done VMRUN for this VM. =
*/
>  	bool snp_certs_enabled;	/* SNP certificate-fetching support. */
> +	gpa_t initial_vmsa_gpa; /* Optinal GPA of BSP VMSA - SEV-SNP only */
>  };
>  #endif
> =20
> --=20
> 2.53.0
>=20