在 Linux 上支持 AMD IOMMU 的代码是 arch/x86/kernel/ 目录下的 amd_iommu.c 和 amd_iommu_init.c 两个文件。 amd_iommu_init.c中主要是实现IOMMU 检测和控制寄存器操作的代码。 IOMMU 的检测是通过分析 ACPI IVRS 表进行的。 文件 amd_iommu.c 中对 AMD IOMMU 进行了抽象并为 IOMMU 通用层实现了一组操作接口。一个数据结构 structprotect_domain 用来抽象一个保护域,其中有个字段是该保护域的 IO 页表的顶层目录的物理地址,所有关联到这个域的设备都只能使用该页表。设备到域的关联当然是通过 dev_table 实现的。 除硬件需要的 dev_table 外,软件还使用了 rlookup_table 和 pd_table。rlookup_table 是用来确定一个具体的 PCI 设备是物理上连接到哪个 IOMMU 上的,这在采用多个 IOMMU 的结构中当然是有必要的。 pd_table 是用来确定一个设备对应的 protect_domain 数据结构。 这三个表都是以设备的 ID 为索引的。 目前在 RHEL6.2 的实现中,似乎还没有对 IOMMU 的中断转换功能的支持。 在amd_iommu.c 中实现的操作接口主要包括几个函数: amd_iommu_domain_init, amd_iommu_domain_destroy, amd_iommu_attach_device, amd_iommu_detach_device, amd_iommu_map_range, amd_iommu_unmap_range, amd_iommu_iova_to_phys amd_iommu_domain_has_cap 读者不难通过函数名和代码看出这几个函数的功能。 Linux 内核 IOMMU 通用层定义的 API 在 driver/base/iommu.c 中, 有八个函数 :iommu_domain_alloc, iommu_domain_free, iommu_attach_device, iommu_detach_device, iommu_map_range, iommu_unmap_range, iommu_iova_to_phys 及 iommu_domain_has_cap,分别调用 AMD IOMMU 层的功能实现函数。
|