问题
I am trying to understand the Linux interrupt handling mechanism. I tried googling a bit but couldn't find an answer to this one. Can someone please explain it to me why the handle_IRQ_event needs to call local_irq_disable at the end? After this the control goes back to do_irq which eventually will go back to the entry point. Then who will enable the interrupts back.? It is the responsibility of the interrupt handler? If so why is that so?
Edit
Code for reference
asmlinkage int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action)
{
int status = 1;
int retval = 0;
if (!(action->flags & SA_INTERRUPT))
local_irq_enable();
do
{
status |= action->flags;
retval |= action->handler(irq, action->dev_id, regs);
action = action->next;
}
while (action);
if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
local_irq_disable();
return retval;
}
回答1:
The version of handle_IRQ_event
from LDD3 appears to come from the 2.6.8 kernel, or possibly earlier. Assuming we're dealing with x86, the processor clears the interrupt flag (IF) in the EFLAGS register before it calls the interrupt handler. The old EFLAGS register will be restored by the iret
instruction.
Linux's SA_INTERRUPT
IRQ handler flag (now obsolete) determines whether higher priority interrupts are allowed in the interrupt handler. The SA_INTERRUPT
flag is set for "fast" interrupt handlers that left interrupts disabled. The SA_INTERRUPT
flag is not set for "slow" interrupt handlers that re-enable interrupts.
Regardless of the SA_INTERRUPT
flag, do_IRQ
itself runs with interrupts disabled and they are still disabled when handle_IRQ_event
is called. Since handle_IRQ_event
can enable interrupts, the call to local_irq_disable
at the end ensures they are disabled again on return to do_IRQ
.
The relevant source code files in the 2.6.8 kernel for i386 architecture are arch/i386/kernel/entry.S
, and arch/i386/kernel/irq.c
.
来源:https://stackoverflow.com/questions/35423063/linux-interrupt-handling