1.概述

ARM SMMUv3控制器初始化及设备树分析(七)中描述了IOMMU控制器初始化过程。SMMU驱动最后调用iommu_device_register将其注册到内核中,下面分析一下SMMU控制器注册过程中都做了那些工作。

如下图所示,SMMU控制器注册过程中主要做了4部分工作:

  1. 遍历内核中所有总线,初始化使用SMMU的设备,主要是创建设备的Stream Table,给设备分配或者创建iommu_group
  2. 遍历所有使用SMMU的设备,创建iommu_domian,并和设备关联起来。主要是初始化设备使用的STE和CD表。
  3. 遍历所有使用SMMU的设备,初始化DMA映射的iommu_domian。主要是初始化iova_domain、TLB刷新队列,设置保留的IOVA。
  4. 释放相关锁,SMMU不需要,这里不多介绍。

iommu_device_register

如下代码所示,iommu_device_register函数会遍历iommu_buses定义的所有总线,初始化其中使用SMMU的设备。

[drivers/iommu/iommu.c]
static const struct bus_type * const iommu_buses[] = {&platform_bus_type,
#ifdef CONFIG_PCI&pci_bus_type,
#endif
#ifdef CONFIG_ARM_AMBA&amba_bustype,
#endif
#ifdef CONFIG_FSL_MC_BUS&fsl_mc_bus_type,
#endif
#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS&host1x_context_device_bus_type,
#endif
#ifdef CONFIG_CDX_BUS&cdx_bus_type,
#endif
};

2.初始化设备

初始化使用IOMMU的client设备,主要是为其创建Stream Table及分配或者创建iommu_group

  1. 调用arm_smmu_probe_device函数初始化设备。
    1. 由于client设备是smmu的master,因此smmu驱动会给每一个client设备分配一个arm_smmu_master,然后通过arm_smmu_master将client设备和smmu控制器关联起来。dev_iommu中的私有数据指针priv指向了arm_smmu_masterarm_smmu_master中保存了设备的Stream ID信息。smmu驱动使用红黑树管理Stream ID。
    2. 如果采用2级Stream table,则需要分配client设备使用的第二级STE表内存,一次性分配256个STE表。然后将STE暂时设置成ABORT。
    3. 处理PCIe设备ATS相关功能。
  2. iommu_device保存到设备的dev_iommu中。这样可以通过设备的device数据结构找到smmu控制器。
  3. 在sysfs中关联设备和iommu,这样在sys文件系统中device目录下会有iommu控制器的文件。
  4. 调用arm_smmu_device_group函数为设备创建iommu_group。PCI设备可能会共享iommu_group,因此驱动会依据PCI总线拓扑结构、isolation特性或者DMA别名quirks查找或者创建iommu_group。其他设备每个设备分配一个iommu_group
  5. 分配group_device,然后挂到iommu_groupdevices链表中。一个iommu_group内可能有多个设备,每个设备使用group_device表示。
  6. iommu_group挂到group_list链表中,稍后统一处理。

probe_iommu_group

3.创建iommu_domian

遍历group_list链表,为每个iommu_group设置默认的iommu_domain,主要的工作内容如下:

  1. 首先获取iommu_domain的类型,传入的参数为0,则iommu_domain类型由驱动和系统共同决定。对于PCI untrusted设备,类型为IOMMU_DOMAIN_DMA,其他设备返回0。
  2. 分配默认的iommu_domain。如果请求的iommu_domain类型非0,则使用请求的类型,否则使用iommu_def_domain_type表示的类型。iommu_def_domain_type是一个全局变量,由命令行参数和内核配置共同决定,通常情况下为IOMMU_DOMAIN_DMAIOMMU_DOMAIN_DMA_FQ。如果iommu_domain类型为DMA,则调用arm_smmu_domain_alloc_paging分配iommu_domain,smmu驱动底层会分配一个arm_smmu_domain,内部包含了iommu_domain,然后将arm_smmu_domainarm_smmu_devicearm_smmu_master)关联在一起,最后初始化domain内页表相关内容。
  3. 遍历iommu_group内的每一个设备,如果其保留内存区域类型为IOMMU_RESV_DIRECTIOMMU_RESV_DIRECT_RELAXABLE,则创建direct mappings。避免这些内存区域被误使用。
  4. 遍历group中的每一个device,调用arm_smmu_attach_dev关联对应的iommu_domain。最主要的是初始化arm_smmu_domain中的CD表。

分配iommu_domian
iommu_domain的类型不同,其分配策略也不同。iommu_domain__iommu_domain_alloc函数中分配,结合smmu驱动,可以总结iommu_domain的分配策略如下:

  1. 如果分配的iommu_domain类型是IOMMU_DOMAIN_IDENTITYIOMMU_DOMAIN_BLOCKED,则直接使用arm_smmu_ops驱动中静态定义的arm_smmu_identity_domainarm_smmu_blocked_domain。这样就存在多个iommu_group使用一个iommu_domain的情况。
  2. 如果分配的iommu_domain类型是IOMMU_DOMAIN_UNMANAGEDIOMMU_DOMAIN_DMAIOMMU_DOMAIN_DMA_FQ,则smmu驱动会动态分配arm_smmu_domain(内部包含了iommu_domain),这样一个iommu_group对应一个iommu_domain,使用default_domain_ops,smmu驱动需要管理IOVA页表。
  3. 如果分配的iommu_domain类型是IOMMU_DOMAIN_SVA,说明DMA共享进程进程地址空间,则smmu驱动会动态分配iommu_domain,并且使用arm_smmu_sva_domain_ops,由于和进程共享,smmu驱动只需要管理iommu_domain和PASID。

3.1.分配iommu_domian

arm_smmu_domain_alloc_paging函数主要分配支持iommu_map/unmap接口的iommu_domain,然后根据不同的地址转换阶段,做不同的初始化。主要的工作如下:

  1. 分配arm_smmu_domain,内部包含了iommu_domain
  2. 初始化arm_smmu_domainARM_SMMU_DOMAIN_S1ARM_SMMU_DOMAIN_S2初始化内容有所不同。
    1. 初始化IO页表配置。包括SMMU支持的页表大小掩码、是否支持Cache一致性、刷新TLB回调函数arm_smmu_flush_ops
    2. 如果是第一阶段地址转换。设置输入地址位宽为48位,如果支持虚拟地址扩展(VAX),则设置为52位,设置输出地址位宽等于IPA地址的位宽。设置IO页表格式为ARM_64_LPAE_S1
    3. 如果是第二阶段地址转换。设置输入地址位宽等于IPA地址的位宽,设置输出地址位宽等于PA地址的位宽。设置IO页表格式为ARM_64_LPAE_S2
    4. 根据不同的IO页表格式,创建管理IO页表的接口集合io_pgtable_ops
      1. 对于ARM_64_LPAE_S1页表格式,调用arm_64_lpae_alloc_pgtable_s1创建io_pgtable_ops。设置TCR(类似于MMU中的TCR_ELx)中的参数,如共享属性、页表大小、IPA地址宽度。设置MAIRs。分配保存第0级页表的内存(CD表中TTB0/1指向这块内存)。
      2. 对于ARM_64_LPAE_S2页表格式,调用arm_64_lpae_alloc_pgtable_s2创建io_pgtable_ops。设置VTCR(类似于MMU中的VTCR_EL2)中的参数,如共享属性、页表大小、PA地址宽度。分配保存第0级页表的内存(STE表中S2TTB指向这块内存)。
    5. 如果是ARM_SMMU_DOMAIN_S1,则需要分配ASID。如果是ARM_SMMU_DOMAIN_S2,则需要分配VMID。

分配iommu_domian

arm_smmu_domain_alloc_paging函数分配iommu_domian的过程中涉及到重要的代码定义如下所示:

[drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c]
// TLB刷新回调函数集合
static const struct iommu_flush_ops arm_smmu_flush_ops = {.tlb_flush_all      = arm_smmu_tlb_inv_context,.tlb_flush_walk     = arm_smmu_tlb_inv_walk,.tlb_add_page       = arm_smmu_tlb_inv_page_nosync,
};[drivers/iommu/io-pgtable.c]
// 根据不同的IO页表格式,对应不同的创建io_pgtable_ops的函数
static const struct io_pgtable_init_fns *
io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
#ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE[ARM_32_LPAE_S1] = &io_pgtable_arm_32_lpae_s1_init_fns,[ARM_32_LPAE_S2] = &io_pgtable_arm_32_lpae_s2_init_fns,[ARM_64_LPAE_S1] = &io_pgtable_arm_64_lpae_s1_init_fns,[ARM_64_LPAE_S2] = &io_pgtable_arm_64_lpae_s2_init_fns,[ARM_MALI_LPAE]  = &io_pgtable_arm_mali_lpae_init_fns,
#endif......
};// io_pgtable_ops函数集合
[drivers/iommu/io-pgtable-arm.c]
data->iop.ops = (struct io_pgtable_ops) {.map_pages            = arm_lpae_map_pages,.unmap_pages          = arm_lpae_unmap_pages,.iova_to_phys         = arm_lpae_iova_to_phys,.read_and_clear_dirty = arm_lpae_read_and_clear_dirty,

3.2.关联设备

arm_smmu_attach_dev函数的主要作用是将iommu_domain和设备关联起来。如果是第一阶段地址转换的iommu_domain,则需要初始化CD表,如果是第二阶段地址转换的iommu_domain,则需要初始化STE表中S2相关的参数。具体的内容如下:

  1. 如果是ARM_SMMU_DOMAIN_S1,则分配CD表。如果是线性CD表(STRTAB_STE_0_S1FMT_LINEAR),则直接分配全部内存。如果是2级CD表(STRTAB_STE_0_S1FMT_64K_L2),先分配第一级L1CD内存,接着分配SSID ==0的第二级CD表数组(可以保存1024个CD),随后将第二级CD表数组的DMA地址写到L1CD内存中(l2.l1tab[0]),最后invalid L1CD。
  2. 处理和ATS相关的功能。
  3. 如果是第一阶段地址转换(ARM_SMMU_DOMAIN_S1)。
    1. 初始化第0个CD表。
    2. 初始化设备需要的STE表(根据SID初始化),默认SID==0的STE(STRTAB_STE_1_S1DSS_SSID0)无法使用,如果使用则会ABORT。
  4. 如果是第二阶段地址转换(ARM_SMMU_DOMAIN_S2)。初始化设备需要的STE表(根据SID初始化),如果该STE表有对应的CD表,则将第一个CD表清零。
  5. 按照EATS设置完成STE/CD的配置之后,需要完成对PCIe设备ATC的同步操作。

关联设备

4.初始化DMA iommu_domian

iommu_setup_dma_ops函数初始化DMA映射的iommu_domian,主要的工作如下:

  1. 设置dev->dma_iommu=true。如果启用DMA-API和IOMMU-API的中间层,则设备在分配DMA内存或者进行流式映射内存时,底层将调用DMA-IOMMU接口。
  2. 初始化iommu_domain。初始化管理IO虚拟地址的iova_domain及地址缓存、TLB刷新队列和注册保留的IO虚拟地址。

初始化IOVA

参考资料

  1. linux 6.12.35 source code.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/92961.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/92961.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/92961.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Idefics3:构建和更好地理解视觉-语言模型:洞察与未来方向

温馨提示: 本篇文章已同步至"AI专题精讲" Idefics3:构建和更好地理解视觉-语言模型:洞察与未来方向 摘要 视觉-语言模型(VLMs)领域,接收图像和文本作为输入并输出文本的模型,正在快…

利用DeepSeek解决kdb+x进行tpch测试的几个问题及使用感受

上文其实没有成功运行tpch的22个标准查询中的任何一个,因为DeepSeek原始给出的导入语句有错,有一些表没有导入。 1.解决类型及长度问题导致的插入tbl文件到内存表失败。 kdbx的Reference card()提到的基本数据类型如下: Basic datatypes n …

SGLang 核心技术详解

SGLang 作为一个高性能的 LLM 服务框架,通过一系列先进的优化技术实现了卓越的推理性能。下面详细解释其核心功能组件: 1. RadixAttention 用于前缀缓存 核心概念 RadixAttention 是 SGLang 独创的前缀缓存机制,基于 Radix Tree(基…

精密全波整流电路(四)

精密全波整流电路(四) 背景说明 [[精密半波整流电路|半波整流]]虽然能实现交直流信号的转换,但是半波整流只能保留信号半个周期的能量,导致信号能量的利用率不高。 因此,在一些场合需要使用到全波整流电路。 同样的&…

深入解读Prometheus 2.33 Series Chunks压缩特性:原理与实践

深入解读Prometheus 2.33 Series Chunks压缩特性:原理与实践 随着监控指标规模不断增长,Prometheus的本地TSDB存储压力日益增大。为提升存储效率,Prometheus 2.33引入了Series Chunks压缩特性,对时间序列数据在写入和存储时进行深…

SpringBoot整合Liquibase提升数据库变更的可控性、安全性、自动化程度(最详细)

为什么要使用liquibase?- 团队协作与版本管理- 当多人(或多个小组)并行开发、对同一数据库结构进行变更时,如果仅靠手写 SQL 脚本,很 容易产生冲突或漏掉某些变更。- Liquibase 将所有 DDL/DML 操作以“changeset”形式纳入源码管…

数据写入因为汉字引发的异常

spark 数据写hive表,发生 查询分区异常问题 异常: 25107124 19 26.49 ERROR Hive: MelaException(message.Exception thrown when execuling quey. S ELECT DISTINCT ‘org apache.hadop.hive melastore .modelMpartion As"NUCLEUS TYPE,AONCREATE TIME,AO.LAST ACCE…

Springboot项目实现将文件上传到阿里云

Springboot项目实现将文件上传到阿里云 一、概述二、具体步骤 2.1引入阿里云工具 首先先建utils包,然后引入AliOSSUtils类,如下: package com.hechixueyuan.forestfiredetectionsystem.utils;import com.aliyun.oss.OSS; import com.aliyun.o…

如何理解 TCP 是字节流协议?详解

文章目录一、面向字节流二、粘包问题应用层如何解决粘包问题?一、面向字节流 使用 TCP socket 进行网络编程,Linux 内核会给每个 socket 都分配一个发送缓冲区和一个接收缓冲区 由于缓冲区的存在, TCP 读写不需要一一匹配,例如:…

面试问题总结——关于OpenCV(二)

最近小组在面试视觉算法工程师,顺便整理了一波关于OpenCV的面试题目。 有些知识点也不深入,对于写的不对的地方,欢迎指正。 目录 20.像素梯度如何计算? 21.关于开运算和闭运算的理解 22.开运算和闭运算有什么优缺点? 23.图像插值有哪些? 24.图像金字塔的原理 25.边缘检测…

目标导向的强化学习:问题定义与 HER 算法详解—强化学习(19)

目录 1、目标导向的强化学习:问题定义 1.1、 核心要素与符号定义 1.2、 核心问题:稀疏奖励困境 1.3、 学习目标 2、HER(Hindsight Experience Replay)算法 2.1、 HER 的核心逻辑 2.2、 算法步骤(结合 DDPG 举例…

2025 XYD Summer Camp 7.21 智灵班分班考 · Day1

智灵班分班考 Day1 时间线 8:00 在滨兰实验的远古机房中的一个键盘手感爆炸的电脑上开考。开 T1,推了推发现可以 segment tree 优化 dp,由于按空格需要很大的力气导致马蜂被迫改变。后来忍不住了顶着疼痛按空格。8:30 过了样例,但是没有大样…

基于多种主题分析、关键词提取算法的设计与实现【TF-IDF算法、LDA、NMF分解、BERT主题模型】

文章目录有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主一、项目背景二、研究目标与意义三、数据获取与处理四、文本分析与主题建模方法1. 传统方法探索2. 主题模型比较与优化3. 深度语义建模与聚类五、研究成果与应用价值六、总结与展望总结每文一…

MDC(Mapped Diagnostic Context) 的核心介绍与使用教程

关于日志框架中 MDC(Mapped Diagnostic Context) 的核心介绍与使用教程,结合其在分布式系统中的实际应用场景,分模块说明: 一、MDC 简介 MDC(映射诊断上下文) 是 SLF4J/Logback 提供的一种线程…

Linux随记(二十一)

一、highgo切换leader,follow - 随记 【待写】二、highgo的etcd未授权访问 - 随记 【待写】三、highgo的etcd未授权访问 - 随记 【待写】3.2、etcd的metric未授权访问 - 随记 【待写】四、安装Elasticsearch 7.17.29 和 Elasticsearch 未授权访问【原理扫描】…

Java环境配置之各类组件下载安装教程整理(jdk、idea、git、maven、mysql、redis)

Java环境配置之各类组件下载安装教程整理(jdk、idea、git、maven、mysql、redis)1.[安装配置jdk8]2.[安装配置idea]3.[安装配置git]4.[安装配置maven]5.[安装配置postman]6.[安装配置redis和可视化工具]7.[安装配置mysql和可视化工具]8.[安装配置docker]…

配置https ssl证书生成

1.可用openssl生成私钥和自签名证书 安装opensslsudo yum install openssl -y 2.生成ssl证书 365天期限sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \-keyout /etc/ssl/private/nginx-selfsigned.key \-out /etc/ssl/certs/nginx-selfsigned.crt3、按照提示编…

编程语言Java——核心技术篇(四)集合类详解

言不信者行不果,行不敏者言多滞. 目录 4. 集合类 4.1 集合类概述 4.1.1 集合框架遵循原则 4.1.2 集合框架体系 4.2 核心接口和实现类解析 4.2.1 Collection 接口体系 4.2.1.1 Collection 接口核心定义 4.2.1.2 List接口详解 4.2.1.3 Set 接口详解 4.2.1.4…

GaussDB 数据库架构师(八) 等待事件(1)-概述

1、等待事件概述 等待事件:指当数据库会话(session)因资源竞争或依赖无法继续执行时,进入"等待"状态,此时产生的性能事件即等待事件。 2、等待事件本质 性能瓶颈的信号灯,反映CPU,I/O、锁、网络等关键资源的阻塞情况。…

五分钟系列-文本搜索工具grep

目录 1️⃣核心功能​​ ​​2️⃣基本语法​​ 3️⃣​​常用选项 & 功能详解​​ ​​4️⃣经典应用场景 & 示例​​ 5️⃣​​重要的提示 & 技巧​​ ​​6️⃣总结​​ grep 是 Linux/Unix 系统中功能强大的​​文本搜索工具​​,其名称源自 …