[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 4/4] ioapic: Use irq specific EOI properly when detected
From: |
Damien Zammit |
Subject: |
[PATCH 4/4] ioapic: Use irq specific EOI properly when detected |
Date: |
Mon, 5 Apr 2021 15:29:16 +1000 |
---
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 <mach/machine.h>
#include <kern/printf.h>
+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;
--
2.30.1