KVM: SEV: Turn sev_es_validate_vmgexit() into a dedicated predicate

Now that sev_es_validate_vmgexit() is only responsible for checking that
all required GHCB fields are marked valid, turn it into a predicate whose
name reflects exactly that.

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-24-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-ID: <20260529183549.1104619-24-pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Sean Christopherson
2026-05-29 20:35:48 +02:00
committed by Paolo Bonzini
parent b911484177
commit abb97ac118

View File

@@ -3410,7 +3410,7 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm)
memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap));
}
static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
static bool sev_es_are_required_ghcb_fields_valid(struct vcpu_svm *svm)
{
struct vmcb_control_area *control = &svm->vmcb->control;
struct kvm_vcpu *vcpu = &svm->vcpu;
@@ -3418,92 +3418,53 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
if (!kvm_ghcb_sw_exit_code_is_valid(svm) ||
!kvm_ghcb_sw_exit_info_1_is_valid(svm) ||
!kvm_ghcb_sw_exit_info_2_is_valid(svm))
goto vmgexit_err;
return false;
switch (control->exit_code) {
case SVM_EXIT_WRITE_DR7:
if (!kvm_ghcb_rax_is_valid(svm))
goto vmgexit_err;
break;
return kvm_ghcb_rax_is_valid(svm);
case SVM_EXIT_RDPMC:
if (!kvm_ghcb_rcx_is_valid(svm))
goto vmgexit_err;
break;
return kvm_ghcb_rcx_is_valid(svm);
case SVM_EXIT_CPUID:
if (!kvm_ghcb_rax_is_valid(svm) ||
!kvm_ghcb_rcx_is_valid(svm))
goto vmgexit_err;
if (vcpu->arch.regs[VCPU_REGS_RAX] == 0xd)
if (!kvm_ghcb_xcr0_is_valid(svm))
goto vmgexit_err;
break;
return false;
return vcpu->arch.regs[VCPU_REGS_RAX] != 0xd ||
kvm_ghcb_xcr0_is_valid(svm);
case SVM_EXIT_IOIO:
if (control->exit_info_1 & SVM_IOIO_STR_MASK) {
if (!kvm_ghcb_sw_scratch_is_valid(svm))
goto vmgexit_err;
} else {
if (!(control->exit_info_1 & SVM_IOIO_TYPE_MASK))
if (!kvm_ghcb_rax_is_valid(svm))
goto vmgexit_err;
}
break;
if (control->exit_info_1 & SVM_IOIO_STR_MASK)
return kvm_ghcb_sw_scratch_is_valid(svm);
if (!(control->exit_info_1 & SVM_IOIO_TYPE_MASK))
return kvm_ghcb_rax_is_valid(svm);
return true;
case SVM_EXIT_MSR:
if (!kvm_ghcb_rcx_is_valid(svm))
goto vmgexit_err;
if (control->exit_info_1) {
if (!kvm_ghcb_rax_is_valid(svm) ||
!kvm_ghcb_rdx_is_valid(svm))
goto vmgexit_err;
}
break;
return false;
return !control->exit_info_1 ||
(kvm_ghcb_rax_is_valid(svm) && kvm_ghcb_rdx_is_valid(svm));
case SVM_EXIT_VMMCALL:
if (!kvm_ghcb_rax_is_valid(svm) ||
!kvm_ghcb_cpl_is_valid(svm))
goto vmgexit_err;
break;
return kvm_ghcb_rax_is_valid(svm) && kvm_ghcb_cpl_is_valid(svm);
case SVM_EXIT_MONITOR:
if (!kvm_ghcb_rax_is_valid(svm) ||
!kvm_ghcb_rcx_is_valid(svm) ||
!kvm_ghcb_rdx_is_valid(svm))
goto vmgexit_err;
break;
return kvm_ghcb_rax_is_valid(svm) &&
kvm_ghcb_rcx_is_valid(svm) &&
kvm_ghcb_rdx_is_valid(svm);
case SVM_EXIT_MWAIT:
if (!kvm_ghcb_rax_is_valid(svm) ||
!kvm_ghcb_rcx_is_valid(svm))
goto vmgexit_err;
return kvm_ghcb_rax_is_valid(svm) && kvm_ghcb_rcx_is_valid(svm);
case SVM_VMGEXIT_AP_CREATION:
return kvm_ghcb_rax_is_valid(svm) ||
lower_32_bits(control->exit_info_1) == SVM_VMGEXIT_AP_DESTROY;
break;
case SVM_VMGEXIT_MMIO_READ:
case SVM_VMGEXIT_MMIO_WRITE:
if (!kvm_ghcb_sw_scratch_is_valid(svm))
goto vmgexit_err;
break;
case SVM_VMGEXIT_AP_CREATION:
if (lower_32_bits(control->exit_info_1) != SVM_VMGEXIT_AP_DESTROY)
if (!kvm_ghcb_rax_is_valid(svm))
goto vmgexit_err;
break;
case SVM_VMGEXIT_PSC:
if (!kvm_ghcb_sw_scratch_is_valid(svm))
goto vmgexit_err;
break;
return kvm_ghcb_sw_scratch_is_valid(svm);
default:
break;
return true;
}
return 0;
vmgexit_err:
/*
* Print the exit code even though it may not be marked valid as it
* could help with debugging.
*/
vcpu_unimpl(vcpu, "vmgexit: exit code %#llx input is not valid\n",
control->exit_code);
dump_ghcb(svm);
svm_vmgexit_bad_input(svm, GHCB_ERR_MISSING_INPUT);
/* Resume the guest to "return" the error code. */
return 1;
}
static void __sev_es_unmap_ghcb(struct vcpu_svm *svm)
@@ -4510,9 +4471,17 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
return 1;
}
ret = sev_es_validate_vmgexit(svm);
if (ret)
return ret;
if (!sev_es_are_required_ghcb_fields_valid(svm)) {
/*
* Print the exit code even though it may not be marked valid
* as it could help with debugging.
*/
vcpu_unimpl(vcpu, "vmgexit: exit code %#llx input is not valid\n",
control->exit_code);
dump_ghcb(svm);
svm_vmgexit_bad_input(svm, GHCB_ERR_MISSING_INPUT);
return 1;
}
svm_vmgexit_success(svm, 0);
@@ -4599,6 +4568,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
vcpu->run->system_event.type = KVM_SYSTEM_EVENT_SEV_TERM;
vcpu->run->system_event.ndata = 1;
vcpu->run->system_event.data[0] = control->ghcb_gpa;
ret = 0;
break;
case SVM_VMGEXIT_PSC:
ret = setup_vmgexit_scratch(svm, true, sizeof(struct psc_hdr));