From 697d9a014506df49976251b2cc449bbe2a806d9a Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Mon, 5 Apr 2021 15:29:16 +1000 Subject: ioapic: Use irq specific EOI properly when detected Message-Id: <20210405052916.174771-5-damien@zamaudio.com> --- i386/i386/apic.h | 4 ++++ i386/i386at/ioapic.c | 30 ++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/i386/i386/apic.h b/i386/i386/apic.h index d63dbfcc..add1b8cf 100644 --- a/i386/i386/apic.h +++ b/i386/i386/apic.h @@ -35,6 +35,8 @@ typedef struct ApicReg { typedef struct ApicIoUnit { ApicReg select; ApicReg window; + ApicReg unused[2]; + ApicReg eoi; /* write the vector you wish to EOI to this reg */ } ApicIoUnit; struct ioapic_route_entry { @@ -175,6 +177,7 @@ extern inline void unmask_irq (unsigned int irq_nr); #define LAPIC_ENABLE 0x100 #define LAPIC_FOCUS 0x200 #define LAPIC_NMI 0x400 +#define LAPIC_ENABLE_DIRECTED_EOI 0x1000 #define LAPIC_DISABLE 0x10000 #define LAPIC_TIMER_PERIODIC 0x20000 #define LAPIC_TIMER_DIVIDE_2 0 @@ -182,6 +185,7 @@ extern inline void unmask_irq (unsigned int irq_nr); #define LAPIC_TIMER_DIVIDE_8 2 #define LAPIC_TIMER_DIVIDE_16 3 #define LAPIC_TIMER_BASEDIV 0x100000 +#define LAPIC_HAS_DIRECTED_EOI 0x1000000 #define NINTR 24 #define IOAPIC_FIXED 0 diff --git a/i386/i386at/ioapic.c b/i386/i386at/ioapic.c index 38d1b43c..30ae30e1 100644 --- a/i386/i386at/ioapic.c +++ b/i386/i386at/ioapic.c @@ -31,6 +31,7 @@ #include #include +static int has_irq_specific_eoi = 1; /* FIXME: Assume all machines have this */ static int timer_gsi; int timer_pin; @@ -244,16 +245,23 @@ ioapic_irq_eoi(int pin) int apic = 0; union ioapic_route_entry_union oldentry, entry; - /* Workaround for old IOAPICs with no specific EOI */ + if (!has_irq_specific_eoi) { + /* Workaround for old IOAPICs with no specific EOI */ - /* Mask the pin and change to edge triggered */ - oldentry.both = entry.both = ioapic_read_entry(apic, pin); - entry.both.mask = IOAPIC_MASK_DISABLED; - entry.both.trigger = IOAPIC_EDGE_TRIGGERED; - ioapic_write_entry(apic, pin, entry.both); + /* Mask the pin and change to edge triggered */ + oldentry.both = entry.both = ioapic_read_entry(apic, pin); + entry.both.mask = IOAPIC_MASK_DISABLED; + entry.both.trigger = IOAPIC_EDGE_TRIGGERED; + ioapic_write_entry(apic, pin, entry.both); + + /* Restore level entry */ + ioapic_write_entry(apic, pin, oldentry.both); + } else { + volatile ApicIoUnit *ioapic = apic_get_ioapic(apic)->ioapic; - /* Restore level entry */ - ioapic_write_entry(apic, pin, oldentry.both); + entry.both = ioapic_read_entry(apic, pin); + ioapic->eoi.r = entry.both.vector; + } } void @@ -382,6 +390,12 @@ ioapic_configure(void) /* Enable IOAPIC processor focus */ lapic->spurious_vector.r |= LAPIC_FOCUS; + /* Enable directed EOI if applicable */ + if (has_irq_specific_eoi || lapic->version.r & LAPIC_HAS_DIRECTED_EOI) { + has_irq_specific_eoi = 1; + lapic->spurious_vector.r |= LAPIC_ENABLE_DIRECTED_EOI; + } + /* Enable IOAPIC interrupts */ lapic->spurious_vector.r |= LAPIC_ENABLE; -- cgit v1.2.3