]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: SEV: Unmap and unpin the GHCB as needed on vCPU free
authorSean Christopherson <seanjc@google.com>
Fri, 29 May 2026 18:35:42 +0000 (20:35 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 3 Jun 2026 14:43:56 +0000 (16:43 +0200)
Unmap and unpin the GHCB as needed when freeing a vCPU.  If the VM is
destroyed after mapping+pinning the GHCB on #VMGEXIT, without re-running
the vCPU, KVM will effectively leak the GHCB and any mappings created for
the GHCB.

Fixes: 291bd20d5d88 ("KVM: SVM: Add initial support for a VMGEXIT VMEXIT")
Cc: stable@vger.kernel.org
Tested-by: Michael Roth <michael.roth@amd.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-ID: <20260501202250.2115252-18-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-ID: <20260529183549.1104619-18-pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/svm/sev.c

index 11d46600cbdc0bf2459ae7e9be14153138920e40..6c6a6d663e29638ac8cd0f5da64fc1a3b1e221f4 100644 (file)
@@ -3552,6 +3552,20 @@ vmgexit_err:
        return 1;
 }
 
+static void __sev_es_unmap_ghcb(struct vcpu_svm *svm)
+{
+       if (svm->sev_es.ghcb_sa_free) {
+               kvfree(svm->sev_es.ghcb_sa);
+               svm->sev_es.ghcb_sa = NULL;
+               svm->sev_es.ghcb_sa_free = false;
+       }
+
+       if (svm->sev_es.ghcb) {
+               kvm_vcpu_unmap(&svm->vcpu, &svm->sev_es.ghcb_map);
+               svm->sev_es.ghcb = NULL;
+       }
+}
+
 void sev_es_unmap_ghcb(struct vcpu_svm *svm)
 {
        /* Clear any indication that the vCPU is in a type of AP Reset Hold */
@@ -3570,18 +3584,11 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
                svm->sev_es.ghcb_sa_sync = false;
        }
 
-       if (svm->sev_es.ghcb_sa_free) {
-               kvfree(svm->sev_es.ghcb_sa);
-               svm->sev_es.ghcb_sa = NULL;
-               svm->sev_es.ghcb_sa_free = false;
-       }
-
        trace_kvm_vmgexit_exit(svm->vcpu.vcpu_id, svm->sev_es.ghcb);
 
        sev_es_sync_to_ghcb(svm);
 
-       kvm_vcpu_unmap(&svm->vcpu, &svm->sev_es.ghcb_map);
-       svm->sev_es.ghcb = NULL;
+       __sev_es_unmap_ghcb(svm);
 }
 
 void sev_free_vcpu(struct kvm_vcpu *vcpu)
@@ -3611,8 +3618,7 @@ void sev_free_vcpu(struct kvm_vcpu *vcpu)
        __free_page(virt_to_page(svm->sev_es.vmsa));
 
 skip_vmsa_free:
-       if (svm->sev_es.ghcb_sa_free)
-               kvfree(svm->sev_es.ghcb_sa);
+       __sev_es_unmap_ghcb(svm);
 }
 
 int pre_sev_run(struct vcpu_svm *svm, int cpu)