是否有任何 CPU 状态位指示在 x86 和 x86-64 中的 exception/interrupt 处理程序中?

Are there any CPU-state bits indicating being in an exception/interrupt handler in x86 and x86-64?

是否有任何 CPU-state 位表示在 x86x86-64 中的 exception/interrupt 处理程序中?换句话说,我们是否可以仅根据 CPU 寄存器的状态来判断当前是否正在执行主线程或异常处理程序?

不,CPU 本身(例如控制寄存器)中没有任何位表示“我们处于异常或中断处理程序中”。

但是有一个隐藏状态表明您处于 NMI(不可屏蔽中断)处理程序中。由于您无法通过禁用中断来阻止它们,并且不可阻止的任意 NMI 嵌套会带来不便,因此在您 运行 和 iret 之前不会交付另一个 NMI。即使在 NMI 处理程序期间发生异常(如 #DE div by 0),并且该异常处理程序本身 returns 和 iret 即使你没有完成处理NMI。请参阅 LWN 上的 The x86 NMI iret problem

对于普通中断,如果您不希望在处理此中断时传送另一个中断,则可以禁用中断 (cli)。

但是,中断控制器(逻辑上在 CPU 核心之外,但实际上是现代 CPUs 的一部分)可能需要在处理完外部中断时被告知。 (不是软件中断或异常)。 https://wiki.osdev.org/IDT_problems#I_can_only_receive_one_IRQ 显示了使旧版 PIC 满意所需的 outb 说明。 (我不知道这是否适用于更现代的中断方式,例如 MSI-X 消息信号中断。 OSdev wiki 页面的那部分可能特定于让 BIOS 模拟遗留 IBM-PC 东西的玩具 OSes。)但不管怎样,这仅适用于 外部 中断,如 PS/2 键盘控制器、硬盘驱动器 DMA 完成或其他(不例外),因此它与您的 问题无关。


缺少异常状态意味着在从中断处理程序调用 schedule() 之前,没有特殊指令您必须 运行“确认”异常。您所要做的就是确保中断在应该或不应该的时候启用或不启用。 (sti / cli,或 pushf / popf 到 save/restore 旧的中断状态。)当然,您的软件数据结构保持一致并适用于你在做什么。但是您无需特别做任何事情来让 CPU 开心。

这与 user-space 不同,信号处理程序应该告诉 OS 它已完成,而不是只是跳到某个地方并无限期地 运行ning。 (在 Linux 中,信号处理程序可以修改主线程程序计数器,因此 sigreturn(2) 会在交付时以外的地方恢复执行。)如果 POSIX 或 Linux 信号是您为 interrupts/exceptions 想知道的(心理)模型,不,它不是那样的。


存在中断优先级机制(x86-64 中的 CR8,或 LAPIC TPR(任务优先级寄存器)),但它 不会 在 CPU 发出中断。你可以设置一次(例如,如果你有很多高优先级的中断要在这个核心上处理)并且它在中断中持续存在。 ().

它只是一个过滤器,用于过滤启用中断时可以将哪些中断号传送到该内核(sti,RFLAGS 中的 IF=1 位)。显然 Windows 使用了它,or did back in 2007,但 Linux 没有(或没有)。

您不必告诉 CPU / LAPIC 您已完成此中断,因此它可以发送另一个此优先级或较低优先级的中断。