MSI-X (二)
1、 MSI-XCAP结构
![](https://www.pcietech.com/wp-content/uploads/2020/05/1-1.jpg)
MSI-X和MSI最大的不同是messagedata、message address和status字段没有存放在设备的配置空间中,而是使用MSI-X Table structure和MSI-X PBA structure来存放这些字段。
MSI-X Table structure和PBA structure存放在设备的BAR空间里,这两个structure可以map到相同BAR,也可以map到不同BAR,但是这个BAR必须是memory BAR而不能是IO BAR,也就是说这两个structure要map到memory空间。
注意:一个function只能支持一个MSI-X CAP。
![](https://www.pcietech.com/wp-content/uploads/2020/05/2.jpg)
1.1 配置空间的Message control 寄存器
配置空间Message Control寄存器中的table size字段表示MSI-X的table的大小。软件读取该字段获取table size,table size+1就是MSI-X table entry的个数,也就是Figure 7-36中的entry(N-1)中的N,每个entry对应一个中断向量。从table size可以看出1个function最多可以支持211=2048个MSI-X中断。
![](https://www.pcietech.com/wp-content/uploads/2020/05/3.jpg)
pci_msix_vec_count读取Message Control寄存器的table size字段获取MSI-X table entry的个数。
调用关系如下:
pci_enable_msix_range->__pci_enable_msix_range->__pci_enable_msix->pci_msix_vec_count
![](https://www.pcietech.com/wp-content/uploads/2020/05/4.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/5.jpg)
1.2 配置空间的Table offset/Table BIR寄存器
配置空间中Table offset/Table BIR寄存器的Table BIR字段指示使用哪个BAR来映射的MSI-X Table structure。该字段的0-5也对应function的BAR0-5。
Table offset字段代表MSI-X Table structure entry 0存放在BAR空间的偏移。
![](https://www.pcietech.com/wp-content/uploads/2020/05/6.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/7.jpg)
kernel代码先读取配置空间的Table offset/Table BIR寄存器,通过Table BIR字段获取使用哪个BAR来映射MSI-X Table structure。然后计算出MSI-X table entry0相对BAR空间偏移的物理地址(phys_addr),最后ioremap得到虚拟地址。
调用关系如下:
pci_enable_msix_range->__pci_enable_msix_range->__pci_enable_msix->msix_capability_init
![](https://www.pcietech.com/wp-content/uploads/2020/05/8.jpg)
1.3配置空间的PBA offset/PBA BIR寄存器
配置空间中PBA offset/PBA BIR寄存器的PBA BIR字段指示使用哪个BAR来映射的PBA structure。该字段的0-5也对应function的BAR0-5。
PBA offset字段代表PBA structure存放在BAR空间的偏移。
![](https://www.pcietech.com/wp-content/uploads/2020/05/9.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/10.jpg)
2、 Memory空间的MSI-X table structure
Message address和Message Upper address字段存放的是MSI-X memory write请求需要使用的地址。
Message Data字段存放的是MSI-X memory write请求需要使用的data。该地址和CPU的架构相关,是使能MSI-X时,系统软件写入的。
![](https://www.pcietech.com/wp-content/uploads/2020/05/11.png)
![](https://www.pcietech.com/wp-content/uploads/2020/05/12.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/13.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/14.jpg)
Kernel函数__pci_write_msi_msg把message address、message data写入对应的entry。
如果是X86的CPU,存放message address和message data的结构struct msi_msg *msg是在irq_msi_compose_msg中初始化的,这个值和CPU架构相关。
desc->mask_base是MSI-X table entry 0对应的虚拟地址,desc->msi_attrib.entry_nr是MSI-X table entry编号。desc->mask_base和desc->msi_attrib.entry_nr都是在msix_setup_entries赋值的(pci_enable_msix_range->__pci_enable_msix_range->
__pci_enable_msix->msix_capability_init->msix_setup_entries)。
X86下调用关系:
pci_enable_msix_range->__pci_enable_msix_range->__pci_enable_msix->msix_capability_init-> pci_msi_setup_msi_irqs-> arch_setup_msi_irqs->native_setup_msi_irqs
msi_domain_alloc_irqs->irq_domain_activate_irq->__irq_domain_activate_irq->msi_domain_activate->irq_chip_write_msi_msg->pci_msi_domain_write_msg->__pci_write_msi_msg
![](https://www.pcietech.com/wp-content/uploads/2020/05/15.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/16.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/17.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/18.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/19.jpg)
Vector Control字段存放的是控制字段,当Mask Bit为1时,PCIe设备不能使用该MSI-X tableentry来发送中断消息。
如果其他的MSI-X table entry也是使用的相同的vector,只要对应entry的vector control寄存器的mask bit字段不为1,仍然可以使用该vector发送MSI-X中断消息。这个意思是说Mask Bit的作用范围是该entry的,如果两个entry使用相同的vector(对X86来说就是Message Data字段低8 bit相同),Mask Bit不为1的entry是可以使用该vector发出message中断。
![](https://www.pcietech.com/wp-content/uploads/2020/05/20.jpg)
此时MSI-X中断还没有完全初始化完毕,Kernel代码是把MSI-X vector control 寄存器的Mask bit置1来mask所有vector的中断。
调用关系:
pci_enable_msix_range->__pci_enable_msix_range->__pci_enable_msix->msix_capability_init-> msix_program_entries
![](https://www.pcietech.com/wp-content/uploads/2020/05/21.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/22.jpg)
3、 什么时候umask的vector中断呢?
以网卡为例,在request_irq的时候才把MSI-X的使用的vector给unmask的。
__igb_open->request_threaded_irq->__setup_irq->irq_startup->__irq_startup->unmask_irq->pci_msi_unmask_irq-> msi_set_mask_bit->msix_mask_irq->
__pci_msix_desc_mask_irq
![](https://www.pcietech.com/wp-content/uploads/2020/05/23.jpg)
![](https://www.pcietech.com/wp-content/uploads/2020/05/24.jpg)