对于MSI或MSI-X中断,通过外设访问某个特定内存,从而触发对应的中断的产生。在没有SMMU时,外设直接访问该内存对应的物理地址即可。但在使能SMMU时,外设在访问某个物理内存前需要建立起IOVA到该物理地址的映射,然后发起对IOVA访问即可访问该物理地址,此过程称为MSI/MSI-X中断重定向。
该过程在linux内核中是由函数iommu_dma_prepare_msi()实现。
int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
参数desc为该中断对应的描述符,参数msi_addr为产生该中断的物理地址;
过程如下:
- 检查触发本中断对应的物理地址是否已经在domain范围内存在映射关系,若存在,返回msi_page(描述msi物理地址以及IOVA的映射);否则执行步骤(2);
- 分配新的msi_page,分配对应长度的IOA,调用API iommu_map()建立映射;
- 添加到domain范围内的cookie->msi_page_list中;
- 将表示中断的msi_desc与msi_page关联起来。
函数iommu_dma_compose_msi_msg()负责获取产生该中断所对应的IOVA地址,并填入到msi_msg中。