Disabling interrupts
Disabling Interrupts
When SeaBIOS is loading in QEMU, it will disable interrupts
1 | 10 0xfd15f: cli |
The #10 instruction cli
above is to disable interrupts, but how it works?
Interrupt is divided into Hardware
and Software
ones. For Hardware interrupts
, there are maskable
and non-maskable
ones.
On the FLAGS register of the CPU, bit 9 is IF (Interrupt flag), who determines whether or not the CPU will respond immediately to maskable hardware interrupts.
The instruction cli
is to set IF to 0
, so we can disable the maskable hardware interrupts. Instead, the instruction sti
is to set IF to 1
, namely enable it.
But as you see, non-maskable hardware interrupts can still be disabled at #13 , Why?
From Non Maskable Interrupt - OSDev Wikiand https://bochs.sourceforge.io/techspec/PORTS.LST
We can know that the MSB of 0x70 is to control the NMI(Non Maskable Interrupt) and it’s shared with CMOS RAM index
1
2
3
4
5
6
7 0070 w CMOS RAM index register port (ISA, EISA)
bit 7 = 1 NMI disabled
= 0 NMI enabled
bit 6-0 CMOS RAM index (64 bytes, sometimes 128 bytes)
any write to 0070 should be followed by an action to 0071
or the RTC wil be left in an unknown state.From OSDev Wiki, you can disable NMI like this
1
2
3
4 void NMI_disable() {
outb(0x70, inb(0x70) | 0x80);
inb(0x71);
}So you read 0x70 using
inb
, and you get the binary value of it. Then make a BoolOR
calculation:
var MSB LSB inb(0x70) X X X X X X X X 0x80 1 0 0 0 0 0 0 0 Result 1 ? ? ? ? ? ? ? Then you write the result to 0x70 again, whose MSB must be 1. So the NMI is now disabled.
Vice versa, when enabling
1
2
3
4 void NMI_enable() {
outb(0x70, inb(0x70) & 0x7F);
inb(0x71);
}The MSB of the result must be 0, so NMI will be enabled.
Let’s use GDB to set a breakpoint before the out
instruction executes
1 | (gdb) b *0xfd167 |
Now %al
is 0x8f
or1000 1111
and its MSB is 1
so NMI will be disabled after this instruction.
Cuz the reference mentioned:
any write to 0070 should be followed by an action to 0071
or the RTC wil be left in an unknown state
That’s why next instruction(#14) is 0xfd169: in $0x71, %al
Disabling interrupts