PCI(Peripheral Component Interconnect,外部不见互连标准)总线是个人电脑中使用的最多的总线。目前笔者主要关心三个方向:(基于ARM架构的)
1、由PCIE总线连接网卡,形成网卡驱动
2、由PCIE总线连接显卡或NPU,并关心通过显卡或NPU的进一步互连,如到显示器等
3、由PCIE总线转USB接口,连接一些常见物件不如鼠标键盘;或者转nvme等block设备
PCIE总线
PCI总线是一个硬件抽象概念,CPU通过访问HOST的地址空间进而与PCI旗下的设备进行交互。这里需要注意,HOST桥本身的地址空间大小是确定的(至少是可以通过配置确定的)。
具体来说,PCI总线需要解决如下3个问题:
1、PCI总线需要保留一定的地址空间用来给PCI桥或PCI设备进行配置。
2、PCI需要可以进行拓展,由CPU控制的一个HOST需要可以新增PCI设备或者新增HOST。
3、PCI需要反馈各PCI设备的中断表、事件表、DMA数据搬移等触发类型的动作,即需要完成总线下各PCI设备的响应。
对于CPU来说,HOST的地址空间实际上就是CPU内部的PCIE主机控制器的地址空间。对ARM架构来说,在进行内存初始化时,会将Host桥的地址映射寄存器通过kernel里的pci_scan_root_bus_bridge函数完成配置,在CPU对特定地址进行访问时,Host桥会自动翻译为对寄存器地址的访问。
在完成HOST地址往内存的映射后(需要首先对内存进行页表化,整出虚拟地址空间,然后再在映射时描述基+大小的一组变量,投影到内存地址空间中去),对于BAR内部地址的分布,根据PCIE标准,也可以分为配置空间、扩展配置空间、设备特定寄存器等不同的寄存器地址区域。(在kernel中可以前往/include/linux/pci_regs.h文件查询)
认为BAR空间地址内部的地址分为:配置空间、前256字节,主要包含Vendor ID、Device ID、BAR寄存器等信息;扩展配置空间,256到4KB,包含MSI-X、AER等能力结构信息;设备特定寄存器,由BAR映射的MMIO空间后,各设备本身通过设备厂商的定义,通过struct pci_dev与resource数组完成对应的管理。
PCIE事务
PCI的核心事务是一次完整的总线操作过程。
1、传统PCI总线事务
事务由信号线(地址/数据服用线、命令线、控制信号线等)经过仲裁、地址或命令执行、数据传输、终止等阶段完成。
2、PCIE总线事务
PCIE总线依赖数据包(TLP)进行,TLP本身包含TLP头(描述事务类型、路由信息、数据长度、流量类别等)、数据载荷、校验。
对于PCIE事务来说,分为Posted事务(不需要响应,UDP式)与Non-Posted事务(需要响应,TCP式,接收后需要返回一个TLP报文作为响应)。
PCIE中断
MSI-X的本质是中断同构内存写。
1、系统初始化配置阶段
在设备枚举阶段,系统软件会为设备分配MSI中断资源,将目标内存地址(Message Address)和中断数据(Message Data)写入MSI Capability寄存器中。这个目标地址对应中断控制器(如ARM下的GIC)的特定寄存器。
2、设备发起中断
当PCIE设备触发中断时,会构造一个内存写的TLP包。这个包会包含一些必要的基本信息,比如地址字段、数据字段(中断向量号)、TLP类型等。
3、由Root Complex识别并转发
TLP通过PCIE链路到达Root Complex后,RC判断不是普通的内存写入而是MSI中断消息,则它会将这个写操作直接转换为系统总线上的中断消息,直接送达中断控制器
4、中断控制器触发CPU中断
RC(即GIC)收到中断后,根据向量号,向CPU核心发送中断信号,CPU随即进入中断处理程序。
PCIE的API
在kernel中,管理PCIE中断(即IRQ号与IRQ动作管理)由一系列驱动封装的API进行:
1、核心分配函数
在/drivers/pci/msi.c文件的pci_alloc_irq_vectors_affinity函数中具体实例化了核心分配函数,用于申请MSI-X中断向量。
2、IRQ号获取
申请完MSI-X中断后,再由/drivers/pci/msi.c文件的pci_irq_vector获取当前IRQ号分布情况,然后通过/kernel/irq/manage.c文件的request_threaded_irq来注册kernel的中断处理函数。
3、中断亲和性绑定
亲和性是一种SMP的属性,主要用于多核时的中断处理负载分担。在pci_alloc_irq_vectors注册时,如果入参携带PCI_IRQ_AFFINITY标志后,会自动将中断分散到可用CPU上。
4、资源释放
PCI设备执行移除操作时,需要在对应finit式函数中释放已分配的中断资源