Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7543a635 authored by Steve Rutherford's avatar Steve Rutherford Committed by Paolo Bonzini
Browse files

KVM: x86: Add KVM exit for IOAPIC EOIs



Adds KVM_EXIT_IOAPIC_EOI which allows the kernel to EOI
level-triggered IOAPIC interrupts.

Uses a per VCPU exit bitmap to decide whether or not the IOAPIC needs
to be informed (which is identical to the EOI_EXIT_BITMAP field used
by modern x86 processors, but can also be used to elide kvm IOAPIC EOI
exits on older processors).

[Note: A prototype using ResampleFDs found that decoupling the EOI
from the VCPU's thread made it possible for the VCPU to not see a
recent EOI after reentering the guest. This does not match real
hardware.]

Compile tested for Intel x86.

Signed-off-by: default avatarSteve Rutherford <srutherford@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 49df6397
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -3309,6 +3309,18 @@ Valid values for 'type' are:
   to ignore the request, or to gather VM memory core dump and/or
   reset/shutdown of the VM.

		/* KVM_EXIT_IOAPIC_EOI */
		struct {
			__u8 vector;
		} eoi;

Indicates that the VCPU's in-kernel local APIC received an EOI for a
level-triggered IOAPIC interrupt.  This exit only triggers when the
IOAPIC is implemented in userspace (i.e. KVM_CAP_SPLIT_IRQCHIP is enabled);
the userspace IOAPIC should process the EOI and retrigger the interrupt if
it is still asserted.  Vector is the LAPIC interrupt vector for which the
EOI was received.

		/* Fix the size of the union. */
		char padding[256];
	};
+2 −0
Original line number Diff line number Diff line
@@ -574,6 +574,8 @@ struct kvm_vcpu_arch {
	struct {
		bool pv_unhalted;
	} pv;

	int pending_ioapic_eoi;
};

struct kvm_lpage_info {
+17 −7
Original line number Diff line number Diff line
@@ -877,8 +877,19 @@ static bool kvm_ioapic_handles_vector(struct kvm_lapic *apic, int vector)

static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector)
{
	if (kvm_ioapic_handles_vector(apic, vector)) {
	int trigger_mode;

	/* Eoi the ioapic only if the ioapic doesn't own the vector. */
	if (!kvm_ioapic_handles_vector(apic, vector))
		return;

	/* Request a KVM exit to inform the userspace IOAPIC. */
	if (irqchip_split(apic->vcpu->kvm)) {
		apic->vcpu->arch.pending_ioapic_eoi = vector;
		kvm_make_request(KVM_REQ_IOAPIC_EOI_EXIT, apic->vcpu);
		return;
	}

	if (apic_test_vector(vector, apic->regs + APIC_TMR))
		trigger_mode = IOAPIC_LEVEL_TRIG;
	else
@@ -886,7 +897,6 @@ static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector)

	kvm_ioapic_update_eoi(apic->vcpu, vector, trigger_mode);
}
}

static int apic_set_eoi(struct kvm_lapic *apic)
{
+11 −0
Original line number Diff line number Diff line
@@ -6271,6 +6271,17 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
			kvm_pmu_handle_event(vcpu);
		if (kvm_check_request(KVM_REQ_PMI, vcpu))
			kvm_pmu_deliver_pmi(vcpu);
		if (kvm_check_request(KVM_REQ_IOAPIC_EOI_EXIT, vcpu)) {
			BUG_ON(vcpu->arch.pending_ioapic_eoi > 255);
			if (test_bit(vcpu->arch.pending_ioapic_eoi,
				     (void *) vcpu->arch.eoi_exit_bitmap)) {
				vcpu->run->exit_reason = KVM_EXIT_IOAPIC_EOI;
				vcpu->run->eoi.vector =
						vcpu->arch.pending_ioapic_eoi;
				r = 0;
				goto out;
			}
		}
		if (kvm_check_request(KVM_REQ_SCAN_IOAPIC, vcpu))
			vcpu_scan_ioapic(vcpu);
		if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
+1 −1
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ static inline bool is_error_page(struct page *page)
#define KVM_REQ_APIC_PAGE_RELOAD  25
#define KVM_REQ_SMI               26
#define KVM_REQ_HV_CRASH          27
#define KVM_REQ_IOAPIC_EOI_EXIT   28

#define KVM_USERSPACE_IRQ_SOURCE_ID		0
#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID	1
@@ -1146,4 +1147,3 @@ static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val)
}
#endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */
#endif
Loading