AMD IOMMU与Linux (1) -- 初始化

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.com)

IOMMU(二)-从配置说起 - 云+社区 - 腾讯云 (tencent.com)

IOMMU(三)-初始化 - 云+社区 - 腾讯云 (tencent.com)

Notes:

IVRS: I/O Virtualization Reporting Structure

Kernel 5.15.11

iommu_domain (in struct protection_domain)

iommu_device (in struct amd_iommu)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值