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

标签 c x86-64 interrupt osdev nmi

我已经读到,为了根据 Intel 的系统编程指南(第 3 卷第 9.9 章)暂时关闭分页,我应该在做任何其他事情之前禁用中断。我可以使用 cli 轻松禁用可屏蔽中断,但是手册中所有关于禁用 NMI 的内容都是

NMI interrupts can be disabled with external circuitry.(Software must guarantee that no exceptions or interrupts are generated during the mode switching operation.)

我在 this OSDEV page 找到了看起来像 C 代码的禁用 NMI 的代码但我不太明白这是什么意思

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

 void NMI_disable() {
    outb(0x70, inb(0x70) | 0x80);
 }

如果不知道函数 outb 和 inb 的作用,感觉代码没有上下文并且没有意义。

最佳答案

CPU 有一个用于触发 NMI 的不可屏蔽中断 (NMI) 引脚(或等效硬件)。有外部电路(或等效硬件)来防止 NMI 到达 CPU。由于 80286 使用的机制是通过与 CMOS/Realtime Clock 关联的 IO 端口(RTC) Controller 。今天的硬件仍然在模仿同样的机制。

CMOS/RTC 端口为 0x70 和 0x71。端口 0x70 用于选择要读取或写入的 CMOS/RTC 地址。 CMOS/RTC 地址的前 2 位不构成实际地址的一部分。最高位被重新用作 NMI 开关。如果您将字节写入端口 0x70,其中第 7 位(最高有效位)已设置,NMI 将被禁用。如果您写入第 7 位清零的值,则启用 NMI。

inboutb 函数是低级别的C 包装器IN (字节)和 OUT (字节)指令。这些指令读写IO端口空间。来自 NMI_enableC 代码:

outb(0x70, inb(0x70) & 0x7F);

相当于:

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 */

0x7f 是位模式 01111111。将 01111111 与当前字节进行与操作会清除最高位(启用 NMI)。

来自 NMI_disableC 代码:

outb(0x70, inb(0x70) | 0x80);

相当于:

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 */

0x80 是位模式 10000000。将 10000000 与当前字节进行或运算设置最高位(禁用 NMI)。

关于c - 如何以编程方式禁用不可屏蔽中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55394608/

相关文章:

c++ - 从 C++ 迁移到 C

C while循环不执行

c - 更大的整数宽度

glibc可以编译成一个目标文件吗

performance - 为什么引入无用的 MOV 指令会加速 x86_64 汇编中的紧密循环?

c++ - "assert"是什么函数?

x86 - 是否可以设置在 cpu 写入特定地址时中断的中断?

java - 计数器应用程序不会停止

linux - MSI 中断如何在 Linux 驱动程序中工作?

interrupt - 这是禁用 PIC24 中断的安全方法吗?