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;
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)
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);
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));