The flags member

The flags member takes two sets of flags. The first set deals with the characteristics of the interrupts:

INTR_FLAG_NMI
Indicates that this is a NonMaskable Interrupt (NMI). An NMI is an interrupt which can't be disabled by clearing the CPU's interrupt enable flag, unlike most normal interrupts. NonMaskable interrupts are typically used to signal events that require immediate action, such as a parity error, a hardware failure, or imminent loss of power. The address for the handler's NMI is stored in the BIOS's Interrupt Vector table at position 02H. For this reason an NMI is often referred to as INT 02H.

The code in the kernel needs to differentiate between normal interrupts and NMIs, because with an NMI the kernel needs to know that it can't protect (mask) the interrupt (hence the "N" in NonMaskable Interrupt). We strongly discourage the use of the NMI vector in x86 designs; we don't support it on any non-x86 platforms.

Note: Regular interrupts that are normally used and referred to by number are called maskable interrupts. Unlike non maskable interrupts, maskable interrupts are those that can be masked, or ignored, to allow the processor to complete a task.
INTR_FLAG_CASCADE_IMPLICIT_EOI
Indicates that an EOI to the primary interrupt controller is not required when handling a cascaded interrupt (e.g. it's done automatically). Only used if this entry describes a cascaded controller.
INTR_FLAG_CPU_FAULT
Indicates that one or more of the vectors described by this entry is not connected to a hardware interrupt source, but rather is generated as a result of a CPU fault (e.g. bus fault, parity error). Note that we strongly discourage designing your hardware this way. The implication is that a check needs to be inserted for an exception into the generated code stream; after the interrupt has been identified, an EOI needs to be sent to the controller. The EOI code burst has the additional responsibility of detecting what address caused the fault, retrieving the fault type, and then passing the fault on. The primary disadvantage of this approach is that it causes extra code to be inserted into the code path.

The second set of flags deals with code generation:

INTR_GENFLAG_LOAD_SYSPAGE
Before the interrupt identification or EOI code sequence is generated, a piece of code needs to be inserted to fetch the system page pointer into a register so that it's usable within the identification code sequence.
Note: If you use the interrupt_id_dec(), interrupt_id_dec_smp(), or interrupt_eoi_dec() callouts, you must specify the INTR_GENFLAG_LOAD_SYSPAGE flag in the genflags field of the intrinfo_entry structure in the board-specific code.
INTR_GENFLAG_LOAD_INTRINFO
Same as INTR_GENFLAG_LOAD_SYSPAGE, except that it loads a pointer to this structure.
INTR_GENFLAG_LOAD_INTRMASK
Used only by EOI routines for hardware that doesn't automatically mask at the chip level. When the EOI routine is about to reenable interrupts, it should reenable only those interrupts that are actually enabled at the user level (e.g. managed by the functions InterruptMask() and InterruptUnmask()). When this flag is set, the existing interrupt mask is stored in a register for access by the EOI routine. A zero in the register indicates that the interrupt should be unmasked; a nonzero indicates it should remain masked.
INTR_GENFLAG_NOGLITCH
Used by the interrupt ID code to cause a check to be made to see if the interrupt was due to a glitch or to a different controller. If this flag is set, the check is omitted — you're indicating that there's no reason (other than the fact that the hardware actually did generate an interrupt) to be in the interrupt service routine. If this flag is not set, the check is made to verify that the suspected hardware really is the source of the interrupt.
INTR_GENFLAG_LOAD_CPUNUM
Same as INTR_GENFLAG_LOAD_SYSPAGE, except that it loads a pointer to the number of the CPU this structure uses.
INTR_GENFLAG_ID_LOOP
Some interrupt controllers have read-and-clear registers indicating the active interrupts. That is, the first read returns a bitset with the pending interrupts, and then immediately zeroes the register. Since the interrupt ID callout can return only one interrupt number at a time, that means that we might fail to process all the interrupts if there's more than one bit on in the status register.

When INTR_GENFLAG_ID_LOOP is on, the kernel generates code to jump back to the ID callout after the EOI has finished.

In the ID callout, you need to allocate read-write storage as per the usual procedures. This storage is initially set to zero (done by default). When the callout runs, the first thing it does is check the storage area:

  • If the storage is nonzero, the callout uses it to identify another interrupt to process, knocks that bit down, writes the new value back into the storage location and returns the identified interrupt number.
  • If the storage location is zero, the callout reads the hardware status register (clearing it) and identifies the interrupt number from it. It then knocks that bit off, writes the value to the storage location, and then returns the appropriate interrupt number.
  • If both the storage and hardware register are zero, the routine returns -1 to indicate no interrupt is present as per usual.