admin管理员组文章数量:1530018
IOMMU的具体工作原理就不展开了,AMD IOMMU【1】与INTEL VT-D有公开的英文版文档。
总得来讲,IOMMU主要做DMA与Interrupt remapping两大类的工作
AMD IOMMU硬件功能上理解起来不算太复杂,但一旦结合Linux,复杂度就明显提高
参考了一些内容,但大多数是写IOMMU硬件功能的【4】,有少量提到IOMMU与Linux的,而大多数也只是一笔带过
Reference [3] 是以Intel IOMMU为介绍对象
Reference [2] 更加有参考价值
这一系列,主要记录:AMD IOMMU在Linux下的学习所得:
1. 先从pci_iommu_alloc()函数开始:
在执行pci_iommu_alloc()之前,内核已经通过汇编指令,将IOMMU相关的启动函数,加载到IOMMU Table中, 如下:
IOMMU_INIT_FINISH(amd_iommu_detect,
gart_iommu_hole_init,
NULL,
NULL);
amd_iommu_detect -- Early detect code. This code runs at IOMMU detection time in the DMA layer. It just looks if there is an IVRS ACPI table to detect AMD IOMMUs
针对INTEL, AMD-GART, SWIOTLB的类似启动函数还有如下:
IOMMU_INIT_POST(gart_iommu_hole_init);
IOMMU_INIT_POST(detect_intel_iommu);
IOMMU_INIT_FINISH(pci_xen_swiotlb_detect,
NULL,
pci_xen_swiotlb_init,
NULL);
IOMMU_INIT_FINISH(pci_swiotlb_detect_override,
pci_xen_swiotlb_detect,
pci_swiotlb_init,
pci_swiotlb_late_init);
IOMMU_INIT(pci_swiotlb_detect_4gb, --> 设置swiotlb变量:如果物理内存大于4GB,那么 pci_swiotlb_detect_4gb()就会将swiotlb置为1,从而导致后续swiotlb_init()被调用,以初始化SWIOTLB
pci_swiotlb_detect_override,
pci_swiotlb_init, --> 初始化SWIOTLB
pci_swiotlb_late_init);
arch/x86/include/asm/iommu_table.h
struct iommu_table_entry {
initcall_t detect;
initcall_t depend;
void (*early_init)(void); /* No memory allocate available. */
void (*late_init)(void); /* Yes, can allocate memory. */
#define IOMMU_FINISH_IF_DETECTED (1<<0)
#define IOMMU_DETECTED (1<<1)
int flags;
};
该文件中定义了这些宏,本质上都是同一个基础宏:__IOMMU_INIT
IOMMU_INIT_POST (depend = pci_swiotlb_detect_4gb)
IOMMU_INIT_POST_FINISH (depend = pci_swiotlb_detect_4gb 、 stop detecting the other IOMMUs after yours has been detected)
IOMMU_INIT_FINISH (除了detect, depend, 也设置init, late_init)
IOMMU_INIT
detect 与depend的关系,从实际dmesg log上看,如果detect 有depend, 则depend会先于detect执行
从内核代码注释中可以看到,during boot-time we will have to resort them based on dependency
关于init, late_init调用时机,见下面的代码注释
arch/x86/kernel/vmlinux.lds.S
/*
* struct iommu_table_entry entries are injected in this section.
* It is an array of IOMMUs which during run time gets sorted depending
* on its dependency order. After rootfs_initcall is complete
* this section can be safely removed.
*/
.iommu_table : AT(ADDR(.iommu_table) - LOAD_OFFSET) {
__iommu_table = .;
*(.iommu_table)
__iommu_table_end = .;
}
2. amd_iommu_detect
pci_iommu_alloc -->
(struct iommu_table_entry). detect == amd_iommu_detect, 函数会将x86_init.iommu.iommu_init设置为amd_iommu_init,后者正是AMD IOMMU的初始化函数
IOMMU_INIT_FINISH(amd_iommu_detect,
gart_iommu_hole_init,
NULL,
NULL);
3. amd_iommu_init 简单的状态机FSM中AMD IOMMU硬件初始化函数的调用,比如AMD IOMMU V2表示支持GVA->SPA的mapping
iommu_go_to_state -->
state_next (AMD IOMMU Initialization State Machine) -->
early_amd_iommu_init (case IOMMU_IVRS_DETECTED)
early_enable_iommus (case IOMMU_ACPI_FINISHED)
register_syscore_ops/amd_iommu_init_pci/enable_iommus_v2 (case IOMMU_ENABLED)
amd_iommu_enable_interrupts (case IOMMU_PCI_INIT)
Reference:
【1】
AMD I/O Virtualization Technology (IOMMU) Specification, 48882
【2】
(7条消息) Linux x86-64 IOMMU详解(五)——Intel IOMMU初始化流程_C is My Best Friend的博客-CSDN博客_初始化iommu
【3】intel IOMMU driver analysis (terenceli.github.io)
【4】IOMMU introduction (terenceli.github.io)
[5]
See <Documentation/x86/x86_64/boot-options.rst> for the iommu kernel parameter documentation
[6]
DMA和IOMMU(一)-简单介绍 - 云+社区 - 腾讯云 (tencent)
IOMMU(二)-从配置说起 - 云+社区 - 腾讯云 (tencent)
IOMMU(三)-初始化 - 云+社区 - 腾讯云 (tencent)
Notes:
IVRS: I/O Virtualization Reporting Structure
Kernel 5.15.11
iommu_domain (in struct protection_domain)
iommu_device (in struct amd_iommu)
版权声明:本文标题:AMD IOMMU与Linux (1) -- 初始化 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1726770845a1083854.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论