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

时间:2019-03-28 09:52:18

标签: c x86-64 intel interrupt osdev

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

  

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

我在this OSDEV page找到了类似于C代码的用于禁用NMI的代码,但是我不太明白它的含义

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

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

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

4 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:3)

CPU具有不可触发的中断(NMI)引脚(或等效硬件),用于触发NMI。有外部电路(或等效硬件)可防止NMI到达CPU。从80286开始,使用的机制是通过与CMOS/Realtime Clock(RTC)控制器关联的IO端口进行的。如今,这种相同的机制仍在硬件中被模仿。

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

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

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与当前字节进行AND运算将清除最高位(启用NMI)。

来自NMI_disable C 代码:

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)。

答案 2 :(得分:1)

我已经读到,为了根据英特尔系统编程指南(第3卷第9.9章)暂时关闭分页,我应该先禁用中断,然后再执行其他操作。

英特尔错了。

NMI通常指示严重的硬件故障(尤其是如果您的软件不是故意导致的,特别是如果您未启用“机器检查异常”)。忽略严重的硬件故障(通过屏蔽NMI)会导致极端的未定义行为。不好。

理想情况下,您想要有保证的行为。最简单的方法是确保如果有NMI,则CPU将使三重故障(并重置计算机)。通过将IDT限制设置为零。在启动过程中(当没有最终用户的数据可能丢失时),这是完全可以的。

“不太容易”的方法是使用临时IDT。要关闭分页,可以具有一个标识映射的IDT(以及GDT,堆栈等),以便可以启动NMI处理程序,而不管打开或关闭分页时是否发生NMI。在CPU模式切换期间,可以使用类似的技巧(依赖于IVT / IDT条目大小的改变,这会导致NMI的IVT / IDT条目位于不同的地址,具体取决于“ NMI时的CPU模式”)

理智的人当然不会在启动后临时禁用分页(或进行CPU模式切换);因此,除了在启动过程中“在NMI上保证三重故障”之外,没有其他必要。

答案 3 :(得分:0)

从操作系统开发人员的角度来看,基本上,您可以安全地考虑禁用NMI(即使您确实想出了禁用NMI的方法)。如果在操作系统引导阶段发生NMI,则意味着发生了严重的事情(通常是硬件,电源),机器无法正常工作,因此请立即停止操作系统,因为您的操作系统仍然无法正常工作。