]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: SEV: Move GHCB "usage" check out of sev_es_validate_vmgexit()
authorSean Christopherson <seanjc@google.com>
Fri, 29 May 2026 18:35:44 +0000 (20:35 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 3 Jun 2026 14:59:19 +0000 (16:59 +0200)
Move the check to verify the guest's requested GHCB out of
sev_es_validate_vmgexit() as the first step towards making said helper a
predicate whose sole purpose is to verify the guest has marked required
GHCB fields as valid.

Using a single "validate" helper sounds good on paper, but in practice it's
difficult to verify that KVM is performing the necessary sanity checks (the
usage of state is far removed from the relevant checks), makes it difficult
to understand that "legacy" exits are simply routed to KVM's existing exit
handlers, and most importantly, has directly contributed to a number of
bugs as adding case-statements to the validation subtly removes them from
the default path that rejects unknown exit codes with INVALID_EVENT.

Deliberately extract the usage code check first so as to preserve the order
of KVM's checks, even though future code extraction will technically fix
bugs.

No functional change intended.

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-20-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-ID: <20260529183549.1104619-20-pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/svm/sev.c

index 7c2ebc81306f2547c8f269028bacbba316035a80..880a2acd77bffead19d16c7d07bcdd71636ab94b 100644 (file)
@@ -3416,12 +3416,6 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
        struct kvm_vcpu *vcpu = &svm->vcpu;
        u64 reason;
 
-       /* Only GHCB Usage code 0 is supported */
-       if (svm->sev_es.ghcb->ghcb_usage) {
-               reason = GHCB_ERR_INVALID_USAGE;
-               goto vmgexit_err;
-       }
-
        reason = GHCB_ERR_MISSING_INPUT;
 
        if (!kvm_ghcb_sw_exit_code_is_valid(svm) ||
@@ -3534,10 +3528,7 @@ vmgexit_err:
         * Print the exit code even though it may not be marked valid as it
         * could help with debugging.
         */
-       if (reason == GHCB_ERR_INVALID_USAGE) {
-               vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n",
-                           svm->sev_es.ghcb->ghcb_usage);
-       } else if (reason == GHCB_ERR_INVALID_EVENT) {
+       if (reason == GHCB_ERR_INVALID_EVENT) {
                vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n",
                            control->exit_code);
        } else {
@@ -4528,6 +4519,14 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
                return 1;
        }
 
+       /* Only GHCB Usage code 0 is supported */
+       if (svm->sev_es.ghcb->ghcb_usage) {
+               vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n",
+                           svm->sev_es.ghcb->ghcb_usage);
+               svm_vmgexit_bad_input(svm, GHCB_ERR_INVALID_USAGE);
+               return 1;
+       }
+
        ret = sev_es_validate_vmgexit(svm);
        if (ret)
                return ret;