本文记录arm64相关的关于irq的基本知识点。
代码为linux 4.0版本。
Q1:如何开启和关闭local irq?
这里关闭irq,是指关闭local CPU的中断响应,它有两层含义:
1.无论何种类型的中断,当前CPU都暂时不响应了;
2.其它CPU不受影响。
以关闭中断为例,linux提供的api在include\linux\irqflags.h中定义
#define raw_local_irq_disable() arch_local_irq_disable()
#define local_irq_disable() do { raw_local_irq_disable(); } while (0)
所以,最终的实现是在各个arch目录下,对于arm64,是在
arch\arm64\include\asm\irqflags.h
static inline void arch_local_irq_disable(void)
{
asm volatile(
"msr daifset, #2 // arch_local_irq_disable"
:
:
: "memory");
}
如何理解这里的汇编指令?
msr daifset, #2
先看看DAIF的含义。
所以,要关闭IRQ,就把I的bit置1,要关闭FIQ,就把F的bit置1.
msr和mrs指令是专门用来操作特殊寄存器的,分别是写和读特殊寄存器,而不是使用mov指令。
因此,得到这几个命令的含义如下
msr daifset, #1 //关闭FIQ
msr daifset, #2 //关闭IRQ
msr daifset, #4 //关闭Async
msr daifset, #8 //关闭Dbg
msr daifclr, #1 //开启FIQ
msr daifclr, #2 //开启IRQ
msr daifclr, #4 //开启Async
msr daifclr, #8 //开启Dbg
Q2:进入中断异常处理前,谁关闭的中断?
硬件会关闭中断,而不是软件。
见参考资料2的10.5 Interrupt handling的这段内容:
When the processor takes an exception to AArch64 execution state, all of the PSTATE interrupt masks is set automatically. This means that further exceptions are disabled.
If software is to support nested exceptions, for example, to allow a higher priority interrupt to interrupt the handling of a lower priority source, then software needs to explicitly re-enable interrupts.
也就是说,在进入entry.S中的el0_irq或者el1_irq前,硬件已经关闭了当前CPU的所有中断。
这里有个问题?那中断结束后开中断是软件完成的吗?
我猜测应该也是硬件完成的,虽然执行软中断时会开启中断,但之后又关闭了,没找到哪里有做这件事。
参考资料:
1.DDI0487D_b_armv8_arm.pdf
2.DEN0024A_v8_architecture_PG.pdf