Re: [PATCH v3 01/12] KVM: SEV: Track the GPA of the guest-controlled VMSA used for SNP guests

From: Michael Roth

Date: Wed Jul 01 2026 - 18:50:28 EST


On Tue, Jun 30, 2026 at 03:25:56PM -0700, Sean Christopherson wrote:
> Track the GPA of the guest-provided VMSA used after AP_CREATION events when
> running SNP guests, instead of simply tracking whether or not the vCPU is
> using a guest-provided VMSA. KVM needs to know the GPA of the VMSA that's
> actively being used so that it can react to MMU invalidation events, i.e.
> so that KVM can drop the VMSA if its backing guest_memfd page is punched
> out of existence.
>
> Opportunistically rename snp_vmsa_gpa to clarify that it tracks the pending
> VMSA GPA, whereas snp_guest_vmsa_gpa now tracks the in-use VMSA GPA.
>
> Note! Take care to track the GPA, not the GFN, as VALID_PAGE() won't
> behave correctly if an invalid GFN is converted to a GPA for checking.
>
> Note #2! Keep snp_has_guest_vmsa so that switching to a guest-provided
> VMSA is sticky, even if the guest-provided VMSA becomes invalid.
>
> No functional change intended.
>
> Cc: stable@xxxxxxxxxxxxxxx # 6.12.x
> Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>

Reviewed-by: Michael Roth <michael.roth@xxxxxxx>

> ---
> arch/x86/kvm/svm/sev.c | 14 +++++++++-----
> arch/x86/kvm/svm/svm.h | 3 ++-
> 2 files changed, 11 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 74fb15551e83..827f5dc06102 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -4003,6 +4003,7 @@ static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)
>
> /* Clear use of the VMSA */
> svm->vmcb->control.vmsa_pa = INVALID_PAGE;
> + svm->sev_es.snp_guest_vmsa_gpa = INVALID_PAGE;
>
> /*
> * When replacing the VMSA during SEV-SNP AP creation,
> @@ -4010,11 +4011,11 @@ static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)
> */
> vmcb_mark_all_dirty(svm->vmcb);
>
> - if (!VALID_PAGE(svm->sev_es.snp_vmsa_gpa))
> + if (!VALID_PAGE(svm->sev_es.snp_pending_vmsa_gpa))
> return;
>
> - gfn = gpa_to_gfn(svm->sev_es.snp_vmsa_gpa);
> - svm->sev_es.snp_vmsa_gpa = INVALID_PAGE;
> + gfn = gpa_to_gfn(svm->sev_es.snp_pending_vmsa_gpa);
> + svm->sev_es.snp_pending_vmsa_gpa = INVALID_PAGE;
>
> slot = gfn_to_memslot(vcpu->kvm, gfn);
> if (!slot)
> @@ -4039,6 +4040,7 @@ static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)
> svm->sev_es.snp_has_guest_vmsa = true;
>
> /* Use the new VMSA */
> + svm->sev_es.snp_guest_vmsa_gpa = gfn_to_gpa(gfn);
> svm->vmcb->control.vmsa_pa = pfn_to_hpa(pfn);
>
> /* Mark the vCPU as runnable */
> @@ -4105,10 +4107,10 @@ static int sev_snp_ap_creation(struct vcpu_svm *svm)
> return -EINVAL;
> }
>
> - target_svm->sev_es.snp_vmsa_gpa = svm->vmcb->control.exit_info_2;
> + target_svm->sev_es.snp_pending_vmsa_gpa = svm->vmcb->control.exit_info_2;
> break;
> case SVM_VMGEXIT_AP_DESTROY:
> - target_svm->sev_es.snp_vmsa_gpa = INVALID_PAGE;
> + target_svm->sev_es.snp_pending_vmsa_gpa = INVALID_PAGE;
> break;
> default:
> vcpu_unimpl(vcpu, "vmgexit: invalid AP creation request [%#x] from guest\n",
> @@ -4791,6 +4793,8 @@ int sev_vcpu_create(struct kvm_vcpu *vcpu)
> return -ENOMEM;
>
> svm->sev_es.vmsa = page_address(vmsa_page);
> + svm->sev_es.snp_pending_vmsa_gpa = INVALID_PAGE;
> + svm->sev_es.snp_guest_vmsa_gpa = INVALID_PAGE;
>
> vcpu->arch.guest_tsc_protected = snp_is_secure_tsc_enabled(vcpu->kvm);
>
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index 716be21fba33..d077783c287e 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -271,7 +271,8 @@ struct vcpu_sev_es_state {
> u64 ghcb_registered_gpa;
>
> struct mutex snp_vmsa_mutex; /* Used to handle concurrent updates of VMSA. */
> - gpa_t snp_vmsa_gpa;
> + gpa_t snp_pending_vmsa_gpa;
> + gpa_t snp_guest_vmsa_gpa;
> bool snp_ap_waiting_for_reset;
> bool snp_has_guest_vmsa;
> };
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>