3

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; 
}
6
  • Is there any relevant code you can post? What you've been looking at? Without any context, we can't help you.
    – antiduh
    Commented Feb 16, 2016 at 3:25
  • Antiduh, I was referring to the use of local_irq_disable call towards the end in the handle_IRQ_event function.?
    – Siva
    Commented Feb 16, 2016 at 3:29
  • I know. Post some code in your question. stackoverflow.com/help/mcve
    – antiduh
    Commented Feb 16, 2016 at 3:41
  • 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; }
    – Siva
    Commented Feb 16, 2016 at 3:53
  • Above is the implementation of handle_IRQ_event function from LLD3. Please let me know if this is sufficient?
    – Siva
    Commented Feb 16, 2016 at 3:54

1 Answer 1

2

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.

1
  • Ian, Thanks for the explanation.
    – Siva
    Commented Feb 24, 2016 at 6:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.