首页 > 解决方案 > 是否有任何 CPU 状态位指示处于 x86 和 x86-64 中的异常/中断处理程序中?

问题描述

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

标签: exceptionx86x86-64cpu-registersinterrupt-handling

解决方案


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

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

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

但是,当您处理完外部中断时,可能需要告知中断控制器(逻辑上在 CPU 内核之外,但实际上是现代 CPU 的一部分)。(不是软件中断或异常)。 https://wiki.osdev.org/IDT_problems#I_can_only_receive_one_IRQ显示了outb让旧版 PIC 满意所需的说明。(我不知道这是否适用于更现代的中断方式,例如 MSI-X 消息信号中断。OSdev wiki 页面的这一部分可能特定于让 BIOS 模拟传统 IBM-PC 东西的玩具操作系统。 ) 但无论哪种方式,这仅适用于外部中断,如 PS/2 键盘控制器、硬盘 DMA 完成或其他任何(不是例外),所以它与你的无关Linux 系统调用是否在异常处理程序中执行?问题。


schedule()缺少异常状态意味着在从中断处理程序调用之前,您无需运行任何特殊指令来“确认”异常。您所要做的就是确保在应该或不应该启用中断时启用或不启用中断。(sti/ cli,或pushf/popf保存/恢复旧的中断状态。)当然,您的软件数据结构保持一致并适合您正在做的事情。但是,您无需专门做任何事情来让 CPU 满意。

这与用户空间不同,信号处理程序应该告诉操作系统它已经完成,而不是只是跳到某个地方并无限期地运行。(在 Linux 中,信号处理程序可以修改主线程程序计数器,以便sigreturn(2)在交付时以外的地方恢复执行。) 如果 POSIX 或 Linux 信号是您想知道的中断/异常的(心理)模型,不,不是那样的。


有一种中断优先级机制(x86-64 中的 CR8,或 LAPIC TPR(任务优先级寄存器)),但它不会CPU 传递中断时自动设置。您可以设置一次(例如,如果您有很多高优先级的中断要在此核心上处理),它会在中断之间持续存在。(如何使用 CR8 寄存器在 x86-64 CPU 中确定中断的优先级?)。

sti它只是一个过滤器,用于在启用中断时( RFLAGS 中的 IF=1 位)可以将哪些中断号传递给该内核。显然 Windows 使用了它,或者早在 2007 年就使用了它,但 Linux 没有(或没有)。

这不像你必须告诉 CPU / LAPIC 你已经完成了这个中断,所以它可以提供另一个这个或更低优先级的中断。


推荐阅读