]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: SVM: Don't change target vCPU state on AP Creation VMGEXIT error
authorSean Christopherson <seanjc@google.com>
Thu, 27 Feb 2025 01:25:35 +0000 (17:25 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Apr 2025 12:39:38 +0000 (14:39 +0200)
commit d26638bfcdfc5c8c4e085dc3f5976a0443abab3c upstream.

If KVM rejects an AP Creation event, leave the target vCPU state as-is.
Nothing in the GHCB suggests the hypervisor is *allowed* to muck with vCPU
state on failure, let alone required to do so.  Furthermore, kicking only
in the !ON_INIT case leads to divergent behavior, and even the "kick" case
is non-deterministic.

E.g. if an ON_INIT request fails, the guest can successfully retry if the
fixed AP Creation request is made prior to sending INIT.  And if a !ON_INIT
fails, the guest can successfully retry if the fixed AP Creation request is
handled before the target vCPU processes KVM's
KVM_REQ_UPDATE_PROTECTED_GUEST_STATE.

Fixes: e366f92ea99e ("KVM: SEV: Support SEV-SNP AP Creation NAE event")
Cc: stable@vger.kernel.org
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: Pankaj Gupta <pankaj.gupta@amd.com>
Link: https://lore.kernel.org/r/20250227012541.3234589-5-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/kvm/svm/sev.c

index 3ec56bf76ef16451aefad5e2d53c873e53c13190..6154cb450b448b4276b1cc18f9093ae62adbbefd 100644 (file)
@@ -3957,16 +3957,12 @@ static int sev_snp_ap_creation(struct vcpu_svm *svm)
 
        /*
         * The target vCPU is valid, so the vCPU will be kicked unless the
-        * request is for CREATE_ON_INIT. For any errors at this stage, the
-        * kick will place the vCPU in an non-runnable state.
+        * request is for CREATE_ON_INIT.
         */
        kick = true;
 
        mutex_lock(&target_svm->sev_es.snp_vmsa_mutex);
 
-       target_svm->sev_es.snp_vmsa_gpa = INVALID_PAGE;
-       target_svm->sev_es.snp_ap_waiting_for_reset = true;
-
        /* Interrupt injection mode shouldn't change for AP creation */
        if (request < SVM_VMGEXIT_AP_DESTROY) {
                u64 sev_features;
@@ -4012,20 +4008,23 @@ static int sev_snp_ap_creation(struct vcpu_svm *svm)
                target_svm->sev_es.snp_vmsa_gpa = svm->vmcb->control.exit_info_2;
                break;
        case SVM_VMGEXIT_AP_DESTROY:
+               target_svm->sev_es.snp_vmsa_gpa = INVALID_PAGE;
                break;
        default:
                vcpu_unimpl(vcpu, "vmgexit: invalid AP creation request [%#x] from guest\n",
                            request);
                ret = -EINVAL;
-               break;
+               goto out;
        }
 
-out:
+       target_svm->sev_es.snp_ap_waiting_for_reset = true;
+
        if (kick) {
                kvm_make_request(KVM_REQ_UPDATE_PROTECTED_GUEST_STATE, target_vcpu);
                kvm_vcpu_kick(target_vcpu);
        }
 
+out:
        mutex_unlock(&target_svm->sev_es.snp_vmsa_mutex);
 
        return ret;