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();
}
经验分享 程序员 微信小程序 职场和发展