当前位置: 首页 > article >正文

SMMU软件指南之使用案例(Stage 1使用场景)

安全之安全(security²)博客目录导读

目录

一、Stage 1使用场景

1、Scatter-gather

2、64 位操作系统中的 32 位设备

3、操作系统设备隔离

4、用户空间设备驱动程序

5、用户空间共享虚拟地址 (SVA)


本博客描述以下使用场景:

  • 一级转换使用场景Stage 1 use cases

本节中的 Linux 描述基于版本 6.4。某些使用场景尚未在此版本中实现,可能在后续版本中实现或仍在开发中。相关信息在每个使用场景中注明。

一、Stage 1使用场景

本节描述单一一级转换(single stage 1 translation)的使用。

1、Scatter-gather

一些高级设备可以使用scatter-gather列表请求 DMA,这些列表包含多个非连续缓冲区地址,组成单个请求。然而,简单设备通常不支持scatter-gather,它们只能请求连续缓冲区的 DMA。当系统运行时,物理内存可能变得碎片化,因此不一定能保证连续缓冲区。操作系统可能需要将较大范围的 DMA 请求分成多个较小范围的请求,这会影响性能。

SMMU 可以解决这个问题。操作系统使用 SMMU 向设备提供连续缓冲区,即使该缓冲区在物理上并不连续。通过在转换表中分配具有连续虚拟地址的页面,并将它们映射到非连续的物理地址,操作系统可以使用虚拟地址编程 DMA 地址。

在 Linux 中,如果设备驱动程序为不支持scatter-gather的设备使用 DMA API 分配分散页面,SMMU 驱动程序会执行“gather”工作,对设备驱动程序透明。

由于该地址空间仅为设备创建,与应用进程虚拟内存地址空间无关,不能使用广播 TLB 维护(Broadcast TLB maintenance)从 PE 失效 SMMU 的 TLB。虽然 SMMU 也使用 ASID 来区分不同的地址空间,但 SMMU 的 ASID 命名空间与 PE 的 ASID 命名空间是独立的。为了确保它们在不同的 ASID 命名空间中,操作系统需要设置 CD.ASET = 1,以便由该上下文创建的 SMMU TLB 条目不需要通过某些广播失效来失效。

2、64 位操作系统中的 32 位设备

一些传统设备仅支持 32 位地址的 DMA。由于操作系统可能会将 DMA 缓冲区分配到超出 32 位范围的物理地址,因此需要一种解决方案来确保这些传统设备仍然可以工作。SMMU 通过基于设备的 StreamID 创建一个独立的虚拟内存映射,允许设备在物理地址超出 32 位范围时在 32 位范围内发出 DMA 请求。在 Linux 中,如果满足以下两个条件:

  • 设备驱动程序使用 DMA API 为设备分配页面。
  • 页面物理地址超过 4GB。

SMMU驱动程序执行地址映射工作,将低于4GB的IOVA映射到超过4GB的分配页面。这项工作对设备驱动程序是透明的。像前面的scatter-gather使用场景一样,该地址空间仅为设备创建,与应用进程虚拟内存地址空间无关,不能使用广播 TLB 维护从 PE 失效 SMMU 的 TLB。

支持 64 位系统上的 32 位传统设备的替代方案是 OS 在低地址范围内维护一个 DMA “跳板缓冲区”池,并在缓冲区与原始 64 位位置之间复制数据。例如,SWIOTLB 在没有 SMMU 的系统或 SMMU 在 Linux 中被禁用时执行此工作。对于大规模传输,使用 SMMU 明显更快。

3、操作系统设备隔离

恶意设备可能会通过互连发起不当的 DMA 传输,导致数据被损坏或被读取。具有 SMMU 的系统中,设备只能访问为 DMA 映射的页面。许多操作系统提供通用 API,设备驱动程序在执行 DMA 传输时使用这些 API。例如,在 Linux 中,这些 DMA API 安排分配、确保适当的地址限制,并在使用非缓存一致 DMA 时执行缓存维护操作。

这些 API 可跟踪任何特定设备访问的页面,并配置 SMMU 以映射正确引用的地址,同时阻止对其他地址的访问。任何编程错误都可以被检测并隔离。失效的设备或驱动程序错误不会影响未配置为 DMA 的页面集之外的数据。这比允许设备进行不受限制的 DMA 更可靠。当存在不受信任或恶意设备时(例如通过外部互连连接),这对安全尤为重要。

在此使用场景中,SMMU 转换表不与 PE 共享,因此不需要共享 ASID。

4、用户空间设备驱动程序

某些系统可能需要用户空间设备驱动程序。用户空间驱动程序用于性能、灵活性、鲁棒性或安全性。例如,应用程序可能需要低延迟地访问加速器,而无需使用系统调用,避免在用户空间和内核空间之间复制数据的开销。

为此,操作系统将设备 MMIO 寄存器映射到用户进程虚拟地址空间。如果用户空间控制的设备能够请求 DMA,则其传输具有与用户进程相同的信任等级。该设备必须置于 SMMU 后,以确保设备 DMA 访问仅在用户进程地址映射的许可区域内正确执行。SMMU 保护系统不受由恶意或不正确的用户空间程序控制的 DMA 影响。

当设备分配给应用程序时,软件会分配用于 DMA 的特殊内存区域。操作系统随后为该设备在 SMMU 设置一个私有的转换表,映射这些内存区域以供设备访问。建议该内存出现在进程 VA 空间和设备地址空间中的相同地址上,以便编程人员能够轻松配置 DMA 指针,但这不是强制性的。

在 Linux 中,VFIO 子系统允许应用程序使用设备。VFIO 允许应用程序选择一个 IOVA,将其映射到进程中的选定内存区域,并在将 DMA 指针编程到设备中时使用 IOVA。SMMU 使设备的 DMA 可以访问进程选定区域的内存,设备和 PE 通过该内存共享数据。SMMU 阻止设备访问进程地址空间的其他部分或其他进程的地址空间。

由于用户空间内存通常按需分配和交换,因此必须考虑 DMA 的页面错误。在许多系统中,与转换相关的错误对 DMA 传输是致命的。许多设备驱动程序通过固定 DMA 目标页面来避免与转换相关的错误。由于 DMA 仅发生在特定的内存区域,这些区域通常较小,因此固定内存是合理的要求。

5、用户空间共享虚拟地址 (SVA)

用户空间设备驱动程序使用场景介绍了用户空间设备驱动程序,但有一些限制:SMMU 转换表必须将特殊的 DMA 区域映射到用户空间设备驱动程序的地址空间中。

此使用场景考虑了与设备共享整个用户进程地址空间的替代方案,而不是特定的区域。与设备共享进程地址空间依赖于 CPU 内核内存管理来支持 DMA。这减少了应用程序和设备驱动程序的一些复杂性。设备的 MMIO 寄存器通过 PE 以与用户空间设备驱动程序相同的方式进行虚拟映射。但是,现在 SMMU 将设备与整个进程地址空间关联,而不是其子集。设备需要能够物理访问任何用户空间虚拟地址。例如,当设备只能使用 32 位地址,且进程使用 48 位虚拟地址时,SVA 就无法实现。

为了实现共享地址空间,SMMU 可以直接使用进程的转换表和 ASID。由于使用了公共 ASID,且虚拟地址在 PE 和 SMMU 上具有相同的含义,因此可以使用广播 TLB 维护来使 PE 失效 SMMU 转换我们推荐使用广播失效,因为手动 TLB 失效命令的慢速往返可以避免。使用公共失效方法可能还会带来软件上的简化。

将每个页面固定内存以防进程尝试将 DMA 编程到它们上是不切实际的。DMA 可能会访问任何地址,无论页面表是否已经映射该地址,因此设备和系统必须支持 DMA 访问时的页面错误。这意味着:

  • 当检测到页面错误时,设备 DMA 流必须不会被致命地中止。
  • 需要一种机制通知操作系统,以便恢复 DMA 传输:
    • 发生了错误。
    • 需要采取措施使所需页面可访问。

SMMU 和设备协同工作,支持 DMA 上的页面错误非致命的要求。例如,设备 DMA 流可能会在 SMMU 中配置为在错误发生时暂停。当错误发生时,SMMU 将向软件报告错误描述符,并且该错误事务会暂停,直到页面错误被解决。软件发出命令,要求 SMMU 重试事务,或者如果错误是由于不正确访问引起的,则中止事务。设备在响应 DMA 请求时会经历一个小的延迟。

另外,一个更智能的设备如果得知错误,可能能够有效地调度流量。例如,SMMU 被配置为中止错误的事务,并将错误通知设备。设备将事件报告给其设备驱动程序,后者解决页面错误的原因。这种方法的优点是避免了在 SMMU 中暂停流量,这可能会影响其他事务。然而,使用这种方法需要特定设备的软件代码。例如,Linux 不支持 SVA 对于仅支持中止错误事务的非 PCIe 设备

类似的方法也被 PCIe PRI 使用,PRI 在 ATS 响应中将错误报告回设备。PRI 提供了一个标准的页面请求接口(Page Request Interface),使设备能够请求软件通过根端口和 SMMU 解决页面错误。PRI 不要求设备特定的页面错误解决例程,这有助于减少标准软件(如虚拟机管理程序)中的设备特定软件需求。

在 Linux 中,VFIO 子系统提供了一个接口,以启用应用程序的 SVA。要支持 SVA,设备、总线和 SMMU 必须支持以下功能

  • 每个设备多个地址空间,例如使用 PCI PASID 扩展。SMMU 驱动程序分配 PASID,设备在 DMA 事务中使用它。
  • I/O 页面错误:
    • 对于 PCIe 设备,需要 PRI。
    • 对于非 PCIe 设备,需要使用 Stall 模型。
    • 核心内存管理处理来自 SMMU 的转换错误。
  • MMU 和 SMMU 实现兼容的页面表格式。

http://www.kler.cn/a/468885.html

相关文章:

  • 【Uniapp-Vue3】image媒体组件属性
  • (转)rabbitmq怎么保证消息不丢失?
  • 实现AVL树
  • pytest测试用例管理框架特点及常见语法和用法分享
  • Nginx——静态资源部署(二/五)
  • 数据仓库中的指标体系模型介绍
  • 解决 ssh connect to host github.com port 22 Connection timed out
  • 基于springboot的课程作业管理系统(源码+数据库+文档)
  • 第5章:索引和性能优化
  • JVM之垃圾回收器概述的详细解析
  • C++进阶:AVL树
  • BBP飞控板中的坐标系变换
  • 利用Mallet进行文本挖掘—— 主题模型与垃圾邮件检测
  • ansible-性能优化
  • 了解RabbitMQ:强大的开源消息队列中间件
  • 【可实战】Bug的判定标准、分类、优先级、定位方法、提交Bug(包含常见面试题)
  • Go语言的 的注解(Annotations)基础知识
  • 【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 4:MHE表示能力
  • 我在广州学 Mysql 系列——有关数据表的插入、更新与删除相关练习
  • Go语言的 的编程环境(programming environment)基础知识
  • CBAM (Convolutional Block Attention Module)注意力机制详解
  • Docker-Compose安装和使用
  • 联发科MTK6771/MT6771安卓核心板规格参数介绍
  • 曲靖郎鹰金属构件有限公司受邀出席第十七届中国工业论坛
  • vulnhub——Earth靶机
  • 单片机-LED实验