How to Get The Interrupt Vector Number on Linux

How do I get the interrupt vector number on Linux?

On x86 NMIs are always on interrupt vector 2. The number is hard-coded just as common exceptions (division by 0, page fault, etc). You can find this in the CPU documentation from Intel/AMD.

If the APIC is enabled (as is the case in the dump presented in the question), Spurious Interrupt's interrupt vector number can be obtained from APIC's SVR register. Again, see the same CPU documentation on that.

If the APIC isn't enabled and instead the PIC is being used, then Spurious Interrupts are delivered as IRQ7 (see the 8259A PIC chip spec for that). The BIOS programs the PIC in such a way that IRQ7 is interrupt vector 0Fh, but Windows and Linux change this mapping to avoid sharing the same interrupt vectors for IRQs and CPU exceptions. It seems like this mapping can't be queried from the PIC, but it's established via sending the Initialization Control Word 2 (ICW2) to the PIC. Here's the relevant piece of Linux code in init_8259A():

    /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 on x86-64,
to 0x20-0x27 on i386 */
outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);

That should answer the Spurious Interrupt vector part.

As for LOC and PMI, I think, these are local APIC's interrupts and you can find their interrupt vectors from the APIC just like with the Spurious Interrupt above.

Multiple interrupt vector tables for multiple processes

A process running in a user address space can not service interrupts and thus does not have a vector table. The interrupt vector table will reside in the kernels address space.

In the case of a keyboard, the kernel's vector table(s) will handle the interrupt and pickup the key press. The kernel then will send the character from the key press to the user application via a system call. In linux, the system call will most likely be abstracted as a file being read by the user processes.

Multiple user processes (applications in this example) can read from the same file, so the behavior depends on the specifics of the file/file like device. There is a good chance it will end up being an unpredictable race between processes to read the data first. In practice, its often a bad idea to have multiple processes concurrently accessing the same file.

How do I identify device specific interrupts on x86?

Well, I seem to have found the answer in our support code, specifically the PIC initialization routine. With the following code IRQ lines are mapped at offset 20h and 28h in the IDT for the master and slave PICs, respectively.


/*
ICW2: master offset of 20 in the IDT, slave offset of 28
*/

__outb( PIC_MASTER_IMR_PORT, 0x20 );
__outb( PIC_SLAVE_IMR_PORT, 0x28 );

This means that the keyboard was mapped to vector number 2c and the primary and secondary channels will be mapped to 2e and 2f respectively. Some of you probably could have given me better answers had I asked the question better, but I appreciate the help anyway!

Table 45 of the 82801EB ICH5 datasheet details the 8259's IRQ lines, and in my OS the master is simply loaded at offset 20h and the slave is 28h.

Thanks!

IRQ and interrupt vector

The beyondlogic.com table shows the default mapping, as set up by the BIOS, from an IRQ (the external interrupt signal going into the Programmable Interrupt Controller (PIC)) to the interrupt or exception number as seen by the CPU. So in this case the interrupt line from the serial port is connected to PIC input 3, which when asserted will cause the CPU to run the interrupt/exception handler pointed to by entry 0xC in the interrupt vector table.

The same thing happens with exceptions generated internally by the CPU. To continue with your example, a stack fault causes the exception hander pointed to by entry 0xC in the in interrupt vector table to be run.

So in this case its not that the serial port interrupt causes a stack fault, but that two different events can cause the same interrupt/exception handler to run.

This clash is not desirable. In theory the interrupt/exception handler code could check to see what actually caused the handler to run, but this would take time, so we need a better solution.

However first it is worth looking at what caused this clash in the first place. Intel always reserved entries less than 0x20 for internal exceptions, but on the 8086 only entries 0 to 4 were used, so when when the original IBM PC mapped interrupts to 8 and above this wasn't a problem.

With the introduction of the 80386 and protected mode the number of exceptions was increased, and entries 5 to 0x14 were now used, which meant that clashes could occur with interrupts when the default IRQ mapping was used.

So the solution used by most modern operating systems which run in protected mode is to reprogram the PIC to so that interrupts use interrupt vector numbers 0x20 or greater. See OSDev.org for more details or for a concrete example see how Linux does this.



Related Topics



Leave a reply



Submit