ioapic_assign_cpu() on active level-triggered interrupt

From: Alexander Motin <mav_at_FreeBSD.org>
Date: Fri, 04 Jun 2010 21:30:13 +0300
Hi.

I am working on driver for HPET event timers. It works mostly fine,
except after some cases when ioapic_assign_cpu() called while timer is
active. Under interrupt rate of 10KHz it is enough a dozen cpuset runs
to break it (with 1KHz - few dozens). When it happens, I can see that
timer is still running, interrupt status register is changing, but no
interrupts received.

Timer uses level-triggered interrupts, so it is tolerant to interrupt
losses. I have tried to not acknowledge some, and they have immediately
got back to me again, as expected for level-triggering. Timer runs in
periodic mode, so it doesn't need handling to continue counting.

I have reproduced it on two different i386 SMP systems: Core2Duo+ICH10
and Core i5+PCH. With more experiments I have found that I can't trigger
this issue if following patch applied:

--- io_apic.c.prev      2010-06-02 10:55:56.000000000 +0300
+++ io_apic.c   2010-06-04 17:45:51.000000000 +0300
_at__at_ -363,7 +366,10 _at__at_ ioapic_assign_cpu(struct intsrc *isrc, u
                printf(") to lapic %u vector %u\n", intpin->io_cpu,
                    intpin->io_vector);
        }
+       ioapic_disable_source(isrc, PIC_NO_EOI);
+       DELAY(10);
        ioapic_program_intpin(intpin);
+       ioapic_enable_source(isrc);
        /*
         * Free the old vector after the new one is established.  This
is done
         * to prevent races where we could miss an interrupt.

It is is almost a hack and 10us is completely experimental. But it looks
like changing interrupt's APIC and vector in some moments of interrupt
processing may be not a good idea.

Can somebody explain this behavior and propose some solution? Have
somebody seen it for regular PCI devices?

-- 
Alexander Motin
Received on Fri Jun 04 2010 - 16:30:36 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:04 UTC