This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

GIC Interrupt handling in Linux

Dear Experts 

I am little confused now with GIC handling of interrupt in case of Linux. 

As I understood. GIC level interrupt can be at following stage 

1) Inactive : No interrupt pending

2) Pending : Interrupt raised by IP , acknowlged by GIC, and forwarded to CPU 

3) Active: Interrupt acknowlged  by core and under servicing 

4) Active and Pending: CPU is serving interrupt and IP raised by same Interrupt 

Coming to Linux code 

Assuming IP interrupt is low level trigger 

1) IP raise interrupt, GIC deliver it to CPU

2) Linux acknowlegd to GIC, and move inteerupt to active state . 

3) Before calling IP specific handler (Where IP interrupt's line status will be changed to high) , Linux mark this interrupt as EOI (As I understood this is moving IT to Inactive) 

https://elixir.bootlin.com/linux/v6.8-rc4/source/drivers/irqchip/irq-gic.c#L351 

Now after this line, at GIC level interrupt moved to Inactive state, IP line is still low 

4) IP specific handler is getting called. 

Confusion, I have how GIC avoids condition between 3 and 4. 

Shouldn't this be better to call IP handler first then clear IT at GIC level. 

I may be wrong , please suggest

 

  • Hello

    I have moved your question to the Architectures and Processors where someone may be able to help you.

    Thanks

    Oli

    Arm Community Manager

  • I am going to start with a disclaimer - I'm not a Linux kernel expert.  For a detailed answer of Linux interrupt handler you might be better off with posting on a Linux group.

    That being said, within __exception_irq_entry you have:

            irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
    		irqnr = irqstat & GICC_IAR_INT_ID_MASK;
    
    		if (unlikely(irqnr >= 1020))
    			break;
    
    		if (static_branch_likely(&supports_deactivate_key))
    			writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
    		isb();


    The write to the EOI register is guarded by the check of "supports_deactivate_key".  Poking around in the source, I believe what this is checking for is whether EOImode is enabled or not. 
    There are two things software has to do before it has fully handled an interrupt: priority drop and deactivation.  Priority drop updates the Running Priority of the CPUIF, Deactivation updates the state machine of the interrupt.  See the end of this page for a fuller explanation:
    When EOImode is cleared to 0, a write to the EOI register performs both priority drop and deactivation.  If EOImode is set to 1, then the write to the EOI regiser _only_ performs the priority drop. A separate with to DIR is needed to perform deactivation.  I believe that is what "supports_deactivate_key" is checking - whether EOImode is set or clear.  The Linux code is only doing the write to EOI when EOImode is set to 1 - meaning it's only performing priority drop.