Commit 11c98fa0 authored by Ivan Orlov's avatar Ivan Orlov Committed by Sean Christopherson
Browse files

KVM: x86: Add function for vectoring error generation



Extract VMX code for unhandleable VM-Exit during vectoring into
vendor-agnostic function so that boiler-plate code can be shared by SVM.

To avoid unnecessarily complexity in the helper, unconditionally report a
GPA to userspace instead of having a conditional entry.  For exits that
don't report a GPA, i.e. everything except EPT Misconfig, simply report
KVM's "invalid GPA".

Signed-off-by: default avatarIvan Orlov <iorlov@amazon.com>
Link: https://lore.kernel.org/r/20241217181458.68690-2-iorlov@amazon.com


[sean: clarify that the INVALID_GPA logic is new]
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
parent 871ac338
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2075,6 +2075,8 @@ void __kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu,
					  u64 *data, u8 ndata);
void kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu);

void kvm_prepare_event_vectoring_exit(struct kvm_vcpu *vcpu, gpa_t gpa);

void kvm_enable_efer_bits(u64);
bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer);
int kvm_get_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 *data);
+5 −12
Original line number Diff line number Diff line
@@ -6554,19 +6554,12 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
	     exit_reason.basic != EXIT_REASON_APIC_ACCESS &&
	     exit_reason.basic != EXIT_REASON_TASK_SWITCH &&
	     exit_reason.basic != EXIT_REASON_NOTIFY)) {
		int ndata = 3;
		gpa_t gpa = INVALID_GPA;

		vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
		vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
		vcpu->run->internal.data[0] = vectoring_info;
		vcpu->run->internal.data[1] = exit_reason.full;
		vcpu->run->internal.data[2] = vmx_get_exit_qual(vcpu);
		if (exit_reason.basic == EXIT_REASON_EPT_MISCONFIG) {
			vcpu->run->internal.data[ndata++] =
				vmcs_read64(GUEST_PHYSICAL_ADDRESS);
		}
		vcpu->run->internal.data[ndata++] = vcpu->arch.last_vmentry_cpu;
		vcpu->run->internal.ndata = ndata;
		if (exit_reason.basic == EXIT_REASON_EPT_MISCONFIG)
			gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);

		kvm_prepare_event_vectoring_exit(vcpu, gpa);
		return 0;
	}

+22 −0
Original line number Diff line number Diff line
@@ -8804,6 +8804,28 @@ void kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_prepare_emulation_failure_exit);

void kvm_prepare_event_vectoring_exit(struct kvm_vcpu *vcpu, gpa_t gpa)
{
	u32 reason, intr_info, error_code;
	struct kvm_run *run = vcpu->run;
	u64 info1, info2;
	int ndata = 0;

	kvm_x86_call(get_exit_info)(vcpu, &reason, &info1, &info2,
				    &intr_info, &error_code);

	run->internal.data[ndata++] = info2;
	run->internal.data[ndata++] = reason;
	run->internal.data[ndata++] = info1;
	run->internal.data[ndata++] = gpa;
	run->internal.data[ndata++] = vcpu->arch.last_vmentry_cpu;

	run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
	run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
	run->internal.ndata = ndata;
}
EXPORT_SYMBOL_GPL(kvm_prepare_event_vectoring_exit);

static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type)
{
	struct kvm *kvm = vcpu->kvm;