IOMMU原理分析以及在Linux中初始化

本文介绍了虚拟化技术中的IOMMU(输入/输出内存管理单元)及其作用,它是如何处理外部设备的地址转换和访问权限的。同时,详细阐述了ATS(地址转换服务)机制,包括PCI设备的DMA操作、AT字段的三种状态以及ATC(地址转换缓存)的工作原理。此外,还提到了IOMMU在Ubuntu和Centos系统中的启用步骤。通过理解这些技术,可以更好地掌握虚拟环境中的设备管理和内存访问控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、IOMMU

      虚拟化技术:多进程共享一个CPU ,多进程虚拟空间共享同一物理内存,一个处理器系统运行多个处理系统技术。也就是虚拟环境相互独立互不干扰使用相同物理资源。

       虚拟化核心技术VMM(Virtual Machine Monitor)集中管理物理资源,每个虚拟处理器系统需要通过VMM访问物理资源。VMM管理PCI设备机制有:IOMMU, PCIe总线ATS机制,SR-IOV(Single Root I/O Virtualization)和MR-IOV(Multi-Root I/O Virtualization)。

       多进程共享一个CPU:MMU机制使每个进程有独立虚拟地址空间,互不干扰。从两方面实现一是进行地址转换,将不听进程的虚拟地址转换为物理地址;二是对物理地址访问进行权限检查,判断地址转化合理性。

      IOMMU与MMU相似,IOMMU是把外部设备地址到存储器地址的转换。IOMMU中存放了IO页表虚实地址转换关系和访问权限,而且处理器加速虚实地址转换,还设置了IOTLB作为IO页表的Cache。

 

       PCI Device A/B进行DMA操作时使用的物理地址是PCI总线域的物理地址,用地址路由或者ID路由进行存储器读写TLP传递,这个PCI总线地址与GAP地址一一对应相等。在虚拟环境下PCI设备与Domain有明确对应关系,当PCI设备进行DMA读写时,TLP首先到达地址转换部件TA(Translation Agent),并通过ATPT(Address Translation and Protection Table)将PCI总线域的物理地址转换为与GPA地址对应的HPA地址,然后对主存储器进行读写操作。PCI设备并不知道PCI设备与Domain有明确对应关系,这种操作是由TA和ATPT决定的。RC把PCI总线地址转换为存储器域地址,TA转换为合适的HPA地址。

     IA处理器和AMD处理器使用不同技术实现TA和ATPT,其中IA使用VT-d,AMD使用IOMMU。

    PCI设备进行DMA操作是,首先从相应的Device Table的Entry 获取“Level 4 Page Table Address”指针,并定位设备使用的I/0页表,最后使用多级页表结构完成PCI总线地址到HPA地址的转换。

二、ATS

       ATC(Address Translation Cache)存放了ATPT部分内容,当PCIE使用地址路由方式发送TLP时,地址首先通过ATC转换为HPA地址。如果地址没有在ATC命中,PCIe设备将通过存储器读TLP从ATPT中获取相应的地址转换信息,更新ATC后,再发送TLP。与其他Cache类似,ATC还可以被Invalidate。当ATPT被更改时,处理器将发送Invalidate报文,同步ATC。

2.1TLP中AT字段

       PCIe总线在TLP中设置了AT字段支持ATS机制,并且只有处理器支持IOMMU时,PCIe设备才可以使用ATS机制。

AT字段为0b00:

      当AT字段为0b00时,表示TLP的Address没有通过ATC转换,存放是PCI总线域的物理地址。

1.不支持ATS 机制,处理器不支持IOMMU;TLP的Address是PCI总线域的物理地址,进行DMA操作时,该地址被RC转换为存储器域的物理地址,然后对存储器进行读写操作。

2. 不支持ATS机制,处理器支持IOMMU;TLP的Address是PCI总线域的物理地址,进行DMA操作时,该地址被TA根据I/O页表转换为存储器域的物理地址,然后对存储器进行读写操作。

3. 支持ATS机制,处理器支持IOMMU;进行DMA操作时,该数据被传送到对存储器进行读写操作。

AT字段为0b01:

        支持ATS机制的设备必须支持0b01报文,该报文为“Translation Request”,该报文由PCIe设备通过存储器读请求TLP发出,其目的为TA。TA收到报文后将根据I/O页表设置,将合适的地址转换关系通过存储器读完成TLP,发送给PCIe设备,PCIe设备收到这个地址转换关系后,将更新ATC。该TLP有64位和32位两种格式。

AT字段为0b10:

        当AT字段为0b10时,表示TLP的Address已经通过ATC转换,进行DMA操作时,RC收到这些报文将不会通过TA和ATPT转换,而直接将数据发送给存储器。经过ATC转换后TLP的Address字段存放的依然是PCI总线域的物理地址,该物理地址为HPA地址在PCI总线域中的映像。

        无论PCIe设备是否使用ATC机制,在TLP中存放的Address字段仍然保存是PCI总线地址。

2.2地址转换请求-- Translation Request

        PCIe使用地址转换请求(Translation Request)TLP向TA提交地址转换请求。该TLP具有64位和32位两种地址格式,并且AT字段为0b01表示当前报文为地址转换请求TLP。该报文将Untranslated Address 字段发送到TA,而TA根据ATPT将Untranslated Address数据区域进行翻译,如果翻译成功TA使用CpI(从存储器读完成TLP)将地址转换关系发送给PCIe设备,PCIe设备收到这个存储器读完成TLP将这个地址转换关系保存在PCIe设备的ATC中。否则使用CpI将失败信息发送给PCIe设备。PCIe设备发送一个地址转换请求后,可能会从TA得到多个地址转换关系,这些地址转换关系可以使用一个存储器读完成TLP发送给PCIe设备。

ATC未命中处理方式:

  1. 使用AT 为0b00 的TLP使用Untranslated Address直接访问存储器,因此TA根据ATPT将Untranslated Address进行地址转换,然后再将报文发送到存储器中。
  2. 使用地址转换请求(Translation Request)TLP向TA提交地址转换请求,并从ATPT获得地址转换关系后,使用TA为0b10的存储器读写TLP,使用Translated Address与主存储器进行数据交换。

2.3Invalidate ATC

       当ATPT被更改时,需要使用MsgD报文通知PCIe设备,并用Invalidate ATC中相应Entry,该MsgD被称为“Invalidate Request Message”,收到一个MsgD只能Invalidate ATC中一个Entry。

三、IOMMU Enable

Ubuntu:

  1. 在vbios中打开iommu
  2. 在hygon CPU IOMMU默认是打开不用配置, 其余CPU /etc/default/grub GRUB_CMDLINE_LINUX="intel_iommu=on(或者amd_iommu=on,iommu=off可关闭)"
  3. 生成配置文件grub-mkconfig -o /boot/grub/grub.cfg,
  4. 重启系统
  5. dmesg | grep -e DMAR -e IOMMU查看IOMMU是否打开,下图为打开状态:

 

Centos:

  1. 打开BIOS中的虚拟化开关(VT-d)
  2. 激活linux内核的VT-d开关。
  1. 编辑/etc/sysconfig/grub文件(系统引导文件),找到rhgb quiet,在后面添加intel_iommu=on或者amd_iommu=on。
  2. 使用grub-mkconfig  –o  /boot/grub/grub.cfg生成新的系统引导菜单(或者是grub2-mkconfig)
  3. 重启使设置生效
  4. 使用dmesg | grep -e DMAR -e IOMMU,查看IOMMU是否启用

 

### Linux IOMMU配置与使用 #### 配置IOMMU支持 在Linux系统中启用IOMMU功能通常涉及修改GRUB引导加载程序的配置文件。对于Ubuntu系统,可以通过编辑`/etc/default/grub`文件来添加必要的内核参数[^3]: ```bash sudo nano /etc/default/grub ``` 找到如下行并加入`intel_iommu=on`或`amd_iommu=on`取决于使用的处理器架构: ```plaintext GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_iommu=on" ``` 保存更改后更新GRUB配置并重启计算机以应用新的设置。 #### 检查IOMMU状态 要验证当前系统的IOMMU状态,可以查看内核变量`iommu_detected`。该变量表示主机环境中是否检测到了IOMMU硬件的存在;如果值为1,则说明已成功识别到IOMMU装置[^4]: ```bash cat /sys/module/iommu/parameters/detected ``` #### 使用IOMMU进行DMA操作 当涉及到直接存储器访问(DMA)时,IOMMU提供了重要的保护机制和服务。通过映射设备可见的虚拟地址至实际物理地址空间,确保数据传输的安全性和效率的同时减少了CPU开销[^5]。例如,在处理共享虚拟内存(SVM)特性时,Intel IOMMU的支持尤为关键[^1]。 #### 编程接口与API调用 针对特定应用场景下的开发工作,开发者可能需要借助于一系列编程接口(APIs),这些接口允许应用程序请求创建、销毁以及查询IOMMU域的信息。具体来说,包括但不限于以下几个方面: - 创建一个新的IOMMU上下文(`io_domain`) - 将PCI设备绑定到指定的IOMMU上下文中 - 执行页表项(Page Table Entry, PTE)的操作如分配、释放等 下面给出一段简单的C语言代码片段展示如何获取默认的IOMMU组ID: ```c #include <stdio.h> #include <fcntl.h> #include <unistd.h> int main() { int fd; char buf[64]; snprintf(buf, sizeof(buf), "/sys/class/iommu/%d/groups", 0); fd = open("/dev/iommu", O_RDONLY); if (fd >= 0) { read(fd, buf, sizeof(buf)); printf("Default group ID: %s\n", buf); close(fd); } else { perror("Failed to get default iommu group"); } return 0; } ``` 此段代码仅作为概念演示用途,并未考虑错误处理等问题的实际生产环境需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值