如何以编程方式禁用不可屏蔽的中断?

Kee*_*ame 5 c x86-64 interrupt osdev nmi

我读过,为了根据英特尔的系统编程指南(第3卷第9.9章)暂时关闭分页,我应该先禁用中断,然后再执行其他操作。我可以使用cli轻松禁用可屏蔽中断,但是所有有关禁用NMI的手册都说

NMI中断可以通过外部电路禁用(软件必须保证在模式切换操作期间不会产生异常或中断。)

我在此OSDEV页面上找到了类似于C代码的用于禁用NMI的代码,但我不太明白它的含义。

void NMI_enable() {
    outb(0x70, inb(0x70) & 0x7F);
 }

 void NMI_disable() {
    outb(0x70, inb(0x70) | 0x80);
 }
Run Code Online (Sandbox Code Playgroud)

感觉代码没有上下文并且在不知道outb和inb函数做什么的情况下是没有意义的。

Mic*_*tch 7

CPU 具有用于触发 NMI 的不可屏蔽中断 (NMI) 引脚(或等效硬件)。有外部电路(或等效硬件)来防止 NMI 到达 CPU。自 80286 以来,所使用的机制是通过与CMOS/实时时钟(RTC) 控制器相关联的 IO 端口。今天的硬件仍然模仿这种相同的机制。

CMOS/RTC 端口是 0x70 和 0x71。端口 0x70 用于选择要从中读取或写入的 CMOS/RTC 地址。CMOS/RTC 地址的高 2 位不构成实际地址的一部分。最上面的位被重新设计为 NMI 切换。如果向端口 0x70 写入一个字节,其中设置了第 7 位(最高有效位),则禁用 NMI。如果写入第 7 位清除的值,则启用 NMI。

inboutb功能是Ç周围低电平包装IN(字节)和OUT(字节)的指令。这些指令读写IO口空间。这个C代码来自NMI_enable

outb(0x70, inb(0x70) & 0x7F);
Run Code Online (Sandbox Code Playgroud)

相当于:

uint8_t curbyte = inb(0x70);   /* Read current port 0x70 state */
outb(0x70, curbyte & 0x7F);    /* Update current state by clearing NMI bit */
                               /* and write new value back to port 0x70 */
Run Code Online (Sandbox Code Playgroud)

0x7f 是位模式 01111111。 01111111 与当前字节的 AND 运算清除最高位(启用 NMI)。

这个C代码来自NMI_disable

outb(0x70, inb(0x70) | 0x80);
Run Code Online (Sandbox Code Playgroud)

相当于:

uint8_t curbyte = inb(0x70);   /* Read current port 0x70 state */
outb(0x70, curbyte | 0x80);    /* Update current state by setting NMI bit */
                               /* and write new value back to port 0x70 */
Run Code Online (Sandbox Code Playgroud)

0x80 是位模式 10000000。ORing 10000000 与当前字节设置最高位(禁用 NMI)。


Pau*_*vie 6

“具有外部电路”表示板上的处理器芯片的NMI引脚之前有门,如果这些门被关闭(关闭),则不会有中断信号到达处理器芯片的NMI引脚。

这些outb呼叫可能会激活/停用这些门。

NMI表示不可屏蔽,这意味着您不能仅使用软件禁用它们。