exception - 是否有任何 CPU 状态位指示处于 x86 和 x86-64 中的异常/中断处理程序中?
问题描述
是否有任何位指示在和CPU-state
中的异常/中断处理程序中?换句话说,我们能否仅根据寄存器的状态来判断当前执行的是主线程还是异常处理程序?x86
x86-64
CPU
解决方案
不,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 你已经完成了这个中断,所以它可以提供另一个这个或更低优先级的中断。
推荐阅读
- laravel - 使用单个模板完全从 JSON 数据中使用 Vue.js 编译多个数据表
- sml - SML 从数据类型调用函数
- android - 即使在 Keep-Alive 标头之后,使用 okhttp 进行改造也非常慢
- jquery - Jquery 返回 $ 未定义的迭代交互
- laravel - Laravel join 只返回连接表的第一行
- php - Net_SSH2 的输出被切断了?
- r - 在散点图上绘制最大值和最小值(基于列值)
- css - 如何将导航栏品牌内的两行文本与图像对齐
- swift - 如何防止在拖动 UIPickerView 时触发按钮?
- javascript - 浏览器中 Date.now() 的准确性