Linux Kernel ARM64体系中断子系统跟踪

目的

这篇文章基于linux kernel 4.10介绍ARMv8体系架构下,中断子系统的整体设计,并会持续跟踪下去。

读者

本文假设读者已有linux kernel编程经验,或者至少已经读过kernel document中IRQ相关的文档。

总述

最早的8251单片机里面,中断初始化主要分三步:定义中断号,定义中断函数和定义中断向量表。
linux kernel也不外乎如此,只不过为了支持不同的体系结构,不同的硬件设备,做了复杂的抽象。
kernel通过virqhw irq联系起来,通过virqirq_deschw irq和中断处理函数联系起来,
通过irq_chipirq_domain把中断控制器的层级关系建立起来。

在ARM64上,随着平台设备和PCI设备的MSI中断的引入,整个子系统越来越复杂,没有一个整体脉络
的认识,很难理解背后代码变动的含义。   

ARM64中断子系统整体设计

深入之前,再强调下几个认知:

  • linux kernel中通过一个全局的irq_desc数组来保存中断信息
  • 一个hw irq对应一个irq或者virq,hw irq是可以在不同irq_domain重复的
  • irq或者virq通常是irq_desc数组的index

基于4.10的代码,它们之前的关系如下:

ARM64中断子系统类图

再不考虑多个中断控制器的情况下,物理关系如下:

单个中断控制器物理连接图

物理中断触发之后,处理逻辑如下:

中断处理逻辑图

引入多个中断控制器(比如GPIO和多GIC)之后,处理逻辑如下: 

多中断处理逻辑图
多中断处理逻辑图2

引入MSI中断之后

msi中断处理逻辑图

引入平台设备MSI中断之后

平台msi中断处理逻辑图

现在的domain状态

domain图

SMMU处理的例子

smmu图

知道是不会有人点的,但万一有人呢:)