PCIE MSI-X Capability

每一个 Capability 结构都有唯一的ID 号,每一个Capability 寄存器都有一个指针,这个指针指向下一个Capability 结构,从而组成一个单向链表结构,这个链表的最后一个Capability 结构的指针为0。链表开始的指针地址为0x34处的1byte数值,寻址过程如下。

pci_find_capability() 断定一个设备是否支持给定PCI权能,返回在设备PCI配置空间内所请求权能结构的地址,如果设备不支持这种权能,则返回0;

PCIE的MSI-X相关信息存在两个地方,一个是PCIE Capability中,存放MSI-X基本信息,主要包含MSI-X Table所在BAR地址相关信息(访问的MSI-X Table关键),另外一个是MSI-X Table,存放在bar空间中,标识中断的msg addr及对应的msg data(即中断vector)。

PCIE MSI-X Capability_第1张图片

 MSI-X Capability结构,此结构在PCIe设备配置空间偏移0xB0的位置处,MSI-X中断表不在Capability中,存在bar中,通过table offset和table bir定位。

/* MSI-X registers */                                                                                                                                                          
#define PCI_MSIX_FLAGS          		 2
#define  PCI_MSIX_FLAGS_QSIZE  		 0x7FF
#define  PCI_MSIX_FLAGS_ENABLE  	 (1 << 15)
#define  PCI_MSIX_FLAGS_MASKALL	 (1 << 14)
#define PCI_MSIX_TABLE          		  4 
#define PCI_MSIX_PBA              		  8
#define  PCI_MSIX_FLAGS_BIRMASK 	  (7 << 0)   // LOW 3 bits

vfio_early_setup_msix {
    pos = pci_find_capability(&vdev->pdev, PCI_CAP_ID_MSIX);                                                                                                                   
    if (!pos) {                                                                                                                                                                
        return 0;                                                                                                                                                              
    }                                                                                                                                                                          
                                                                                                                                                                               
    table = pci_get_long(vdev->pdev.config + pos + PCI_MSIX_TABLE);  //   获取 MSI-X table(偏移 4 字节)                                                                                                        
    pba = pci_get_long(vdev->pdev.config + pos + PCI_MSIX_PBA);                                                                                                                
    ctrl = pci_get_word(vdev->pdev.config + pos + PCI_CAP_FLAGS);                                                                                                              
                                                                                                                                                                               
    vdev->msix = g_malloc0(sizeof(*(vdev->msix)));                                                                                                                             
    vdev->msix->table_bar = table & PCI_MSIX_FLAGS_BIRMASK;   // 获取 msi-x table 所在的bar                                                                                                                  
    vdev->msix->table_offset = table & ~PCI_MSIX_FLAGS_BIRMASK;                                                                                                                
    vdev->msix->pba_bar = pba & PCI_MSIX_FLAGS_BIRMASK;                                                                                                                        
    vdev->msix->pba_offset = pba & ~PCI_MSIX_FLAGS_BIRMASK;                                                                                                                    
    vdev->msix->entries = (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1; 
}

lspci查看当前pcie的msi-x capability

PCIE MSI-X Capability_第2张图片

参考

PCIe MSI-X 中断编程 - 知乎

你可能感兴趣的:(PCIE)