Linux内核禁止_开启中断和处理器间中断
禁止_开启中断
一、ARM64 架构下全局中断控制函数解析
在 ARM64 架构中,内核通过特定函数实现全局中断的禁止与开启,具体如下:
1. 禁止全局中断
- 函数调用链:
local_irq_disable() --> raw_local_irq_disable() --> arch_local_irq_disable()
。 - 内核源码:
static inline void arch_local_irq_disable(void) { asm volatile( "msr daifset, #2 // 通过汇编设置中断屏蔽位为1,禁止可屏蔽中断响应\n" : : : "memory"); }
- 作用:将处理器中断屏蔽位设为 1,使处理器不响应可屏蔽中断(但不可屏蔽中断 NMI 除外)。
2. 开启全局中断
- 函数:
local_irq_enable()
,底层调用arch_local_irq_enable()
。 - 内核源码:
static inline void arch_local_irq_enable(void) { asm volatile( "msr daifclr, #2 // 清除中断屏蔽位,允许可屏蔽中断响应\n" : : : "memory"); }
- 作用:将中断屏蔽位设为 0,恢复处理器对可屏蔽中断的响应。
3. 保存中断状态并禁止中断
- 函数:
local_irq_save(flags)
。 - 作用:先将当前中断状态存入
flags
,再禁止中断。适用于需恢复中断状态的场景,如:unsigned long flags; local_irq_save(flags); // 保存中断状态并禁止中断 // 临界区代码 local_irq_restore(flags); // 恢复中断状态
4. 恢复中断状态
- 函数:
local_irq_restore(flags)
,与local_irq_save
配合,恢复之前保存的中断状态。
5. 使用注意
local_irq_disable
与local_irq_enable
不可嵌套,否则中断状态混乱。local_irq_save
与local_irq_restore
支持嵌套,因每次保存的状态记录对应层级的中断开关情况。
二、单个中断的禁止与开启
Linux 内核支持针对单个外设中断的控制,灵活屏蔽特定设备中断。
1. 禁止单个外设中断
- 函数:
void disable_irq(unsigned int irq)
。 - 作用:禁止指定中断号
irq
的外设中断,中断控制器不再转发该设备的中断请求。disable_irq(128); // 禁止中断号为128的设备(如网卡)的中断
2. 开启单个外设中断
- 函数:
void enable_irq(unsigned int irq)
。 - 作用:重新开启指定中断号
irq
的外设中断,恢复中断控制器对该设备中断请求的转发。enable_irq(128); // 开启中断号为128的设备的中断
处理器间中断
处理器间中断(Inter-Processor Interrupt)是一种特殊的中断,在多处理器系统中,一个处理器可以向其他处理器发送中断,要求目标处理器执行某件事情。
常见的使用处理器间中断的函数:
对于 ARM64 架构的 GIC 控制器,把处理器间中断称为软件生成的中断,可以写分发器的寄存器以生成处理器间中断(GICD_SGIR 软件生成中断寄存器 Software Generated Interrupt Register)。
负责处理处理器间中断的函数是handle_IPI():
处理处理器间中断的流程如下:
比如处理器正在用户模式(异常级别0)下执行64位应用程序,中断控制器是GIC v2控制器,处理处理器间中断的执行流程如下:
https://github.com/0voice