Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3662868
  • 博文数量: 216
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 7464
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-23 18:56
个人简介

将晦涩难懂的技术讲的通俗易懂

文章分类

全部博文(216)

文章存档

2025年(8)

2024年(11)

2023年(9)

2022年(4)

2021年(12)

2020年(8)

2019年(18)

2018年(19)

2017年(9)

2016年(26)

2015年(18)

2014年(54)

2013年(20)

分类: LINUX

2025-03-16 00:46:48

RDMA为什么要Pin内存?

——lvyilonng316

    今晚面试了一个做RDMA的同学,有一个项目挺有意思,其中牵扯到RDMA pin内存的问题,所谓pin内存也叫锁页,就是固定虚拟地址和物理地址的映射,防止对应物理页面被swap。关于这类问题在过往面试中我也问过相关问题,但大部分人都是只回答出一部分,不够全面和深入。正好借此把这个问题大稍微展开一下,其实这个问题延伸下去可以很多。

     首先,明确我想问的问题是什么?正如题目所说,使用RDMA得时候为什么要pin内存?当然仅仅回答这个问题很简单,因为网卡要直接内存访问(DMA),RDMA网卡的MTTMemory Translation Table)需要进行地址翻译,准确的说是虚拟地址(VA)到物理地址的翻译(PA),而pin内存是为了不让这个地址映射关系发生变化,否则RDMA要访问虚拟地址A,本来对应的是物理地址a,如果不pin内存,这个时候操作系统把物理地址a进行swap,然后物理地址a又被另外一个进程拿去用了,这个时候RDMA再去访问虚拟地址A,经过MTT转换还是往a这个物理地址写,那就写了其他进程的内存,乱套了。。。

     但这只是问题的开始。我接下来想问的是非RDMA场景(例如普通TCP)应用也有DMA操作,为什么不用pin内存?什么?你说内核帮忙进行pin了,那基于DPDK用户态的高性能协议栈可以不pin吗?我们平时写程序用的都是虚拟内存,都要经过MMU地址翻译成物理内存,怎么我们写普通程序就不用pin内存?另外,我们知道普通网卡DMA的时候也需要地址翻译,这是通过IOMMU进行的,那RDMA为什么还要搞个MTT翻译,为什么不直接用IOMMU?下面开始逐个展开。

IOMMU的作用

IOMMU是系统级的硬件单元,负责保护主机内存免受DMA攻击(如恶意设备直接访问非授权内存区域),并提供虚拟地址到物理地址的转换(VA→PA的。所以这里IOMMU有两个功能,内存保护和地址翻译。前者是检查DMA目的地址的合法性,比如如果没有IOMMU,程序直接使用物理地址(PA)进行DMA,如果这个程序被攻击者控制,传入的是系统的其他物理地址,那么DMA就会读取或写入这个地址了,进而产生攻击。又例如,在虚拟化场景下,一个VM控制网卡DMA写入的物理地址对应的是另一个VM的内存,也会产生DMA攻击。对于后者则类似CPUMMUMMUVAPA的翻译,IOMMU则实现IOVAPA的翻译。

关于IOMMU的几个常见问题:

QIOMMU物理硬件位于哪个位置?

A:在CPU packageuncore部分,或者说我们常说的RC中;

Q:一个CPU有几个IOMMU单元?

A:有多个,这个与物理root port11的关系,即每个CPU的物理PCI口都有一个独立的IOMMU单元

Q:一个IOMMU单元与PCI设备的管理关系是什么?

A:每个IOMMU单元负责root port下挂载的所有设备,包括switchPF,以及PF生成的所有VF

MTT的作用

MTTMemory Translation Table)是RDMA硬件(如Mellanox InfiniBand网卡)内部的专用机制,用于将RDMA的虚拟内存地址(例如QP的虚拟地址)映射到物理内存页。所以同样是IO地址翻译,为什么不直接用IOMMU呢。这要从以IOMMUMTT下几个方面的不同说起:

MTTIOMMU的位置不同

如前所述,IOMMU是位于CPU RC中,每次地址反应是要经过CPU RC的,所以普通使用IOMMUDMA不需要CPU参与,只是不需要CPU的计算core参与,但是还是要经过CPU uncore的,是root port下发的设备共享的,而MTT是位于网卡设备上的,因此MTT的访问会更加高效。虽然有些高级网卡可以支持ATS,但是也存在cache miss的情况。因此位置不同决定了MTT的访问性能更好;

通用和专用

IOMMU是设备通用的地址转换,而MTTRDMA网卡内部的专用表结构,由驱动直接管理(绕过操作系统),支持更快的地址转换,而且不同网卡厂商可以针对RDMA场景定制优化。

    举个例子,例如MTT 是位于主机内存(DDR)上的,如果硬件每次做地址转换都到主机内存查询一遍表,肯定会影响数据传输的效率。所以实际方案中还需要考虑一些机制来解决这种问题,比如有些网卡(如海思)引入了MR HEM,来先让硬件快速找到MR对应的数据结构,然后根据MR查找MTT,将数据缓存的前两个内存页的物理地址保存到MR HEM 表的对象中,如果应用程序要求传输的数据量比较少,都位于前两个内存页,就可以直接从MR HEM 表的对象中获取内存页的物理地址,从而简化查询MTT表的步骤。另外还可以将{BANNED}最佳近使用的MR HEM/MTT 表中的表项暂存到硬件内部,避免每次都到DDR 中查表。

    此外,IOMMU通过Domain ID(如PCIe PASID)隔离设备内存访问,但无法感知RDMAMR粒度。MTT提供了对每个MR的精确控制,避免IOMMU的过度泛化。

MTTIOMMU的协同

    对于RDMA来说有了MTT是不是就不需要IOMMU了呢?要看什么场景,比如在物理机没有虚拟化的时候,确实使用RDMA也没必要开启IOMMU。但是在虚拟化场景,MTT虽然完成了地址翻译,但是还是需要IOMMU进行内存校验的,以确保MTT翻译的地址在合法范围内,避免DMA到其他虚拟机的内存。

当虚拟化遇到GPUDirect

     再稍微延伸一点。GPUDirect包括 GPUDirect StorageGPUDirect RDMAGPUDirect P2P。以GPUDirect P2P 为例,使用后将数据从源 GPU 复制到同一节点中的另一个 GPU 不再需要将数据临时暂存到主机内存中。

    

上面提到IOMMU是集成在RC中的一个部件,当设备访问主机内存时,它将设备访问时使用的地址转换为主机内存的地址,在虚拟化场景下可以将设备访问的GPA转换为HPA。而PCIe P2P是两个设备的直接通信,自然不在经过RC,也就无法经过IOMMU的地址翻译。这就导致了安全隐患。为了解决这个问题,就需要开启ACSAccess Control Services)特性,ACS是为了增强I/O虚拟化安全性而引入的,开启ACS也会强制PCIe P2P绕行RC

     无论是ACS的开启,还是IOMMU,都需要绕行RC, 安全是解决了,可是性能呢?例如GPUDirect RDMA如果每次都绕RC,性能完全没有优势。因此有一种方式可以借助MTT实现类似IOMMU GPA-HPA的翻译,同时通过ACS DTDirect Translated P2P实现PCIe switch对已翻译DMA请求的直接转发来解决绕行RC的问题。当然GPU间的GPUDirect P2P也有相关方案,这个有机会再展开。

为什么RDMApin内存

    RDMA要求应用程序在使用内存前显式注册内存区域(Memory Region, MR),此时驱动会:

  a. Pin内存:锁定物理内存,阻止操作系统换出或移动。

  b. 构建地址映射表(如MTT):将虚拟地址映射到物理地址,供网卡直接访问。

    为什么要pin内存其实再文章的{BANNED}最佳开头已经提到了。主要是为了地址翻译。只要涉及IO地址翻译,物理是IOMMU还是MTT都需要pin内存。那么普通TCP需要吗?这要分两个场景:

●    内核协议栈

传统TCP通信通过操作系统内核协议栈处理数据:用户态数据内核态Socket Buffer → 网卡DMA缓冲区。内核自身负责分配和固定用于DMA的内核缓冲区(如sk_buff),用户空间内存无需pin,因为数据会被复制到内核的固定区域。而内核网卡驱动分配出的内存本身就是物理地址固定的。并且通过内核的DMA映射接口(如dma_map_single())临时建立DMA映射,完成后立即解除映射。

用户态协议栈

如果是用户态协议栈,那用户态协议栈本身要不要pin内存呢。一般用户态协议栈都基于DPDK,而DPDK一般使用hugepagehugepage是不支持swap的,因此不显式pin也是没有问题的。那如果就是用普通的匿名内存呢?这种方式还是需要pin的,否则可能导致IOMMU缺页。

为什么MMU不需要pin内存?

接着上文,因为要地址翻译就要pin内存。那CPU{BANNED}最佳常用的MMU解决进程VAPA的翻译怎么不需要进程都pin内存,MMU缺页是很正常的现象。这是因为内核处理了MMU的缺页中断,在其中进行了页面的重映射。而IOMMU一般不支持动态缺页处理,当设备尝试访问未映射的虚拟地址时,IOMMU不会触发类似CPU的缺页中断,而是直接导致DMA错误(如PCIe错误或系统崩溃)。

不过也有一些新硬件设备支持触发的缺页机制(如ARM SMMUv3STALL模型),允许IOMMU暂停DMA操作并通知操作系统重新映射内存,或者一些intelCPU支持再IOMMU缺页时产生MMU-notifier提供内核处理,然而,当然这些是依赖硬件支持的。

阅读(73) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~