Now that we have locking per apic pin, we need to prevent usual pin maskings from stepping on EOI special masking procedures. Also, do the lapic eoi before the ioapic eoi. Add code for conditioning on TMR bit, but keep it disabled for now.
TESTED: on SMP and UP+apic: receives a large file over rumpnet. --- i386/i386/irq.c | 23 +++++++++++++++-------- i386/i386at/ioapic.c | 26 +++++++++++++++++++------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/i386/i386/irq.c b/i386/i386/irq.c index 30457a3d..9d96578e 100644 --- a/i386/i386/irq.c +++ b/i386/i386/irq.c @@ -26,14 +26,6 @@ extern queue_head_t main_intr_queue; -static void -irq_eoi (struct irqdev *dev, int id) -{ -#ifdef APIC - ioapic_irq_eoi (dev->irq[id]); -#endif -} - /* Each array elem fits in a cache line */ struct nested_irq { simple_lock_irq_data_t irq_lock; @@ -41,6 +33,21 @@ struct nested_irq { uint32_t unused[14]; } __attribute__((packed)) nested_irqs[NINTR]; +static void +irq_eoi (struct irqdev *dev, int id) +{ +#ifdef APIC + int irq_nr = dev->irq[id]; + struct nested_irq *nirq = &nested_irqs[irq_nr]; + + spl_t s = simple_lock_irq(&nirq->irq_lock); + + ioapic_irq_eoi (irq_nr); + + simple_unlock_irq(s, &nirq->irq_lock); +#endif +} + void init_irqs (void) { diff --git a/i386/i386at/ioapic.c b/i386/i386at/ioapic.c index d0724f76..c3a3c804 100644 --- a/i386/i386at/ioapic.c +++ b/i386/i386at/ioapic.c @@ -290,22 +290,38 @@ ioapic_toggle(int pin, int mask) ioapic_toggle_entry(apic, pin, mask); } +#if 0 +static int +lapic_tmr_bit(uint8_t vec) +{ + int i; + + i = (vec & ~0x1f) >> 5; + return lapic->tmr[i].r & (1 << (vec & 0x1f)); +} +#endif + void ioapic_irq_eoi(int pin) { + /* FIXME: multiple ioapics */ int apic = 0; union ioapic_route_entry_union oldentry, entry; + lapic_eoi(); if (pin == 0) - goto skip_specific_eoi; + return; spl_t s = simple_lock_irq(&ioapic_lock); + /* Read entry to find vector */ + ioapic_read_entry(apic, pin, &entry.both); + if (!has_irq_specific_eoi) { + // XXX Linux conditions on TMR bit: if (!lapic_tmr_bit(entry.both.vector)) { /* Workaround for old IOAPICs with no specific EOI */ /* Mask the pin and change to edge triggered */ - ioapic_read_entry(apic, pin, &entry.both); oldentry = entry; entry.both.mask = IOAPIC_MASK_DISABLED; entry.both.trigger = IOAPIC_EDGE_TRIGGERED; @@ -313,17 +329,13 @@ ioapic_irq_eoi(int pin) /* Restore level entry */ ioapic_write_entry(apic, pin, oldentry.both); + //} } else { volatile ApicIoUnit *ioapic = apic_get_ioapic(apic)->ioapic; - - ioapic_read_entry(apic, pin, &entry.both); ioapic->eoi.r = entry.both.vector; } simple_unlock_irq(s, &ioapic_lock); - -skip_specific_eoi: - lapic_eoi (); } static unsigned int -- 2.45.2