interrupt flags - ceragon/LinuxDoc GitHub Wiki

flags 寄存器与中断

保存 flags 寄存器

#define local_save_flags(flags)				\
    do {						\
//      raw_local_save_flags(flags);		
        typecheck(unsigned long, flags);    \
        flags = arch_local_save_flags();    \
    } while (0)
static inline unsigned long arch_local_save_flags(void){
//	return native_save_fl();
    unsigned long flags;

	// “=rm”在这里是安全的,
    // 因为“pop”在评估其有效地址之前会调整堆栈——这是“pop”指令的记录行为的一部分。 
	asm volatile("# __raw_save_flags\n\t"
                 // 先将 flags 寄存器压栈,然后再弹出到 flags 对应的寄存器中
		     "pushf ; pop %0" 
		     : "=rm" (flags) // r:编译器指定一个寄存器,m:数据也会输出到内存中
		     : /* no input */
		     : "memory");

	return flags;
}

恢复 flags 寄存器

#define local_irq_restore(flags)			\
    do {						\
//      if (raw_irqs_disabled_flags(flags)) {	
        if ({                        \
                typecheck(unsigned long, flags);    \
                arch_irqs_disabled_flags(flags);    \
            }) {   
            // 如果 IF 的值是0(禁用中断),则中断启用成功。
//			raw_local_irq_restore(flags);	
            typecheck(unsigned long, flags);
            arch_local_irq_restore(flags);
            
//          trace_hardirqs_off();		
		} else {				\
            // 如果 IF 的值是1(启用中断),则说明原本中断就是打开的。
//          trace_hardirqs_on();		
//          raw_local_irq_restore(flags);	
            typecheck(unsigned long, flags);
            arch_local_irq_restore(flags);
        }					\
    } while (0)
static inline int arch_irqs_disabled_flags(unsigned long flags) {
    // X86_EFLAGS_IF = 0x00000200。右边数第10是 IF 标志位
    return !(flags & X86_EFLAGS_IF);
}
static inline void arch_local_irq_restore(unsigned long flags) {
//	native_restore_fl(flags);
    // 将 flags 压栈,并弹出到 flags 寄存器中
    asm volatile("push %0 ; popf"
		     : /* no output */
		     :"g" (flags)
		     :"memory", "cc"); // 本次操作修改了内存,和标志寄存器
}

打开和关闭

#define local_irq_enable() \
    do {                      \
//        trace_hardirqs_on();
//        raw_local_irq_enable();
        arch_local_irq_enable();
    } while (0)

#define local_irq_disable() \
	do {                       \
//        raw_local_irq_disable(); 
        arch_local_irq_disable();
//        trace_hardirqs_off();    
    } while (0)
static inline void arch_local_irq_enable(void) {
//	native_irq_enable();
    // 启用中断
    asm volatile("sti": : :"memory");
}

static inline void arch_local_irq_disable(void) {
//	native_irq_disable();
    // 禁用中断
	asm volatile("cli": : :"memory");
}
⚠️ **GitHub.com Fallback** ⚠️