]> git.ipfire.org Git - thirdparty/kernel/linux.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)
committerSean Christopherson <seanjc@google.com>
Mon, 3 Mar 2025 15:33:44 +0000 (07:33 -0800)
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>
arch/x86/kvm/svm/sev.c

index 5325de9c66ce435af95a83e2724398ff34c9a6c7..2b76957209e68d484b1aec57e15d765359f9193d 100644 (file)
@@ -3963,16 +3963,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;
@@ -4018,20 +4014,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;