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函数做什么的情况下是没有意义的。
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。
的inb和outb功能是Ç周围低电平包装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)。
“具有外部电路”表示板上的处理器芯片的NMI引脚之前有门,如果这些门被关闭(关闭),则不会有中断信号到达处理器芯片的NMI引脚。
这些outb呼叫可能会激活/停用这些门。
NMI表示不可屏蔽,这意味着您不能仅使用软件禁用它们。