1. The interrupt flag (IF) of the 80x86 is reset either directly (e.g., by a "cli" instruction) or because an interrupt handler is entered. In the latter case the corresponding in-service (IS) bit of the 8259A is set (effectively blocking interrupts of lower priority). 2. The 8259A receives an unmasked interrupt request (IRQn), and, in case an interrupt is being served and has higher priority than IRQn, the IS bit of the 8259A is reset by an end of interrupt (EOI) command. (These steps may occur in either order.) If IRQn has higher priority (e.g. IRQ0), no EOI is necessary. 3. The 8259A activates the interrupt (INT) line to the 80x86 (which will ignore it - for the moment). 4. The interrupt mask (IM) bit of the 8259A for IRQn is set. (A little late, though. The sequence has already started.) 5. The interrupt flag (IF) of the 80x86 is set (either directly, or as a consequence of e.g. an "iret" instruction). 6. The 80x86 will now acknowledge the INT request by activating the INTA line of the 8259A. 7. The 8259A will not see the masked IRQn and will continue by issuing a spurious interrupt of level 7 instead.
之前从网络上搜到一个伪中断相关讨论, 其中给出了一个伪中断产生的步骤, 翻译一下大概如此:
1. X86 IF 标志重置, CPU 不再相应 INT 引脚信号
2. 8259A 收到一个未被屏蔽的中断
3. 8259A 为这个中断向 CPU 发出 INT 信号, 但由于 IF 重置, CPU 忽略之
4. 在某个内核路径中, 有代码调用了 disable_irq, 将已经发出 INT 的中断给屏蔽了, 貌似这个 disable 只是在 IMR 中设置了一个bit 位, 已经发出的 INT 没有收回 (这个是水平触发的还是在8259A 和 CPU 间存在锁存器就不得而知了)
5. CPU IF 标志恢复, CPU 注意到这个 INT, 发出 INTA 相应
6. 然而现在 8269A 已经没有可以拿出来的中断了, 因为仅有的一个已经被屏蔽了, 于是它产生一个伪中断给 CPU
没什么内容, 只有一点可以推断, 就是 INT 一旦发出, 再收到INTA 回应前, 这个信号应该是始终有效的。
还有一点内容, 将常见的伪中断原因给列出了几个:
Maciej W. Rozycki wrote: > > There are actually two D-latches between the input and the priority > resolver. You are clearly writing of the ISR latch which is really reset > by EOI. But the reason of spurious interrupts is the IRR D-latch which is > located earlier in the path from IR<x> pin to the priority resolver. The > IRR latch normally reflects the IR<x> input but it gets frozen at the > start of the first INTA cycle (it also gets reset by ICW1 but this doesn't > matter here). But the CPU probes for INT at the late stage of execution > of an instruction. There is a small window between the INT probe and the > start of the first INTA cycle. If the IR<x> line gets deasserted during > this window and no other IR<x> line is active at the moment you get a > spurious interrupt -- an 8259A issues a default vector which is that of > IR7. Exactly! >From my notes of long ago, Spurious Interrupts occur when: - Interrupt pin is asserted in level sensitive mode, and the asserted level is negated before the interrupt is acknowledged. - Interrupt pin is asserted for an interrupt source that is later masked using the mask bit in the vector/priority register before the interrupt is acknowledged. - Some UARTs can generate spurious interrupts if you clear the IER (Interrupt Enable Register) right before an interrupt occurs. Same result, interrupt generated but not present during the acknowledge cycle. - There are more, but you get the idea. This appears to be an desired behavior. I remember that the OpenPIC interrupt controller (AMD/CYRIX SMP response to the APIC) has the same (non?) feature... Bob
还有一点, CPU 从发出第一个 INTA 到调用进入中断门调用中断处理程序第一行代码前, 应该是一个原子操作, 在此期间, 应该不会再次检查 INT 信号了, 否则两个事务互相纠缠, 就乱了。 之前记得曾经有这么一个结论, 现在只隐约记得似乎有这么个结论了。
IF 重置应该是在穿越中断门的时候做的, 因为关闭中断与否是中断门的一个属性。 因此不能用来保证两次 INTA 的原子性, 只能说, CPU 本身做这个保证。