AMD IOMMU与Linux (4) -- Domain, Group, Device

2023-05-16

1. domain的本质是一个页表,1对1的关系

2. IOMMU_DOMAIN_UNMANAGED vs. IOMMU_DOMAIN_DMA

        a. IOMMU_DOMAIN_UNMANAGED    - DMA mappings managed by IOMMU-API user, used for VMs
        b. IOMMU_DOMAIN_DMA    - Internally used for DMA-API implementations. This flag allows IOMMU drivers to implement certain optimizations for these domains

IOMMU_DOMAIN_DMA对应default_domain

IOMMU_DOMAIN_UNMANAGED对应VFIO, 或者GPU自行创建的domain

多个domain解决的问题: 用户态发起的DMA,它自己在分配iova,直接设置下来,要求iommu就用这个iova,内核对这个设备做dma_map,也要分配iova, 两者(两个iova)冲突产生。

解决办法 就是:

VFIO:默认情况下,iommu(应该是DMA设备,而不是IOMMU)上会绑定一个default_domain,它具有IOMMU_DOMAIN_DMA属性,原来怎么弄就怎么弄,这时你可以调用dma_map()。但如果你要用VFIO,你就要(DMA设备)先detach原来的驱动,改用VFIO的驱动,VFIO就给你换一个domain,这个domain的属性是IOMMU_DOMAIN_UNMANAGED,之后你爱用哪个iova就用那个iova,你自己保证不会冲突就好,VFIO通过iommu_map(domain, iova, pa)来执行这种映射。

等你从VFIO上detach,把你的domain删除了,这个iommu(同上,应该是DMA设备,而不是IOMMU)就会恢复原来的default_domain,这样你就可以继续用你的dma API了。

这种情况下,你必须给你的设备选一种应用模式,非此即彼

vfio-pci [1]

vfio-pci 驱动中,把这个设备的io空间和iommu_group直接暴露到用户态

vfio_group是vfio对iommu_group的表述

The Intel IOMMU driver allocates a virtual address per domain. Each PCIE device has its own domain (hence protection). Devices under p2p bridges share the virtual address with all devices under the p2p bridge due to transaction id aliasing for p2p bridges.[7]

IOVA generation is pretty generic. We used the same technique as vmalloc() but these are not global address spaces, but separate for each domain. Different DMA engines may support different number of domains.[7]

Interrupt ranges are not address translated, (0xfee00000 - 0xfeefffff). The same is true for peer to peer transactions. Hence we reserve the address from PCI MMIO ranges so they are not allocated for IOVA addresses【7】

IOVA是有domain的属性的

中断, P2P, MMIO不作remapping

3. 关于PASID

AMD IOMMU支持PASID, 由Device ID (BDF) + PASID (TLP Prefix) + GVA构成GVA到SPA的translate

 

4. IOMMU group

从struct device与struct iommu_group的结构上可以看出,DMA设备隶属于一个iommu group (PCIE 协议中由拓扑结构中ACS支持与否等因素决定设备的iommu group 【3】【4】【5】), 而一个iommu group可以处于default domain或者其它的domain

struct device {

        ...

struct fwnode_handle        *fwnode; /* firmware device node */ @fwnode:     Associated device node supplied by platform firmware.

struct iommu_group        *iommu_group;  * @iommu_group: IOMMU group the device belongs to.

struct dev_iommu        *iommu;  * @iommu:      Per device generic IOMMU runtime data

        ...

};

struct iommu_group {

        ...

        struct iommu_domain *default_domain;

        struct iommu_domain *domain;

        ...

};

iommu.c关于PCI设备group的分配 相关函数:pci_device_group/get_pci_alias_group/get_pci_function_alias_group

/* PCI device grouping function */
extern struct iommu_group *pci_device_group(struct device *dev);
/* Generic device grouping function */
extern struct iommu_group *generic_device_group(struct device *dev);
/* FSL-MC device grouping function */
struct iommu_group *fsl_mc_device_group(struct device *dev);

另外,一个DMA设备与一个IOMMU是通过struct dev_iommu作为纽带:

struct device {

        ...

        struct iommu_group        *iommu_group;  * @iommu_group: IOMMU group the device belongs to.

        struct dev_iommu        *iommu; * @iommu:      Per device generic IOMMU runtime data

        ...

}

struct dev_iommu {

        ...

        struct iommu_device                *iommu_dev;

        ...

};

struct iommu_device {

        struct list_head list;

        const struct iommu_ops *ops;

        struct fwnode_handle *fwnode;

        struct device *dev;

};

5. 关于struct iommu_fwspec

其中,固件(比如DTS或者ACPI)对Topo和smmu的描述,从软件管理的角度,称为(定义为)iommu_fwspec,属于device,在device发现的时候就可以生成(比如pcie扫描或者devicetree/ACPI扫描的时候)【1】

struct dev_iommu {

        ...

        struct iommu_fwspec                *fwspec;

        ...

};

struct iommu_fwspec {

        const struct iommu_ops        *ops;

        struct fwnode_handle        *iommu_fwnode;

        u32                        flags;

        unsigned int                num_ids;

        u32                        ids[];

};

AMD IOMMU driver没有使用, 因其直接扫描IVRS

6. 关于aux domain, 见【2】

Reference:

[1] Linux iommu和vfio概念空间解构 - 知乎 (zhihu.com)

[2] IOMMU的现状和发展 - 知乎 (zhihu.com) 

【3】 pci: Enable overrides for missing ACS capabilities - Patchwork (kernel.org)

【4】IOMMU是如何划分PCI device group的? - 知乎 (zhihu.com)

【5】IOMMU group and PCIe ACS问题 - 知乎 (zhihu.com)

[7] 14. Linux IOMMU Support — The Linux Kernel documentation

[8]dmar 与 IOMMU | Linux Performance

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AMD IOMMU与Linux (4) -- Domain, Group, Device 的相关文章

  • 安装J语言的JQt IDE,出现错误

    我一直按照这里的说明进行操作 http code jsoftware com wiki System Installation Linux http code jsoftware com wiki System Installation L
  • 有谁知道在哪里定义硬件、版本和序列号。 /proc/cpuinfo 的字段?

    我想确保我的 proc cpuinfo 是准确的 目前它输出 Hardware am335xevm Revision 0000 Serial 0000000000000000 我可以在代码中的哪里更改它以给出实际值 这取决于 Linux 的
  • 为什么我可以直接从 bash 执行 JAR?

    我是一个长期从事 Java 工作的人 并且知道运行带有主类的 JAR 的方法MANIFEST MFJar 中的文件很简单 java jar theJar jar 我用它来启动 Fabric3 服务器 包含在bin server jar在其标
  • SSE:跨页边界的未对齐加载和存储

    我在页面边界旁边执行未对齐加载或存储之前读过某处 例如使用 mm loadu si128 mm storeu si128内在函数 代码应首先检查整个向量 在本例中为 16 个字节 是否属于同一页 如果不属于同一页 则切换到非向量指令 我知道
  • 将 jar 作为 Linux 服务运行 - init.d 脚本在启动应用程序时卡住

    我目前正在致力于在 Linux VM 上实现一个可运行的 jar 作为后台服务 我已经使用了找到的例子here https gist github com shirish4you 5089019作为工作的基础 并将 start 方法修改为
  • 我的线程图像生成应用程序如何将其数据传输到 GUI?

    Mandelbrot 生成器的缓慢多精度实现 线程化 使用 POSIX 线程 Gtk 图形用户界面 我有点失落了 这是我第一次尝试编写线程程序 我实际上并没有尝试转换它的单线程版本 只是尝试实现基本框架 到目前为止它是如何工作的简要描述 M
  • 如何确保应用程序在 Linux 上持续运行

    我试图确保脚本在开发服务器上保持运行 它会整理统计数据并提供网络服务 因此它应该会持续存在 但一天中有几次 它会因未知原因而消失 当我们注意到时 我们只需再次启动它 但这很麻烦 并且某些用户没有权限 或专有技术 来启动它 作为一名程序员 我
  • 我如何知道 C 程序的可执行文件是在前台还是后台运行?

    在我的 C 程序中 我想知道我的可执行文件是否像这样在前台运行 a out 或者像这样 a out 如果你是前台工作 getpgrp tcgetpgrp STDOUT FILENO or STDIN FILENO or STDERR FIL
  • 监视目录的更改

    很像一个类似的问题 https stackoverflow com questions 112276 directory modification monitoring 我正在尝试监视 Linux 机器上的目录以添加新文件 并希望在这些新文
  • 如何在c linux中收听特定接口上的广播?

    我目前可以通过执行以下操作来收听我编写的简单广播服务器 仅广播 hello int fd socket PF INET SOCK DGRAM 0 struct sockaddr in addr memset addr 0 sizeof ad
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost
  • Windows CE 与嵌入式 Linux [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 现在我确信我们都清楚 Linux 与 Windows 桌面的相对优点 然而 我对嵌入式开发世界的了解却少得多 我主要对行业解决方案感兴
  • 在 C++ linux 中将 STRINGS 写入串口

    我知道这个问题遍布互联网 但仍然没有任何东西能让我完全解决这个问题 我想用 C linux 将数据写入 Propeller 板的串行端口 从控制台获取输入时程序运行良好 但是当我向它写入字符串时总是返回 ERROR Invalid comm
  • 捕获实时流量时如何开启纳秒精度?

    如何告诉 libpcap v1 6 2 将纳秒值存储在struct pcap pkthdr ts tv usec 而不是微秒值 捕获实时数据包时 Note This question is similar to How to enable
  • Capistrano 3 部署无法连接到 GitHub - 权限被拒绝(公钥)

    我使用 Capistrano v3 和 capistrano symfony gem 设置了以下部署脚本 我正在使用 Ubuntu 14 4 部署到 AWS EC2 实例 我正在连接从 AWS 下载的 pem 文件 我的deploy rb中
  • 为什么我可以在 /proc/pid/maps 输出中看到几个相同的段?

    测试在32位Linux上进行 代码如下 int foo int a int b int c a b return c int main int e 0 int d foo 1 2 printf d n d scanf d e return
  • Linux 上的基准测试程序

    对于一项任务 我们需要使用不同的优化和参数来对我们的实现进行基准测试 有没有一种可行的方法可以在Linux命令行 我知道时间 上使用不同的参数对小程序进行基准测试 从而为我提供CSV或类似内容的时间数据 输出可能类似于 Implementa
  • Python 脚本作为 Linux 服务/守护进程

    Hallo 我试图让 python 脚本作为服务 守护进程 在 ubuntu linux 上运行 网络上存在多种解决方案 例如 http pypi python org pypi python daemon http pypi python
  • 如何在 GNU/Linux 上设置 Subversion (SVN) 服务器 - Ubuntu [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一台运行 Ubuntu 的笔记本电脑 我想将其用作 Subversion 服务器 既让我自己在本地承诺 也让其他人远程承诺 要使其
  • 嵌入式linux编写AT命令

    我在向 GSM 模块写入 AT 命令时遇到问题 当我使用 minicom b 115200 D dev ttySP0 term vt100 时它工作完美 但我不知道如何在 C 代码中做同样的事情 我没有收到任何错误 但模块对命令没有反应 有

随机推荐