MSI全称Message Signaled Interrupt。
当设备向一个特殊地址写入时,会向CPU产生一个中断,即也MSI中断。
与传统引脚中断相比,MSI/MSI-X有三个方面的优势。
基于引脚的PCI中断经常在几个设备间共享,内核必须调用与该中断相关的每一个中断处理函数,降低了效率。MSI不是共享的,所以不存在这个问题。
当设备向内存写入数据,然后发起引脚中断时,有可能在CPU收到中断时,数据还未到达内存(在PCI-PCI桥后的设备更有可能如此)。为了保证数据已达 内存,中断处理程序必须轮询产生该中断的设备的一个寄存器,PCI事务保序规则会确保所有数据到达内存后,寄存器才会返回值。
使用MSI时,产生中断的写不能越过数据写,因而避免了这个问题。当中断产生时,驱动可以确信所有数据已经到达内存。
![787cf6ff21500ba52e32b17b3ed13879.png](https://i-blog.csdnimg.cn/blog_migrate/96b22947102ccf654611ef354cfa4794.jpeg)
![bdd61ecb2145e28c01092110898c3409.png](https://i-blog.csdnimg.cn/blog_migrate/5e03632a07a2f78fdbe92e2b09069aab.jpeg)
MSI在PCI Capability ID=05,有4种类型,如上面图所示。
MSI主要是Message Address,跟Message Data,PCI设备把Message Data写入Message Address这个地址,CPU就会发生中断。
static void __irq_msi_compose_msg(struct irq_cfg *cfg, struct msi_msg *msg)
{
msg->address_hi = MSI_ADDR_BASE_HI;
if (x2apic_enabled())
msg->address_hi |= MSI_ADDR_EXT_DEST_ID(cfg->dest_apicid);
msg->address_lo =
MSI_ADDR_BASE_LO |
MSI_ADDR_DEST_MODE_PHYSICAL|
MSI_ADDR_REDIRECTION_CPU |
MSI_ADDR_DEST_ID(cfg->dest_apicid);
msg->data =
MSI_DATA_TRIGGER_EDGE |
MSI_DATA_LEVEL_ASSERT |
MSI_DATA_DELIVERY_FIXED |
MSI_DATA_VECTOR(cfg->vector);
}
void msi_compose_msg(uint vector,uint destid, struct msi_msg *msg)
{
struct irq_cfg cfg={.vector = vector,.dest_apicid = destid};
__irq_msi_compose_msg(&cfg,msg);
}
msi_compose_msg这个函数生成msi消息,即64位地址跟32位data。地址空间在0xfee00000起始的1M内存。每个cpu有不同的地址。
data里面最总要的一个就是中断向量,告诉设备产生几号中断(vector)
bool msi_write_entry(pci_device_t pci, int entry_id, msi_msg *msg)
{
if (!pci_is_msi(pci)) {