菜单

kaoqi
kaoqi
发布于 2026-07-27 / 6 阅读
0
0

MSI中断

MSI中断的意思是,硬件设备通过向特定内存地址写入数据来通知系统处理中断,目前MSI-X是MSI的升级版本(Message Signaled Interrupts Extended)。

MSI是从设备写一个特殊的地址,导致CPU接收到一个中断。传统上说,基于针脚的PCI中断通常在几个设备之间共享。为了支持这一点,内核必须调用每个与中断相关的中断处理程序,导致整个系统的性能降低。

当一个设备将数据写入内存,然后引发一个基于引脚的中断时,有可能在所有的数据到达内存之前,中断就已经到达了。为了确保所有的数据已经到达内存中,中断处理程序必须在引发中断的设备上读取一个寄存器。PCI事务排序规则要求所有的数据再返回寄存器的值之前到达内存。使用MSI可以避免这个问题,因为中断产生的写入不能通过数据写入,所以当中断发生时,驱动程序知道所有的数据已经到达内存中。(这里需要结合PCI的协议准则详细解释一下PCI的事务)

如何使用MSI,PCI设备被初始化为使用基于引脚的中断。设备驱动程序必须将设备设置为使用MSI或者MSI-X。为了支持MSI或者MSI-X,内核在构建时必须启用CONFIG_PCI_MSI选项。大部分沉重的工作时PCI层作为驱动程序完成的。驱动程序只需要请求PCI层为这个设备设置MSI功能。

int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, unsigned int max_vecs, unsigned int flags);

这个函数使用了MSI-X的中断向量,返回分配的向量数量或一个符的错误。

从内核的角度来说,这个东西要么时一个MSI-X的类型,要么会回退回一个IRQ的向量。

中断的触发由内存写事务开启,核心在于TLP写入中断控制器地址。

1、设备内部逻辑产生中断事件,映射到特定向量索引

2、查表与判掩,硬件根据索引读取MSI-X Table对应条目

3、组装TLP,硬件构造Memory Write TLP,目的地址=Msg Addr,数据=Msg Data

4、总线传输,TLP经PCIE链路传至Root Complex,路由至目标中断控制器,如x86、LAPIC/IOAPIC、ARM GIC-ITS等

5、控制器解码,中断控制器解析地址定位目标CPU/Hart,解析Data获取中断向量号,直接拉起对应中断信号

6、CPU响应,CPU挂起当前任务,查IDT/向量表跳转至ISR处理;处理完后写EOI/清Pending位复位状态。

正是因为PCIE或者说MSI的这种性质,可以具体解释BAR空间的作用。

MSI-X Capability空间,存放MSI-X的配置,存使能位、全局掩码、表大小、Table指针、PBA指针。

MSI-X Table空间(位于BAR空间,Base Address Register),PCIE设备通过基址寄存器向主机宣告并映射地址资源区域,用于实现主机对设备内部寄存器或存储单元的内存映射IO或IO端口访问。

PBA(Pending Bit Array,也位于BAR空间),PCIE MSI-X中断机制中专用的位图状态寄存器,用于记录各种中断向量的待处理状态。

PBA和MSI-X中断向量表一同映射在PCIE设备的BAR空间中,系统软件通过PBA BIR寄存器指向BAR,通过PBA Offset寄存器指向其在该BAR内的偏移地址,这两个合起来实现对中断向量的状态管理。

由MSI-X可以产生中断,经过ITS后传递给GIC。

ITS(Interrupt Translation Service)是ARM GICv3架构中的一个硬件模块,可以理解为一个中断翻译引擎。它的核心任务就是把PCIE设备发出的MSI-X消息翻译成GIC能直接处理的LPI中断,然后路由到目标CPU。

ITS获取到MSI-X的中断消息中包含两个核心参数,通过DeviceID知道请求者的ID,标识对应设备,通过EventID标识设备内部的事件号。ITS在获取上述两个关键参数后,通过三级查表:设备表,以DeviceID为索引,找到该设备对应的中断翻译表指针;中断翻译表,以EventID为索引,找到对应的LPI中断号;集合表,以集合号为索引,找到目标CPU对应的重分发器的地址。经过这三级映射,ITS完成了从“哪个设备的哪个事件”到"哪个CPU的哪个LPI中断号"的完整翻译。

LPI(Locality-specific Peripheral Interrupt),是ARM GICv3/v4引入的一种全新中断类型。LPI在内存中标记挂起后,对端CPU首先响应中断,通过读取GIC中断应答器获取LPI中断号,然后调用驱动注册的中断处理函数。处理完成后,软件向GIC写入中断结束寄存器,充分发起清除挂起表中的对应位,整个中断生命周期结束。

总的来说,这里对应的kernel源代码可以追溯到三个主要driver:

1、/drivers/pci

2、/drivers/irq

3、drivers/irqchip


评论