2025年PCI MSIX中断模式总结

PCI MSIX中断模式总结1 pci 中断核心 不管 PCI PCIe 中断机制如何演变 组成整个中断体系的关键要素都包含以下 3 个方面 PCI PCIe 设备本地发起中断请求的机制 从本地将中断请求投递到 CPU 端的机制 CPU 端接收和处理中断的机制 INTx 中断 略 MSI Message Signaled Interrupt MSI X Message

大家好,我是讯享网,很高兴认识大家。

1.pci中断核心

不管PCI/PCIe中断机制如何演变,组成整个中断体系的关键要素都包含以下3个方面:

  • PCI/PCIe设备本地发起中断请求的机制
  • 从本地将中断请求投递到CPU端的机制
  • CPU端接收和处理中断的机制

INTx中断:略。

2.为什么推出MSI和MSI-X机制

为了解决了传统Line-based Interrupt机制的种种限制,包括:

  • 无需经过I/O APIC转发中断,直接通过PCI/PCIe Memory Write Transaction向CPU发送中断,效率更高
  • 每个PCI Function可以支持分配多个中断向量,满足同一个设备有多个不同中断请求的需要
  • 当分配多个中断向量给同1个PCI Function时,提供按中断向量进行屏蔽的功能,更为灵活


讯享网

3.MSI/MSI-X的工作机制

        其演示的过程背景是:PCI Device先通过PCI Memory Write向Memory传输1段数据,当数据传输完成后发1个中断告诉CPU,让中断程序来处理该数据。

1.PCI Device发起Memory Write事务向Memory写入数据,此事务先排队缓存到PCI Bridge的Write Buffer中。

2.PCI Device认为前面的数据已成功写入Memory(实际在PCI Bridge等候),于是发起MSI或MSI-X,它其实是1个Memory Write事务,同样在PCI Bridge中排队。

3.第1步中PCI Device发起的Memory Write事务终于从PCI Bridge Write Buffer释放出来,向上转发到达Memory,即数据成功写入到Memory。

4.因为排在前面的Memory Write事务已经释放,PCI Bridge接着执行MSI/MSI-X对应的Memory Write事务转发,其目标是某个CPU Local APIC。目标Local APIC收到这个Memory Write后知道是发起了中断请求,其中断向量号已包含在这个MSI/MSI-X Memory Write要写的数据中。于是调用执行对应的中断服务程序,在中断服务程序中会在Memory中取用已经传输好的数据。
 

 4. vx下代码实例

入口函数:

LOCAL STATUS vxbPciMSIXMultiProgram ( VXB_DEVICE_ID pDev, int numVectors, struct vxbIntDynaVecInfo * pDynaVec ) 

讯享网

流程1:找打msioffset(pice中msix能力寄存器) 

讯享网 vxbPciConfigExtCapFind(busCtrlID, PCI_EXT_CAP_MSIX, pPciDevice->pciBus, pPciDevice->pciDev, pPciDevice->pciFunc, &msiOffset);

 tips:msix能力寄存器参考如下

 流程二:读Table size

 vxbPciBusCfgRead (pDev, msiOffset + PCI_MSIX_CTL, 2, &msiCtl); tableSize = (msiCtl & PCI_MSIX_CTL_TABLE_SIZE) + 1;

流程三:读table offset

讯享网 vxbPciBusCfgRead (pDev, msiOffset + PCI_MSIX_TABLE, 4, &table); tableOffset = (table & PCI_MSIX_TABLE_OFFSET_MASK);

 流程四:读PBA

vxbPciBusCfgRead (pDev, msiOffset + PCI_MSIX_PBA, 4, &pba);

 流程五:确认msix使用的bar空间基地址

讯享网 pbaBase = (ULONG)pDev->pRegBase[pba & PCI_MSIX_PBA_BIR_MASK]; if (vxMemProbe(pbaBase, VX_READ, 4, &temp) != OK) { vxbRegMap (pDev, pba & PCI_MSIX_PBA_BIR_MASK, &msixBarHandle); pbaBase = (ULONG)pDev->pRegBase[pba & PCI_MSIX_PBA_BIR_MASK]; } tableBase = (ULONG)pDev->pRegBase[(table & PCI_MSIX_TABLE_BIR_MASK)];

流程六:使能msix中断

 msiCtl |= PCI_MSIX_CTL_FUNCTION_MASK | PCI_MSIX_CTL_ENABLE; vxbPciBusCfgWrite (pDev, msiOffset + PCI_MSIX_CTL, 2, &msiCtl);

 流程七:配置table结构

讯享网 pTableEntry = (UINT32 *)(tableBase + tableOffset); for (i = 0; i < numVectors; i++) { struct vxbIntDynaVecInfo *pCurDynaVec; pCurDynaVec = &pDynaVec[i]; /* Message Vector Control */ pTableEntry[(pCurDynaVec->index << 2) + PCI_MSIX_MSG_CTRL] = htole32(pTableEntry[(pCurDynaVec->index << 2) + PCI_MSIX_MSG_CTRL] | PCI_MSIX_MSG_CTRL_MASK); /* Message Lower Address */ pTableEntry[(pCurDynaVec->index << 2) + 0] = htole32(pCurDynaVec->vecAddr); /* Message Higher Address */ pTableEntry[(pCurDynaVec->index << 2) + 1] = htole32(pCurDynaVec->vecAddr >> 32); /* Message Data */ pTableEntry[(pCurDynaVec->index << 2) + 2] = htole32(pCurDynaVec->vecVal); PCILIB_DEBUG_MSG(20, "vxbPciMSIXMultiProgram(): " "vecAddr 0x%016x val 0x%x for %s%d index %d Vector Control 0x%x\n", pCurDynaVec->vecAddr, pCurDynaVec->vecVal, (int)pDev->pName, pDev->unitNumber, pCurDynaVec->index, pTableEntry[(pCurDynaVec->index << 2) + 3]); }

流程八:使能pcie的msix中断

 vxbPciIntrExclusiveEnable(pDev, VXB_INT_PCI_MSIX);

参看文档

PCIe学习笔记之MSI/MSI-x中断及代码分析_pci_alloc_irq_vectors-CSDN博客

PCIe中断机制(1):演变历史 - 知乎 (zhihu.com)

小讯
上一篇 2025-03-27 20:59
下一篇 2025-04-04 13:28

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/72311.html