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

Commit f5244726 authored by Marcelo Tosatti's avatar Marcelo Tosatti Committed by Avi Kivity
Browse files

KVM: irq ack notification



Based on a patch from: Ben-Ami Yassour <benami@il.ibm.com>
which was based on a patch from: Amit Shah <amit.shah@qumranet.com>

Notify IRQ acking on PIC/APIC emulation. The previous patch missed two things:

- Edge triggered interrupts on IOAPIC
- PIC reset with IRR/ISR set should be equivalent to ack (LAPIC probably
needs something similar).

Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
CC: Amit Shah <amit.shah@qumranet.com>
CC: Ben-Ami Yassour <benami@il.ibm.com>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent 564f1537
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -159,9 +159,10 @@ static inline void pic_intack(struct kvm_kpic_state *s, int irq)
		s->irr &= ~(1 << irq);
}

int kvm_pic_read_irq(struct kvm_pic *s)
int kvm_pic_read_irq(struct kvm *kvm)
{
	int irq, irq2, intno;
	struct kvm_pic *s = pic_irqchip(kvm);

	irq = pic_get_irq(&s->pics[0]);
	if (irq >= 0) {
@@ -187,12 +188,21 @@ int kvm_pic_read_irq(struct kvm_pic *s)
		intno = s->pics[0].irq_base + irq;
	}
	pic_update_irq(s);
	kvm_notify_acked_irq(kvm, irq);

	return intno;
}

void kvm_pic_reset(struct kvm_kpic_state *s)
{
	int irq;
	struct kvm *kvm = s->pics_state->irq_request_opaque;

	for (irq = 0; irq < PIC_NUM_PINS; irq++) {
		if (!(s->imr & (1 << irq)) && (s->irr & (1 << irq) ||
		    s->isr & (1 << irq)))
			kvm_notify_acked_irq(kvm, irq);
	}
	s->last_irr = 0;
	s->irr = 0;
	s->imr = 0;
+1 −1
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
		if (kvm_apic_accept_pic_intr(v)) {
			s = pic_irqchip(v->kvm);
			s->output = 0;		/* PIC */
			vector = kvm_pic_read_irq(s);
			vector = kvm_pic_read_irq(v->kvm);
		}
	}
	return vector;
+2 −1
Original line number Diff line number Diff line
@@ -63,11 +63,12 @@ struct kvm_pic {
	void *irq_request_opaque;
	int output;		/* intr from master PIC */
	struct kvm_io_device dev;
	void (*ack_notifier)(void *opaque, int irq);
};

struct kvm_pic *kvm_create_pic(struct kvm *kvm);
void kvm_pic_set_irq(void *opaque, int irq, int level);
int kvm_pic_read_irq(struct kvm_pic *s);
int kvm_pic_read_irq(struct kvm *kvm);
void kvm_pic_update_irq(struct kvm_pic *s);

static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)
+5 −2
Original line number Diff line number Diff line
@@ -439,7 +439,7 @@ struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
static void apic_set_eoi(struct kvm_lapic *apic)
{
	int vector = apic_find_highest_isr(apic);

	int trigger_mode;
	/*
	 * Not every write EOI will has corresponding ISR,
	 * one example is when Kernel check timer on setup_IO_APIC
@@ -451,7 +451,10 @@ static void apic_set_eoi(struct kvm_lapic *apic)
	apic_update_ppr(apic);

	if (apic_test_and_clear_vector(vector, apic->regs + APIC_TMR))
		kvm_ioapic_update_eoi(apic->vcpu->kvm, vector);
		trigger_mode = IOAPIC_LEVEL_TRIG;
	else
		trigger_mode = IOAPIC_EDGE_TRIG;
	kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode);
}

static void apic_send_ipi(struct kvm_lapic *apic)
+13 −7
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@

#include "ioapic.h"
#include "lapic.h"
#include "irq.h"

#if 0
#define ioapic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg)
@@ -285,26 +286,31 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
	}
}

static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi)
static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi,
				    int trigger_mode)
{
	union ioapic_redir_entry *ent;

	ent = &ioapic->redirtbl[gsi];
	ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);

	kvm_notify_acked_irq(ioapic->kvm, gsi);

	if (trigger_mode == IOAPIC_LEVEL_TRIG) {
		ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
		ent->fields.remote_irr = 0;
		if (!ent->fields.mask && (ioapic->irr & (1 << gsi)))
			ioapic_service(ioapic, gsi);
	}
}

void kvm_ioapic_update_eoi(struct kvm *kvm, int vector)
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode)
{
	struct kvm_ioapic *ioapic = kvm->arch.vioapic;
	int i;

	for (i = 0; i < IOAPIC_NUM_PINS; i++)
		if (ioapic->redirtbl[i].fields.vector == vector)
			__kvm_ioapic_update_eoi(ioapic, i);
			__kvm_ioapic_update_eoi(ioapic, i, trigger_mode);
}

static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr,
Loading