Relationship between the IDT, PIC, and external interrupts

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
quadrant
Member
Member
Posts: 74
Joined: Tue Apr 24, 2018 9:46 pm

Relationship between the IDT, PIC, and external interrupts

Post by quadrant »

The interrupt descriptor table (IDT) on a x86 CPU has 256 entries. Of these, the first 32 are reserved for CPU generated exceptions.

The CPU has one external interrupt pin[1]. A programmable interrupt controller (PIC) is used to allow multiple external devices to send interrupts to the CPU through this one shared pin. From the wiki:
In the beginning (IBM PC and XT), only a single 8259 PIC chip was used, which provided 8 IRQs to the system.
...
The IBM PC/AT extended the PC architecture by adding a second 8259 PIC chip...This gives a total of 15 interrupts. Why 15 and not 16? That's because when you cascade chips, the PIC needs to use one of the interrupt lines to signal the other chip.
Does this mean only 15 external interrupts are possible? Can all the devices found in modern PCs/laptops that are external to the CPU really be serviced with just 15 interrupts? For example a laptop might have a speaker, a touchpad, a keyboard, a camera, a wifi card, various USB ports, a HDMI port, a VGA port, an ethernet port, and SD card port, a headphone jack, a bluetooth controller, a magnet sensor, a harddrive etc.

Also to which interrupt number are the external interrupts configured to? Is the single CPU interrupt pin hardwired to the number 32 (the first available IDT entry following the 31 reserved for internal use by the CPU)? Or is the OS responsible for choosing the number?

For example in xv6, external interrupts are defined as follows:

Code: Select all

#define T_IRQ0        32  // IRQ 0 corresponds to int T_IRQ

#define IRQ_TIMER      0
#define IRQ_KBD        1
#define IRQ_COM1       4
#define IRQ_IDE       14
#define IRQ_ERROR     19
#define IRQ_SPURIOUS  31
For example the interrupt number for the keyboard is 33. (T_IRQ0 + IRQ_KBD = 32 + 1 = 33)


[1]: A simple x86 CPU like the 8086
linguofreak
Member
Member
Posts: 510
Joined: Wed Mar 09, 2011 3:55 am

Re: Relationship between the IDT, PIC, and external interrup

Post by linguofreak »

quadrant wrote:The interrupt descriptor table (IDT) on a x86 CPU has 256 entries. Of these, the first 32 are reserved for CPU generated exceptions.

The CPU has one external interrupt pin[1]. A programmable interrupt controller (PIC) is used to allow multiple external devices to send interrupts to the CPU through this one shared pin. From the wiki:
In the beginning (IBM PC and XT), only a single 8259 PIC chip was used, which provided 8 IRQs to the system.
...
The IBM PC/AT extended the PC architecture by adding a second 8259 PIC chip...This gives a total of 15 interrupts. Why 15 and not 16? That's because when you cascade chips, the PIC needs to use one of the interrupt lines to signal the other chip.
Does this mean only 15 external interrupts are possible?
Only 15 external interrupts (plus the NMI, which doesn't go through the 8259s) are possible on an old-school AT-style PC containing only 8259 interrupt controllers, but the NMI is (at least in theory) reserved for signalling catastrophic failures like imminent loss of power or unrecoverable hardware failures, and not for the normal operation of the system. But a system can have other things than an 8259 attached to the interrupt line, and, these days, generally does.
Also to which interrupt number are the external interrupts configured to? Is the single CPU interrupt pin hardwired to the number 32 (the first available IDT entry following the 31 reserved for internal use by the CPU)? Or is the OS responsible for choosing the number?
The interrupt pin just tells the CPU that there's an interrupt, the CPU then sends the interrupt controller (whether it's an 8259 PIC or something more modern) an interrupt acknowledge signal, and the interrupt controller then puts the interrupt number onto the data bus (just as if it were a byte of data being read from memory).

The double 8259 setup of the AT architecture allows up to 15 interrupts, but each of the 2 PICs can be set up to use any consecutive block of 8 interrupts starting at a multiple of 8 for the IRQs it is responsible for. But while the 8259 is still around on modern computers for legacy compatibility, modern OSes will generally use the APIC instead.
Last edited by linguofreak on Fri Jun 14, 2019 6:12 pm, edited 1 time in total.
nullplan
Member
Member
Posts: 1801
Joined: Wed Aug 30, 2017 8:24 am

Re: Relationship between the IDT, PIC, and external interrup

Post by nullplan »

quadrant wrote:Does this mean only 15 external interrupts are possible? Can all the devices found in modern PCs/laptops that are external to the CPU really be serviced with just 15 interrupts?
No. The PIC is legacy. More modern systems will have an IOAPIC with 24 or 32 inputs. You still need to reserve interrupt vectors for the PIC, if ACPI tables indicate a PIC is present, but if an IOAPIC is present, all of the PIC interrupts are spurious. Also, even more modern systems have PCI-Express with Message Signalled Interrupts (MSI), which means you can get a single interrupt for each device supporting it, completely without PIC or APIC (that is, MSI requires a local APIC, but not necessarily an IOAPIC). And yet more modern systems support MSI-X, which uses a different format and supports a load more interrupts, and allows a single peripheral to do multiple different interrupts. Put all of that together, and the biggest bottleneck in some systems is the IDT's 256 entries.

But even 15 interrupts would last you a while. According to Linux, my Laptop is currently running with 21 interrupts of which 9 are MSIs. My interrupts are:

Code: Select all

$ cat /proc/interrupts | grep '^\s*[0-9]'
  0:          8          0          0          0  IR-IO-APIC   2-edge      timer
  1:     118601          0          0        398  IR-IO-APIC   1-edge      i8042
  6:          0          0          0          0  IR-IO-APIC   6-fasteoi   dw:dmac-1
  7:  159019372          0    3932826          0  IR-IO-APIC   7-fasteoi   INT3432:00, INT3433:00
  8:          0         46          0          0  IR-IO-APIC   8-edge      rtc0
  9:     658055       5821          0          0  IR-IO-APIC   9-fasteoi   acpi
 18:          0          0          0          0  IR-IO-APIC  18-fasteoi   i801_smbus
 19:       8085          0    8596498      68155  IR-IO-APIC  19-fasteoi   ath9k
 23:        517         35         10          0  IR-IO-APIC  23-fasteoi   ehci_hcd:usb3
 39:   10714492          0          0     302884  IR-IO-APIC  39-fasteoi   ELAN0501:00
 40:          0          0          0          0  DMAR-MSI   0-edge      dmar0
 41:          0          0          0          0  DMAR-MSI   1-edge      dmar1
 42:          0          0          0          0  IR-PCI-MSI 458752-edge      PCIe PME, pciehp
 43:          0          0          0          0  IR-PCI-MSI 462848-edge      PCIe PME
 44:          0          0          0          0  IR-PCI-MSI 464896-edge      PCIe PME
 46:       4188       1755    1700313    1179411  IR-PCI-MSI 327680-edge      xhci_hcd
 47:    1074654          0       7044          0  IR-PCI-MSI 512000-edge      ahci[0000:00:1f.2]
 48:          0          0          0          0  IR-PCI-MSI 49152-edge      snd_hda_intel:card0
 49:      10723   30921017          0          0  IR-PCI-MSI 32768-edge      i915
 50:          0          0         18          0  IR-PCI-MSI 360448-edge      mei_me
 51:          0          0          0        133  IR-PCI-MSI 442368-edge      snd_hda_intel:card1
I have no idea what "dmac", "dmar" and "mei_me" are. Also i801_smbus will likely go unused, since that is only needed to read BIOS information.
Carpe diem!
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Relationship between the IDT, PIC, and external interrup

Post by bzt »

Hi,

I think @lingofreak and @nullplan summed it up pretty good.
quadrant wrote:Can all the devices found in modern PCs/laptops that are external to the CPU really be serviced with just 15 interrupts?
I think your problem is with the definitions: there's a difference between IRQ and interrupt. IDT has 256 interrupt slots, which can hold exception, call gate, IRQ handler and software interrupt handlers. On legacy systems you have 15 IRQ handlers, but more devices can share the same IRQ handler (share the same IDT slot, therefore the same interrupt), and also with MSI you can program separate interrupts (different IDT slots, different interrupts). Not to mention that with IOAPIC you can specify priority, in which case you spread the IRQs to several IDT slot blocks. So 15 IRQ does not necessarily mean 15 interrupts, could be more or less.

This difference becames more apparent on the ARM architecture, where you have only one IRQ handler, yet you can serve lots of devices all with different interrupts. (There the IRQ handler polls the devices' status registers to figure out which interrupt service routine should be called).

Cheers,
bzt
quadrant
Member
Member
Posts: 74
Joined: Tue Apr 24, 2018 9:46 pm

Re: Relationship between the IDT, PIC, and external interrup

Post by quadrant »

Thank you all for the replies!
Post Reply