Disabling interrupts

Disabling Interrupts

When SeaBIOS is loading in QEMU, it will disable interrupts

1
2
3
4
5
6
7
8
10 0xfd15f: cli                        
11 0xfd160: cld
12 0xfd161: mov $0x8f, %eax
# Here to disable Maskable Hardware interrupts

13 0xfd167: out %al, $0x70
14 0xfd169: in $0x71, %al
# And disable Non-maskable Hardware interrupts

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 Bool OR 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
2
3
4
5
6
7
8
9
10
(gdb) b *0xfd167
Breakpoint 1 at 0xfd167
(gdb) c
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
[f000:d167] 0xfd167: out %al,$0x70
0x0000d167 in ?? ()
(gdb) info register al
al 0x8f -113

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

Author

BakaFT

Posted on

2021-10-29

Updated on

2023-12-28

Licensed under

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×