本文共 2814 字,大约阅读时间需要 9 分钟。
本专题主要介绍ARM64架构下的中断管理机制,重点分析Linux内核中gic_handle_irq函数的处理流程。以下将从gic_handle_irq的实现细节、中断处理机制以及相关优化措施等方面展开讨论。
gic_handle_irq是ARM64体系结构下处理中断的核心函数。该函数主要负责从底层硬件中断处理进入内核中断处理逻辑,并通过调用handle_domain_irq完成中断的上下文切换。
gic_handle_irq的实现代码如下:
static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs){ struct gic_chip_data *gic = &gic_data[0]; void __iomem *cpu_base = gic_data_cpu_base(gic); do { irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); irqnr = irqstat & GICC_IAR_INT_ID_MASK; if (unlikely(irqnr >= 1020)) break; if (static_branch_likely(&supports_deactivate_key)) writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); isb(); if (irqnr <= 15) smp_rmb(); this_cpu_write(sgi_intid, irqstat); handle_domain_irq(gic->domain, irqnr, regs); } while (1);}
while (1)
循环的退出条件基于以下逻辑:当GIC的GICC_IAR寄存器中的所有位都为1时,中断处理完成,进入下一个中断处理阶段。
handle_domain_irq
是一个通用的中断处理函数,主要负责将硬中断转换为软中断,并根据中断类型(如SGI中断或普通中断)分别调用相应的处理函数。
int handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, struct pt_regs *regs){ __handle_domain_irq(domain, hwirq, true, regs); unsigned int irq = hwirq; irq_enter(); irq = irq_find_mapping(domain, hwirq); generic_handle_irq(irq); irq_exit();}
readl_relaxed
读取中断状态,完成中断的ACK操作。tasklet
或workqueue
等处理。irq_enter
和 irq_exit
分别用于进入和退出中断上下文。
void irq_enter(void){ rcu_irq_enter(); irq_enter_rcu(); if (is_idle_task(current) && !in_interrupt()) { local_bh_disable(); tick_irq_enter(); _local_bh_enable(); } __irq_enter(); account_irq_enter_time(current); preempt_count_add(HARDIRQ_OFFSET); __preempt_count_add(val); u32 pc = READ_ONCE(current_thread_info()->preempt.count); pc += val; WRITE_ONCE(current_thread_info()->preempt.count, pc); lockdep_hardirq_enter();}
void irq_exit(void){ __irq_exit_rcu(); local_irq_disable(); account_irq_exit_time(current); preempt_count_sub(HARDIRQ_OFFSET); if (!in_interrupt() && local_softirq_pending()) { invoke_softirq(); } tick_irq_exit(); rcu_irq_exit(); lockdep_hardirq_exit();}
local_softirq_pending
用于检查是否有软中断(如tasklet
或workqueue
)等待处理。通过检查local_softirq_pending_ref
,可以快速判断中断状态。
irq_enter
和 irq_exit
函数通过修改preempt.count
来管理中断上下文。preempt_count_add
和 preempt_count_sub
用于递增和递减硬中断计数,同时local_bh_disable
和 local_bh_enable
用于管理软中断。
通过分析gic_handle_irq
函数及其相关处理流程,可以清晰地了解ARM64体系结构下的中断管理机制。从硬中断到软中断的转换,再到中断上下文的管理,都体现了Linux内核对中断处理的高效设计。
转载地址:http://csqd.baihongyu.com/