0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

IOMMU功能简介

Linux阅码场 来源:Linuxer 2020-08-03 15:55 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1.IOMMU

1.1 IOMMU功能简介

IOMMU主要功能包括DMA Remapping和Interrupt Remapping,这里主要讲解DMA Remapping,Interrupt Remapping会独立讲解。对于DMA Remapping,IOMMU与MMU类似。IOMMU可以将一个设备访问地址转换为存储器地址,下图针对有无IOMMU情况说明IOMMU作用。


在没有IOMMU的情况下,网卡接收数据时地址转换流程,RC会将网卡请求写入地址addr1直接发送到DDR控制器,然后访问DRAM上的addr1地址,这里的RC对网卡请求地址不做任何转换,网卡访问的地址必须是物理地址。

对于有IOMMU的情况,网卡请求写入地址addr1会被IOMMU转换为addr2,然后发送到DDR控制器,最终访问的是DRAM上addr2地址,网卡访问的地址addr1会被IOMMU转换成真正的物理地址addr2,这里可以将addr1理解为虚机地址。

左图是没有IOMMU的情况,对于虚机无法实现设备的透传,原因主要有两个:一是因为在没有IOMMU的情况下,设备必须访问真实的物理地址HPA,而虚机可见的是GPA;二是如果让虚机填入真正的HPA,那样的话相当于虚机可以直接访问物理地址,会有安全隐患。所以针对没有IOMMU的情况,不能用透传的方式,对于设备的直接访问都会有VMM接管,这样就不会对虚机暴露HPA。

右图是有IOMMU的情况,虚机可以将GPA直接写入到设备,当设备进行DMA传输时,设备请求地址GPA由IOMMU转换为HPA(硬件自动完成),进而DMA操作真实的物理空间。IOMMU的映射关系是由VMM维护的,HPA对虚机不可见,保障了安全问题,利用IOMMU可实现设备的透传。这里先留一个问题,既然IOMMU可以将设备访问地址映射成真实的物理地址,那么对于右图中的Device A和Device B,IOMMU必须保证两个设备映射后的物理空间不能存在交集,否则两个虚机可以相互干扰,这和IOMMU的映射原理有关,后面会详细介绍。

1.2 IOMMU作用

根据上一节内容,总结IOMMU主要作用如下:

屏蔽物理地址,起到保护作用。典型应用包括两个:一是实现用户态驱动,由于IOMMU的映射功能,使HPA对用户空间不可见,在vfio部分还会举例。二是将设备透传给虚机,使HPA对虚机不可见,并将GPA映射为HPA

IOMMU可以将连续的虚拟地址映射到不连续的多个物理内存片段,这部分功能于MMU类似,对于没有IOMMU的情况,设备访问的物理空间必须是连续的,IOMMU可有效的解决这个问题

1.3 IOMMU工作原理

前面简单介绍了IOMMU的映射功能,下面讲述IOMMU到底如何实现映射的,为便于分析,这里先不考虑虚拟化的场景,以下图为例,阐述工作原理。

IOMMU的主要功能就是完成映射,类比MMU利用页表实现VA->PA的映射,IOMMU也需要用到页表,那么下一个问题就是如何找到页表。在设备发起DMA请求时,会将自己的Source Identifier(包含Bus、Device、Func)包含在请求中,IOMMU根据这个标识,以RTADDR_REG指向空间为基地址,然后利用Bus、Device、Func在Context Table中找到对应的Context Entry,即页表首地址,然后利用页表即可将设备请求的虚拟地址翻译成物理地址。这里做以下说明:

图中红线的部门,是两个Context Entry指向了同一个页表。这种情况在虚拟化场景中的典型用法就是这两个Context Entry对应的不同PCIe设备属于同一个虚机,那样IOMMU在将GPA->HPA过程中要遵循同一规则

由图中可知,每个具有Source Identifier(包含Bus、Device、Func)的设备都会具有一个Context Entry。如果不这样做,所有设备共用同一个页表,隶属于不同虚机的不同GPA就会翻译成相同HPA,会产生问题,

有了页表之后,就可以按照MMU那样进行地址映射工作了,这里也支持不同页大小的映射,包括4KB、2MB、1GB,不同页大小对应的级数也不同,下图以4KB页大小为例说明,映射过程和MMU类似,不再详细阐述。

1.4 Source Identifier

在讲述IOMMU的工作原理时,讲到了设备利用自己的Source Identifier(包含Bus、Device、Func)来找到页表项来完成地址映射,不过存在下面几个特殊情况需要考虑。

对于由PCIe switch扩展出的PCI桥及桥下设备,在发送DMA请求时,Source Identifier是PCIe switch的,这样的话该PCI桥及桥下所有设备都会使用PCIe switch的Source Identifier去定位Context Entry,找到的页表也是同一个,如果将这个PCI桥下的不同设备分给不同虚机,由于会使用同一份页表,这样会产生问题,针对这种情况,当前PCI桥及桥下的所有设备必须分配给同一个虚机,这就是VFIO中组的概念,下面会再讲到。

对于SRIO-V,之前介绍过VF的Bus及devfn的计算方法,所以不同VF会有不同的Source Identifier,映射到不同虚机也是没有问题的

2.VFIO

VFIO就是内核针对IOMMU提供的软件框架,支持DMA Remapping和Interrupt Remapping,这里只讲DMA Remapping。VFIO利用IOMMU这个特性,可以屏蔽物理地址对上层的可见性,可以用来开发用户态驱动,也可以实现设备透传。

2.1 概念介绍

先介绍VFIO中的几个重要概念,主要包括Group和Container。

Group:group 是IOMMU能够进行DMA隔离的最小硬件单元,一个group内可能只有一个device,也可能有多个device,这取决于物理平台上硬件的IOMMU拓扑结构。设备直通的时候一个group里面的设备必须都直通给一个虚拟机。不能够让一个group里的多个device分别从属于2个不同的VM,也不允许部分device在host上而另一部分被分配到guest里, 因为就这样一个guest中的device可以利用DMA攻击获取另外一个guest里的数据,就无法做到物理上的DMA隔离。

Container:对于虚机,Container 这里可以简单理解为一个VM Domain的物理内存空间。对于用户态驱动,Container可以是多个Group的集合。

上图中PCIe-PCI桥下的两个设备,在发送DMA请求时,PCIe-PCI桥会为下面两个设备生成Source Identifier,其中Bus域为红色总线号bus,device和func域为0。这样的话,PCIe-PCI桥下的两个设备会找到同一个Context Entry和同一份页表,所以这两个设备不能分别给两个虚机使用,这两个设备就属于一个Group。

2.2 使用示例

这里先以简单的用户态驱动为例,在设备透传小节中,在分析如何利用vfio实现透传。

int container, group, device, i; struct vfio_group_status group_status = { .argsz = sizeof(group_status) }; struct vfio_iommu_type1_info iommu_info = { .argsz = sizeof(iommu_info) }; struct vfio_iommu_type1_dma_map dma_map = { .argsz = sizeof(dma_map) }; struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; /* Create a new container */ container = open("/dev/vfio/vfio", O_RDWR); if (ioctl(container, VFIO_GET_API_VERSION) != VFIO_API_VERSION) /* Unknown API version */ if (!ioctl(container, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) /* Doesn't support the IOMMU driver we want. */ /* Open the group */ group = open("/dev/vfio/26", O_RDWR); /* Test the group is viable and available */ ioctl(group, VFIO_GROUP_GET_STATUS, &group_status); if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)) /* Group is not viable (ie, not all devices bound for vfio) */ /* Add the group to the container */ ioctl(group, VFIO_GROUP_SET_CONTAINER, &container); /* Enable the IOMMU model we want */ // type 1 open | attatch ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); /* Get addition IOMMU info */ ioctl(container, VFIO_IOMMU_GET_INFO, &iommu_info); /* Allocate some space and setup a DMA mapping */ dma_map.vaddr = mmap(0, 1024 * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); dma_map.size = 1024 * 1024; dma_map.iova = 0; /* 1MB starting at 0x0 from device view */ dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE; ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map); /* Get a file descriptor for the device */ device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, "00000d.0"); /* Test and setup the device */ ioctl(device, VFIO_DEVICE_GET_INFO, &device_info);

对于dev下Group就是按照上一节介绍的Group划分规则产生的,上述代码描述了如何使用VFIO实现映射,对于Group和Container的相关操作这里不做过多解释,主要关注如何完成映射,下图解释具体工作流程。

首先,利用mmap映射出1MB字节的虚拟空间,因为物理地址对于用户态不可见,只能通过虚拟地址访问物理空间。然后执行ioctl的VFIO_IOMMU_MAP_DMA命令,传入参数主要包含vaddr及iova,其中iova代表的是设备发起DMA请求时要访问的地址,也就是IOMMU映射前的地址,vaddr就是mmap的地址。VFIO_IOMMU_MAP_DMA命令会为虚拟地址vaddr找到物理页并pin住(因为设备DMA是异步的,随时可能发生,物理页面不能交换出去),然后找到Group对应的Contex Entry,建立页表项,页表项能够将iova地址映射成上面pin住的物理页对应的物理地址上去,这样对用户态程序完全屏蔽了物理地址,实现了用户空间驱动。IOVA地址的00x100000对应DRAM地址0x100000000x10100000,size为1024 * 1024。一句话概述,VFIO_IOMMU_MAP_DMA这个命令就是将iova通过IOMMU映射到vaddr对应的物理地址上去。

3.设备透传分析

设备透传就是由虚机直接接管设备,虚机可以直接访问MMIO空间,VMM配置好IOMMU之后,设备DMA读写请求也无需VMM借入,需要注意的是设备的配置空间没有透传,因为VMM已经配置好了BAR空间,如果将这部分空间也透传给虚机,虚机会对BAR空间再次配置,会导致设备无法正常工作。

3.1 虚机地址映射

在介绍透传之前,先看下虚机的GPA与HVA和HPA的关系,以及虚机是如何访问到真实的物理地址的,过程如下图。

一旦页表建立好后,整个映射过程都是硬件自动完成的,对于上图有如下几点说明:

对于虚机内的页表,完成GVA到GPA的映射,虽然整个过程都是硬件自动完成,但有一点要注意下,在虚机的中各级页表也是存储在HPA中的,而CR3及各级页表中装的地址都是GPA,所以在访问页表时也需要借助EPT,上图中以虚线表示这个过程

利用虚机页表完成GVA到GPA的映射后,此时借助EPT实现GPA到HPA的映射,这里没有什么特殊的,就是一层层页表映射

看完上图,有没有发现少了点啥,是不是没有HVA。单从上图整个虚机寻址的映射过程来看,是不需要HVA借助的,硬件会自动完成GVA->GPA->HPA映射,那么HVA有什么用呢?这里从下面两方面来分析:1)Qemu利用iotcl控制KVM实现EPT的映射,映射的过程中必然要申请物理页面。Qemu是应用程序,唯一可见的只是HVA,这时候又需要借助mmap了,Qemu会根据虚机的ram大小,即GPA大小范围,然后mmap出与之对应的大小,即HVA。通过KVM_SET_USER_MEMORY_REGION命令控制KVM,与这个命令一起传入的参数主要包括两个值,guest_phys_addr代表虚机GPA地址起始,userspace_addr代表上面mmap得到的首地址(HVA)。传入进去后,KVM就会为当前虚机GPA建立EPT映射表实现GPA->HPA,同时会为VMM建立HVA->HPA映射。2)当vm_exit发生时,VMM需要对异常进行处理,异常发生时VMM能够获取到GPA,有时VMM需要访问虚机GPA对应的HPA,VMM的映射和虚机的映射方式不同,是通过VMM完成HVA->HPA,且只能通过HVA才能访问HPA,这就需要VMM将GPA及HVA的对应关系维护起来,这个关系是Qemu维护的,这里先不管Qemu的具体实现(后面会有专门文档介绍),当前只需要知道给定一个虚机的GPA,虚机就能获取到GPA对应的HVA。下图描述VMM与VM的地址映射关系。

3.2 设备透传实现

在前面介绍VFIO的使用实例时,核心思想就是IOVA经过IOMMU映射出的物理地址与HVA经过MMU映射出的物理地址是同一个。对于设备透传的情况,先上图,然后看图说话。

先来分析一下设备的DMA透传的工作流程,一旦设备透传给了虚机,虚机在配置设备DMA时直接使用GPA。此时GPA经由EPT会映射成HPA1,GPA经由IOMMU映射的地址为HPA2,此时的HPA1和HPA2必须相等,设备的透传才有意义。下面介绍在配置IOMMU时如何保证HPA1和HPA2相等,在VFIO章节讲到了VFIO_IOMMU_MAP_DMA这个命令就是将iova通过IOMMU映射到vaddr对应的物理地址上去。对于IOMMU来讲,此时的GPA就是iova,我们知道GPA经由EPT会映射为HPA1,对于VMM来讲,这个HPA1对应的虚机地址为HVA,那样的话在传入VFIO_IOMMU_MAP_DMA命令时讲hva作为vaddr,IOMMU就会将GPA映射为HVA对应的物理地址及HPA1,即HPA1和HPA2相等。上述流程帮助理清整个映射关系,实际映射IOMMU的操作很简单,前面提到了qemu维护了GPA和HVA的关系,在映射IOMMU的时候也可以派上用场。注:IOMMU的映射在虚机启动时就已经建立好了,映射要涵盖整个GPA地址范围,同时虚机的HPA对应的物理页都不会交换出去(设备DMA交换是异步的)。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 控制器
    +关注

    关注

    114

    文章

    17877

    浏览量

    195109
  • dma
    dma
    +关注

    关注

    3

    文章

    582

    浏览量

    106268
  • gpa
    gpa
    +关注

    关注

    0

    文章

    7

    浏览量

    4864

原文标题:VFIO概述

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    AN - 1305 LM5030评估板:功能、原理与使用指南

    一款采用LM5030 100V推挽电流模式PWM控制器的全功能推挽式转换器。 文件下载: LM5030EVAL.pdf 一、评估板简介 AN - 1305评估板为设计工程师提供了一个使用LM5030
    的头像 发表于 04-21 10:30 119次阅读

    预期功能安全是什么?(上)

    刹。 可预见的人为误用: 聚集于用户对自动驾驶功能的不正确理解和使用,例如:L2 级自动驾驶场景下,驾驶员过度依赖、分心接管不及时,或在非设计场景(如市区)激活高速辅助功能,放大安全风险。 未知场景
    发表于 04-10 09:21

    Cadence Virtuoso Dashboard功能简介

    我们全新的 AI 驱动的定制设计解决方案——Virtuoso Studio,依托 30 年的行业积淀与领导地位,带来了创新功能、重塑的基础设施以实现极致生产力,并突破经典设计边界,达到全新的集成高度。在本博客系列中,你将了解顶尖模拟设计工具的全新升级,助你从容应对复杂设计挑战。
    的头像 发表于 04-01 09:57 745次阅读

    CET消防设备电源监控系统简介

    电子发烧友网站提供《CET消防设备电源监控系统简介 .pdf》资料免费下载
    发表于 03-18 15:11 0次下载

    Simlab+CAD+Hyperstudy联合优化几何参数

    议程联合优化功能概述实用案例软件简介-HyperStudy概述-HyperStudy解决什么问题-HyperStudy主要功能-SimLa
    的头像 发表于 03-04 18:20 260次阅读
    Simlab+CAD+Hyperstudy联合优化几何参数

    RK平台Linux IOMMU开发:从原理到实战

    在瑞芯微(RK)芯片的 Linux 开发中,IOMMU(输入输出内存管理单元)是个关键部件 —— 它能实现设备虚拟地址(IOVA)与物理地址的转换,还能控制读写权限、处理缺页 / 总线异常,广泛用于
    的头像 发表于 02-04 16:24 2760次阅读
    RK平台Linux <b class='flag-5'>IOMMU</b>开发:从原理到实战

    各种显示技术简介

    各种 显示****技术简介 致力成为差异化显示领域中全链路方案的领先者 ** 各种显示器方案** 1.多种规格的芯片,根据不同功能,选择最合适的芯片 2.适应场景多,兼容性强 3.画质好,色彩
    发表于 02-02 15:51

    比较器的简介分类

    一、比较器简介据圣邦微SGMICRO比较器一级代理鑫富立介绍,比较器是一种得到广泛使用的电路元件。实际上也是增益非常高的运算放大器,可以放大输入端很小的差分信号,并驱动输出端切换到两个输出状态中的一
    的头像 发表于 11-21 20:13 644次阅读
    比较器的<b class='flag-5'>简介</b>分类

    AXI GPIO扩展e203 IO口简介

    AXI GPIO简介 AXI-GPIO是一种Xilinx公司开发的外设IP,可以连接到AXI总线上,并提供GPIO(General Purpose Input Output)功能。AXI-GPIO
    发表于 10-22 08:14

    英集芯IP2302带路径管理功能单节锂电池线性充电器

    IP2302带路径管理功能单节锂电池线性充电器简介3简介IP2302是一款高度集成的、高性能的支持路径管理 1节锂离子电池线性充电器。IP2302具有涓流充电(TC)、恒流(CC)和恒压(CV)充电
    发表于 10-10 18:53 1次下载

    车机DAB功能验证方法论及测试三神器简介

    本文不拘泥于某个具体的功能点进行讨论,譬如Linking、Announcement、Reconfiguration、SLS、SPI、EPG或是DLS等,而是从更高一维度来分析DAB功能验证的方法论
    的头像 发表于 08-10 15:29 4765次阅读
    车机DAB<b class='flag-5'>功能</b>验证方法论及测试三神器<b class='flag-5'>简介</b>

    STM32项目分享:智能鱼缸/水族箱/水产养殖系统

    01—项目简介1.功能详解STM32智能鱼缸/水族箱/水产养殖系统功能如下:可检测温度,水位
    的头像 发表于 07-03 18:24 1302次阅读
    STM32项目分享:智能鱼缸/水族箱/水产养殖系统

    FPC组成简介及工程设计规范

    FPC产品简介概述: 1,FPC概念 2,FPC产品结构组成 3,FPC材料 4,FPC产品类型 5,FPC产品特征 FPC(Flexible Printed Circuit)挠性印刷电路版,简称
    发表于 05-27 15:10

    蓝牙LE Audio技术简介和优势分析

    Energy)技术的优点,同时又具备卓越的音频性能。本文将从技术简介和优势分析两个方面对蓝牙LE Audio技术进行详细的介绍。 一、蓝牙LE Audio技术简介 蓝牙LE Audio技术是蓝牙技术联盟在
    的头像 发表于 05-21 16:08 5175次阅读