[PATCH 2/4] kvm: svm: Defer VMSA allocation to LAUNCH_FINISH stage
Jörg Rödel <[email protected]> Thu, 11 Jun 2026 14:35:26 +0200
| Newsgroups | dev.linux.lists.coconut-svsm,org.kernel.vger.kvm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Joerg Roedel <[email protected]> Do not allocate a KVM-managed VMSA for all VCPUs on VCPU creation, defer it to the LAUNCH_FINISH stage of SEV-ES and SEV-SNP. At this stage the VMSAs get used for the first time. Signed-off-by: Joerg Roedel <[email protected]> --- arch/x86/kvm/svm/sev.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 9b1280222e20..350bb97c32c0 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -1095,11 +1095,11 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm) { struct kvm_vcpu *vcpu = &svm->vcpu; struct kvm_sev_info *sev = to_kvm_sev_info(vcpu->kvm); - struct sev_es_save_area *save = sev_es_vmsa_ref(vcpu); + struct sev_es_save_area *save; struct xregs_state *xsave; const u8 *s; + int ret, i; u8 *d; - int i; lockdep_assert_held(&vcpu->mutex); @@ -1110,6 +1110,12 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm) if (svm->vcpu.guest_debug || (svm->vmcb->save.dr7 & ~DR7_FIXED_1)) return -EINVAL; + ret = sev_es_vcpu_alloc_vmsa(vcpu); + if (ret) + return ret; + + save = sev_es_vmsa_ref(vcpu); + /* * SEV-ES will use a VMSA that is pointed to by the VMCB, not * the traditional VMSA that is part of the VMCB. Copy the @@ -1196,7 +1202,7 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu, { struct sev_data_launch_update_vmsa vmsa; struct vcpu_svm *svm = to_svm(vcpu); - void *vmsa_ref = sev_es_vmsa_ref(vcpu); + void *vmsa_ref; int ret; if (vcpu->guest_debug) { @@ -1209,6 +1215,8 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu, if (ret) return ret; + vmsa_ref = sev_es_vmsa_ref(vcpu); + /* * The LAUNCH_UPDATE_VMSA command will perform in-place encryption of * the VMSA memory content (i.e it will write the same memory region @@ -1237,6 +1245,9 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu, fpstate_set_confidential(&vcpu->arch.guest_fpu); vcpu->arch.guest_state_protected = true; + /* VMSA encrypted - put it into the VMCB */ + svm->vmcb->control.vmsa_pa = sev_es_vmsa_pa(vcpu); + /* * SEV-ES guest mandates LBR Virtualization to be _always_ ON. Enable it * only after setting guest_state_protected because KVM_SET_MSRS allows @@ -2689,12 +2700,14 @@ 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 = sev_es_vmsa_ref(vcpu); + void *vmsa; ret = sev_es_sync_vmsa(svm); if (ret) goto out; + vmsa = sev_es_vmsa_ref(vcpu); + ret = sev_es_vcpu_vmsa_make_private(vcpu); if (ret) goto out; @@ -2710,6 +2723,10 @@ static int snp_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp) } svm->vcpu.arch.guest_state_protected = true; + + /* VMSA encrypted - put it into the VMCB */ + svm->vmcb->control.vmsa_pa = sev_es_vmsa_pa(vcpu); + /* * SEV-ES (and thus SNP) guest mandates LBR Virtualization to * be _always_ ON. Enable it only after setting @@ -4914,22 +4931,11 @@ void sev_init_vmcb(struct vcpu_svm *svm, bool init_event) int sev_vcpu_create(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); - int ret; mutex_init(&svm->sev_es.snp_vmsa_mutex); - if (!is_sev_es_guest(vcpu)) - return 0; - - /* - * SEV-ES guests require a separate (from the VMCB) VMSA page used to - * contain the encrypted register state of the guest. - */ - ret = sev_es_vcpu_alloc_vmsa(vcpu); - if (ret) - return ret; - - vcpu->arch.guest_tsc_protected = snp_is_secure_tsc_enabled(vcpu->kvm); + if (is_sev_es_guest(vcpu)) + vcpu->arch.guest_tsc_protected = snp_is_secure_tsc_enabled(vcpu->kvm); return 0; } -- 2.53.0