From: Sean Christopherson Date: Fri, 29 May 2026 18:35:47 +0000 (+0200) Subject: KVM: SEV: Handle unknown #VMGEXIT reasons in sev_handle_vmgexit() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9114841777021ddc3b975c05fd5998a47b44587;p=thirdparty%2Fkernel%2Flinux.git KVM: SEV: Handle unknown #VMGEXIT reasons in sev_handle_vmgexit() Handle unknown #VMGEXIT reasons in sev_handle_vmgexit(), not in sev_es_validate_vmgexit(). This makes it _much_ more obvious that KVM simply funnels "legacy" exits to the standard SVM interception handlers, and is the final preparatory change needed to reduce the scope of sev_es_validate_vmgexit(). No functional change intended. Reviewed-by: Tom Lendacky Signed-off-by: Sean Christopherson Message-ID: <20260501202250.2115252-23-seanjc@google.com> Signed-off-by: Paolo Bonzini Message-ID: <20260529183549.1104619-23-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 84421d9a116b..864d6aea544b 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -3414,9 +3414,6 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) { struct vmcb_control_area *control = &svm->vmcb->control; struct kvm_vcpu *vcpu = &svm->vcpu; - u64 reason; - - reason = GHCB_ERR_MISSING_INPUT; if (!kvm_ghcb_sw_exit_code_is_valid(svm) || !kvm_ghcb_sw_exit_info_1_is_valid(svm) || @@ -3424,14 +3421,10 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) goto vmgexit_err; switch (control->exit_code) { - case SVM_EXIT_READ_DR7: - break; case SVM_EXIT_WRITE_DR7: if (!kvm_ghcb_rax_is_valid(svm)) goto vmgexit_err; break; - case SVM_EXIT_RDTSC: - break; case SVM_EXIT_RDPMC: if (!kvm_ghcb_rcx_is_valid(svm)) goto vmgexit_err; @@ -3444,8 +3437,6 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) if (!kvm_ghcb_xcr0_is_valid(svm)) goto vmgexit_err; break; - case SVM_EXIT_INVD: - break; case SVM_EXIT_IOIO: if (control->exit_info_1 & SVM_IOIO_STR_MASK) { if (!kvm_ghcb_sw_scratch_is_valid(svm)) @@ -3470,10 +3461,6 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) !kvm_ghcb_cpl_is_valid(svm)) goto vmgexit_err; break; - case SVM_EXIT_RDTSCP: - break; - case SVM_EXIT_WBINVD: - break; case SVM_EXIT_MONITOR: if (!kvm_ghcb_rax_is_valid(svm) || !kvm_ghcb_rcx_is_valid(svm) || @@ -3495,23 +3482,12 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) if (!kvm_ghcb_rax_is_valid(svm)) goto vmgexit_err; break; - case SVM_VMGEXIT_NMI_COMPLETE: - case SVM_VMGEXIT_AP_HLT_LOOP: - case SVM_VMGEXIT_AP_JUMP_TABLE: - case SVM_VMGEXIT_UNSUPPORTED_EVENT: - case SVM_VMGEXIT_HV_FEATURES: - case SVM_VMGEXIT_TERM_REQUEST: - break; case SVM_VMGEXIT_PSC: if (!kvm_ghcb_sw_scratch_is_valid(svm)) goto vmgexit_err; break; - case SVM_VMGEXIT_GUEST_REQUEST: - case SVM_VMGEXIT_EXT_GUEST_REQUEST: - break; default: - reason = GHCB_ERR_INVALID_EVENT; - goto vmgexit_err; + break; } return 0; @@ -3521,16 +3497,10 @@ 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_EVENT) { - vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n", - control->exit_code); - } else { - vcpu_unimpl(vcpu, "vmgexit: exit code %#llx input is not valid\n", - control->exit_code); - dump_ghcb(svm); - } - - svm_vmgexit_bad_input(svm, reason); + 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; @@ -4547,6 +4517,25 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) svm_vmgexit_success(svm, 0); switch (control->exit_code) { + case SVM_EXIT_IOIO: + if (!((control->exit_info_1 & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT)) + return 1; + + fallthrough; + case SVM_EXIT_READ_DR7: + case SVM_EXIT_WRITE_DR7: + case SVM_EXIT_RDTSC: + case SVM_EXIT_RDTSCP: + case SVM_EXIT_RDPMC: + case SVM_EXIT_CPUID: + case SVM_EXIT_INVD: + case SVM_EXIT_MSR: + case SVM_EXIT_VMMCALL: + case SVM_EXIT_WBINVD: + case SVM_EXIT_MONITOR: + case SVM_EXIT_MWAIT: + ret = svm_invoke_exit_handler(vcpu, control->exit_code); + break; case SVM_VMGEXIT_MMIO_READ: case SVM_VMGEXIT_MMIO_WRITE: { bool is_write = control->exit_code == SVM_VMGEXIT_MMIO_WRITE; @@ -4643,18 +4632,21 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) control->exit_info_2); break; case SVM_VMGEXIT_UNSUPPORTED_EVENT: + /* + * Note, the _guest_ is reporting an unsupported #VC, i.e. this + * isn't the same thing as KVM getting an unsupported #VMGEXIT. + */ vcpu_unimpl(vcpu, "vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n", control->exit_info_1, control->exit_info_2); ret = -EINVAL; break; - case SVM_EXIT_IOIO: - if (!((control->exit_info_1 & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT)) - return 1; - - fallthrough; default: - ret = svm_invoke_exit_handler(vcpu, control->exit_code); + vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n", + control->exit_code); + svm_vmgexit_bad_input(svm, GHCB_ERR_INVALID_EVENT); + ret = 1; + break; } return ret;