Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interrupt vector and irq mapping in do_IRQ

I'm working on a x86 system with Linux 3.6.0. For some experiments, I need to know how the IRQ is mapped to the vector. I learn from many book saying that for vector 0x0 to 0x20 is for traps and exceptions, and from vector 0x20 afterward is for the external device interrupts. And this also defined in the source code Linux/arch/x86/include/asm/irq_vectors.h

However, what I'm puzzled is that when I check the do_IRQ function, http://lxr.linux.no/linux+v3.6/arch/x86/kernel/irq.c#L181 I found the IRQ is fetched by looking up the "vector_irq" array:

unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
    struct pt_regs *old_regs = set_irq_regs(regs);
    /* high bit used in ret_from_ code  */
    unsigned vector = ~regs->orig_ax;
    unsigned irq;
    ...
    irq = __this_cpu_read(vector_irq[vector]); // get the IRQ from the vector_irq
    // print out the vector_irq
    prink("CPU-ID:%d, vector: 0x%x  - irq: %d", smp_processor_id(), vector, irq); 
}

By instrumenting the code with printk, the vector-irq mapping I got is like below and I don't have any clue why this is the mapping. I though the mapping should be (irq + 0x20 = vector), but it seems not the case.

from: Linux/arch/x86/include/asm/irq_vector.h
*  Vectors   0 ...  31 : system traps and exceptions - hardcoded events
*  Vectors  32 ... 127 : device interrupts = 0x20 – 0x7F

But my output is:

CPU-ID=0.Vector=0x56 (irq=58)
CPU-ID=0.Vector=0x66 (irq=59)
CPU-ID=0.Vector=0x76 (irq=60)
CPU-ID=0.Vector=0x86 (irq=61)
CPU-ID=0.Vector=0x96 (irq=62)
CPU-ID=0.Vector=0xa6 (irq=63)
CPU-ID=0.Vector=0xb6 (irq=64)

BTW, these irqs are my 10GB ethernet cards with MSIX enabled. Could anyone give me some ideas about why this is the mapping? and what's the rules for making this mapping?

Thanks. William

like image 494
William Tu Avatar asked Oct 03 '22 21:10

William Tu


2 Answers

The irq number (which is what you use in software) is not the same as the vector number (which is what the interrupt controller actually uses).

The x86 I/OAPIC interrupt controller assigns interrupt priorities in groups of 16, so the vector numbers are spaced out to prevent them from interfering with each other (see the function __assign_irq_vector in arch/x86/kernel/apic/io_apic.c).

like image 82
CL. Avatar answered Oct 05 '22 10:10

CL.


I guess my question is how the vectors are assigned for a particular IRQ number and what's are the rules behind.

The IOAPIC supports a register called IOREDTBL for each IRQ input. Software assigns the desired vector number for the IRQ input using bit 7-0 of this register. It is this vector number that serves as an index into the processors Interrupt Descriptor Table. Quoting the IOAPIC manual (82093AA)

7:0 Interrupt Vector (INTVEC)—R/W: The vector field is an 8 bit field containing the interrupt vector for this interrupt. Vector values range from 10h to FEh.

Note that these registers are not directly accessible to software. To access IOAPIC registers (not to be confused with Local APIC registers) software must use the IOREGSEL and IOWIN registers to indirectly interact with the IOAPIC. These registers are also described in the IOAPIC manual.

The source information for the IOAPIC can be a little tricky to dig up. Here's a link to the example I used: IOAPIC data sheet link

like image 45
srking Avatar answered Oct 05 '22 09:10

srking