Linux Kernel中local_irq_enable()和local_irq_disable()的实现
快速链接: . 说明: 在默认情况下,本文讲述的都是ARMV8-aarch64架构,linux kernel 5.14
local_irq_enable()和local_irq_disable()的实现,其实就是操作的DAIF寄存器(PSTATE), 命令分别是
-
msr daifclr, #3 //enable msr daifset, #3 //disable
(1)、 local_irq_disable()
(linux/include/linux/irqflags.h)
#define local_irq_disable() do { raw_local_irq_disable(); } while (0)
#define raw_local_irq_disable() arch_local_irq_disable()
(linux/arch/arm64/include/asm/irqflags.h)
static inline void arch_local_irq_disable(void)
{
if (system_has_prio_mask_debugging()) {
u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
}
asm volatile(ALTERNATIVE(
"msr daifset, #3 // arch_local_irq_disable",
__msr_s(SYS_ICC_PMR_EL1, "%0"),
ARM64_HAS_IRQ_PRIO_MASKING)
:
: "r" ((unsigned long) GIC_PRIO_IRQOFF)
: "memory");
}
(2)、 local_irq_enable()
(linux/include/linux/irqflags.h)
#define local_irq_disable() do { raw_local_irq_disable(); } while (0)
#define raw_local_irq_enable() arch_local_irq_enable()
(linux/arch/arm64/include/asm/irqflags.h)
static inline void arch_local_irq_enable(void)
{
if (system_has_prio_mask_debugging()) {
u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
}
asm volatile(ALTERNATIVE(
"msr daifclr, #3 // arch_local_irq_enable",
__msr_s(SYS_ICC_PMR_EL1, "%0"),
ARM64_HAS_IRQ_PRIO_MASKING)
:
: "r" ((unsigned long) GIC_PRIO_IRQON)
: "memory");
pmr_sync();
}
