In a previous blog post, I explained some of the exception codes which are stored within a data structure called the Interrupt Dispatch Table, we can be viewed with WinDbg using the !idt extension. Here I would like to breifly explain how the Interrupt Dispatch Table works.
We can gain further information from each interrupt, when using the dt nt!_KINTERRUPT command, which will give you the following prototype:
Drivers will use the IoConnectInterruptEx API, to provide a pointer to the above data structure, when registering a ISR for that device.
Hardware interrupts are handled by a interrupt controller which then interrupts the CPU, and the CPU then reads the IRQ to match the request to the appropriate interrupt number. Most CPUs use a APIC interrupt controller, rather than the older PIC controller. You can attempt to use the !pic and !apic extensions to see which one you are using; only one extension will work. Furthermore, interrupts are serviced by a routine called a Interrupt Service Routine (ISR), whereas, a exception is serviced by a exception handler.
Each interrupt is given a IRQL (Interrupt Request Priority Level), as this is generally a software related interrupt concept (APCs and DPCs), then IRQs from hardware interrupts have to be mapped to the appropriate IRQL level. We can view the IRQL level of a processor with !irql.
On x86 systems, the IRQL levels range from 0 to 31, whereas, on x64 systems this is 0 to 15.