Re: [PATCH 3/4] kvm: svm: Support guest-provided VMSA for launching
From: Sean Christopherson
Date: Tue Jun 23 2026 - 17:08:22 EST
On Thu, Jun 11, 2026, Jörg Rödel wrote:
> From: Joerg Roedel <joerg.roedel@xxxxxxx>
>
> 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 out
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 is
the way to go. This entire approach is convoluted, as is the code. E.g. the
below iterates over all vCPUs, but then only actually does anything for vcpu_idx=0.
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-scoped
ioctl to effectively mimic SVM_VMGEXIT_AP_CREATE.
> supports to set a single VMSA.
>
> Signed-off-by: Joerg Roedel <joerg.roedel@xxxxxxx>
> ---
> arch/x86/kvm/svm/sev.c | 62 ++++++++++++++++++++++++++++++------------
> arch/x86/kvm/svm/svm.h | 1 +
> 2 files changed, 45 insertions(+), 18 deletions(-)
>
> 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 kvm_sev_cmd *argp,
>
> INIT_LIST_HEAD(&sev->regions_list);
> INIT_LIST_HEAD(&sev->mirror_vms);
> + sev->initial_vmsa_gpa = INVALID_PAGE;
> sev->need_init = false;
>
> kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_SEV);
> @@ -2680,6 +2681,46 @@ static int snp_launch_update(struct kvm *kvm, struct kvm_sev_cmd *argp)
> return 0;
> }
>
> +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 != 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 = to_svm(vcpu);
> + int ret;
> + void *vmsa;
> +
> + ret = sev_es_sync_vmsa(svm);
> + if (ret)
> + return ret;
> +
> + vmsa = sev_es_vmsa_ref(vcpu);
> +
> + ret = sev_es_vcpu_vmsa_make_private(vcpu);
> + if (ret)
> + return ret;
> +
> + /* Issue the SNP command to encrypt the VMSA */
> + data->address = __sme_pa(vmsa);
> + ret = __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 *argp)
> {
> struct kvm_sev_info *sev = to_kvm_sev_info(kvm);
> @@ -2700,28 +2741,13 @@ static int snp_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp)
>
> kvm_for_each_vcpu(i, vcpu, kvm) {
> struct vcpu_svm *svm = to_svm(vcpu);
> - void *vmsa;
>
> - ret = sev_es_sync_vmsa(svm);
> + ret = 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;
>
> - vmsa = sev_es_vmsa_ref(vcpu);
> -
> - ret = sev_es_vcpu_vmsa_make_private(vcpu);
> - if (ret)
> - goto out;
> -
> - /* Issue the SNP command to encrypt the VMSA */
> - data.address = __sme_pa(vmsa);
> - ret = __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 = true;
>
> /* 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 buffers */
> 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
>
> --
> 2.53.0
>