Hi,
Jezze wrote:
Let's say I have enabled interrupts but has not yet installed an interrupt handler for anything except something very basic that will just ignore every incoming interrupt and return back to the previous state. During this time the PIT or the keyboard could fire an interrupt (depending on what the bootloader left their state in) but because no interrupt handler is installed for them yet there is no code that will send the EOI to the APIC and therefor no new interrupts will be sent from the APIC again. So far so good.
During boot; the "most correct" sequence (assuming PC BIOS) is:
- mask all IRQs in the PIC
- with interrupts enabled (STI) do a dew dummy instructions (e.g. NOP, NOP) to make sure the BIOS has a chance to handle any IRQs that were received before you masked them. Failure to do this can cause "PIC jam" later.
- Don't bother doing CLI - the only IRQs that are possible now are IPIs that you send yourself and NMIs.
- Set the IDT limit to zero. NMIs normally indicate serious hardware failures and therefore shouldn't be ignored; but your boot code isn't prepared to properly handle an NMI at this stage (especially if an NMI occurs while you're switching CPU modes). Simple solution is to make sure NMIs cause a reset/triple fault.
- Switch to protected mode (and/or long mode)
- Install a suitable IDT (including NMI handler)
- Disable PCI devices (except bridges, the "PCI to LPC brige" and the video card if you're using it) by writing 0xFFFF to their Device Control register in PCI configuration space. This makes sure that a device can't generate a level triggered interrupt before you've installed a suitable device driver; even if the IRQ is shared by several devices and that IRQ is unmasked in the PIC or IO APIC. If a device's IRQ is unmasked in the PIC or IO APIC and a "device without a driver" does generate a (level triggered) interrupt, you end up with an "IRQ flood" (e.g. where you get an interrupt, send an EOI, get the same interrupt again, send an EOI, ...).
- Intialise device drivers. For each device you would:
- If the device is PCI, enable the device by writing 0x0000 to the Device Control register in PCI configuration space.
- Start initialising the device (including any reset, and including performing any self tests it has)
- Install the device driver's interrupt handler/s (if any)
- Make sure the interrupt/s are unmasked in the PIC or IO APIC (if any)
- Finish initialising the device
Note that you should be able to bring a device online and take a device offline. For example, if a PCI device's driver crashes (possibly while the device is in the middle of a bus mastering transfer with all sorts of interrupts about to happen) then you'd want to write 0xFFFF to the device's Device Control register in PCI configuration space to stop it; then let the user download/install a new device driver; then start the new device driver in the same way as above.
Jezze wrote:
Interrupts are enabled in order to do syscalls for which there exist handlers.
Software interrupts (e.g. "int 0x80") are not IRQs and are not effected by the IF flag in EFLAGS (e.g. CLI/STI).
Cheers,
Brendan