CPU 是否在调用中断处理程序之前禁用本地 CPU 上的所有中断?或者它是否只禁用正在服务的特定中断线?
5 回答
x86 在跳转到中断向量之前禁用所有本地中断(当然 NMI 除外)。Linux 通常屏蔽特定中断并重新启用其余中断(未屏蔽),除非将特定标志传递给中断处理程序注册。
请注意,虽然这意味着您的中断处理程序不会在同一个 CPU 上与自身竞争,但它可以并且将与在 SMP / SMT 系统中的其他 CPU 上运行的自身竞争。
通常(至少在 x86 中),中断会禁用中断。
当收到中断时,硬件会做这些事情:
1. 将所有寄存器保存在预定位置。
2. 将指令指针(AKA 程序计数器)设置为中断处理程序的地址。
3. 将控制中断的寄存器设置为禁用所有(或大部分)中断的值。这可以防止另一个中断中断这个中断。
一个例外是不能被禁用的 NMI(不可屏蔽中断)。
是的,没关系。我还想添加我认为可能相关的内容。
在许多现实世界的驱动程序/内核代码中,经常使用“下半部分”(bh)处理程序——tasklet、softirqs。这些 bh 在中断上下文中运行,并且可以与 SMP(尤其是软中断)上的上半部分(th)处理程序并行运行。
当然,最近有一个向主线移动(主要是从 PREEMPT_RT 项目迁移的代码),它基本上摆脱了“bh”机制——所有中断处理程序都将在所有中断禁用的情况下运行。不仅如此,处理程序(可以)转换为内核线程——这些是所谓的“线程”中断处理程序。
直到今天,选择仍然留给开发人员——您可以使用“传统”th/bh 样式或线程样式。
参考和详细信息:
引用 Intel 自己写得非常出色的“Intel® 64 and IA-32 Architectures Software Developer's Manual”,第 1 卷,第 6-10 页:
如果通过中断门调用中断或异常处理程序,处理器将清除 EFLAGS 寄存器中的中断使能 (IF) 标志,以防止后续中断干扰处理程序的执行。当通过陷阱门调用处理程序时,IF 标志的状态不会改变。
所以要清楚 - 是的,CPU在调用中断处理程序之前有效地“禁用”了所有中断。正确描述,处理器只是触发一个标志,使其忽略所有中断请求。除了可能不可屏蔽的中断和/或它自己的软件异常(请有人纠正我,未验证)。
我们希望 ISR 是原子的,没有人应该能够抢占 ISR。
因此,ISR 会禁用本地中断(即当前处理器上的中断),并且一旦 ISR 调用 ret_from_intr() 函数(即我们完成了 ISR),当前处理器上的中断就会再次启用。
如果发生中断,它将由另一个处理器(在 SMP 系统中)提供服务,并且与该中断相关的 ISR 将开始运行。
在 SMP 系统中,我们还需要在 ISR 中包含适当的同步机制(自旋锁)。