Re: i8259 IRQ problems

From: James Bottomley (James.Bottomley@SteelEye.com)
Date: Sat Mar 25 2000 - 14:00:43 EST


manfreds@colorfullife.com said:
>> A local APIC won't accept another interrupt while the CPU has
>> interrupts
>> disabled.
> Are you sure? The "Interrupt Acceptance Flow Chart for the Local APIC"
> doesn't contain the "Interrupt Enabled" flag of the associated cpu.

Actually no. I know this causes problems in the Voyager architecture (a
precursor to the APIC architecture) since the VICs (local APIC equivalents)
happily assign an interrupt to a processor with its local mask raised unless
told not to, causesing no end of grief in this architecture since telling the
VICs not to accept an interrupt for a CPU is a very expensive operation. I'm
sure this was pointed out to Intel during the APIC architecture design and
they promised to do something about it...

There is a solution which I use in the Linux Voyager SMP kernel, but I'd
rather be sure the same problem exists before employing it.

>> > The task priority remains 0, but the local apic maintains a "Processor
>> > priority register", and this one changes automagically.
>>
>> This register is used in the priority backoff algorithm on the APIC bus, not
>> for interrupt priority.
>
>This is wrong: the arbitration priority register APR is used for the
>priority backoff.
>The local APIC uses 3 priority registers [APR, PPR, TPR], plus an "Arb
>ID" as a tie breaker.

OK, I think we're arguing over different things. The local APIC has five
separate concepts of priority:

1. Priority for arbitrating to send a message on the APIC Bus (the arbitration
priotity).
2. Task priority: this determines whether the local APIC will accept an
interrupt or not. Linux keeps this at 0.
3. Processor Priority: Determines whether an accepted interrupt can be
delivered to the CPU.
4. Prority for arbitrating to receive a lowest priority interrupt--see below--
(also called the arbitration priority in the docs :-P)
5. Lowest priority interrupt delivery mode. Linux uses this mode to
distribute all interrupts which originate in the IO-APICs.

I was describing the mechanism for 1.

I think we both agree 2. is irrelevant since linux holds this to zero.

3. is germane to the discussion since it gives the concept of "priority" to
the currently executing interrupt. Your question:

> 2) we are in the middle of a level triggered interrupt. We do not ack
> the interrupt until the end of the interrupt handler. And the APIC
> will deliver higher priority interrupts immediately, but lower
> priority interrupts wait for the EOI.

is governed both by 3. and 4. You're right, if we accept an interrupt at lower priority (lets call this vector to be clearer) than 3. we hold it until all other higher vectored ones have EOI'd. However, 4. is set to the highest of the pending and accepted interrupts. This means we can accept an interrupt of lower vector than 3. only if all other CPUs in the system are currently processing higher vectored interrupts than we are, since "lowest priority" interrupts (5. above) are delivered to the CPU with the lowest value for 4.

I believe this means that your scenario where we have pending lower priority interrupts is possible but quite rare: In a dual CPU system you must have three level interrupts asserted over a short time interval in decreasing vector order.

Now we get to your other observation:

> 1) what happens if the cpu runs with disabled local interrupts, the
> local apic accepts multiple interrupts. The cpu reenables the local
> interrupts. Now the tlb flush interrupts should be handled first.

I believe this is correct. However, practically once the CPU is handling a level interrupt, it won't accept another unless all other CPUs are handling higher vectored interrupts. This means that usually when it has finished it will handle the tlb flush, whatever vector it happens to be at.

*But*, I believe you think it could have handled the tlb flush as soon as a sti was done? since as you point out it takes a long time get to the EOI. I agree. The way to fix this is surely to shuffle around the vectors so the critical IPIs occur at the top of the range not the bottom, as you pointed out in your email that started this. The code for doing this is in arch/i386/kernel/irq.h for the static #defines and arch/i386/kernel/io_apic.c for the function assign_irq_vector() which must be taught to ignore a different range.

James Bottomley

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Mar 31 2000 - 21:00:15 EST