LWN:64位DMA的问题!

关注了就能看到更多这么棒的文章哦~

The trouble with 64-bit DMA

By Jonathan Corbet
August 11, 2022
DeepL assisted translation
https://lwn.net/Articles/904210/

我们生活在一个 64 位的世界里,甚至许多发行版提供方想完全停止支持 32 位系统了。然而,在我们的 64 位内核中潜伏着一个子系统尚未真正使用超过 32 位地址。最近一组 patch 试图在 I/O 内存管理单元(IOMMU)子系统中使用 64 位地址没能赶上合并窗口,这正展示了消除所有 32 位包袱是多么困难。

需要大量快速移动数据的外围设备都必须支持直接内存访问(DMA),才能得到合理的性能。正如 DMA 的名字所示,这些设备过去是可以直接访问系统的物理地址空间的内存的。不过,随着时间的推移,大多数系统已经转而在 device 和内存之间加入一个 IOMMU,原因有很多。例如,IOMMU 可以帮助确保设备只访问准备给它访问的内存。也可以使用 IOMMU 来使分散在物理内存中的 page 在设备看来像是连续的地址。

为了能使这一切发挥作用,设备驱动程序必须在向设备提供映射的地址之前,就给 I/O buffer 创建好 IOMMU 映射。这些地址被称为 I/O virtual address(或 IOVA),它看起来像物理地址,但有自己的 64 位地址空间。人们期望能够将该范围内的地址直接传递给设备,但生活并不那么简单;许多设备对它们实际能使用的地址位数有限制。内核的 DMA mapping 映射层代码就考虑到了这一点;驱动程序传入一个 mask,告知设备可以处理什么范围的地址,而内核则在这个范围内寻找一个地址。

不过,IOMMU 层带来了一个额外的限制,它会尽可能选择一个低于 4GB 的地址(即适合 32 位的地址)。在 PCI 总线的早期阶段,对 64 位地址进行 DMA 传输的设备必须在每次访问时都使用特殊的 "dual-address cycle"(DAC)模式;DAC cycle 比 single-address cycle 慢,很多设备要么根本没有实现它们,要么实现得有问题。将 IOVA 限制在 32 位范围内有助于提高性能,并避免了硬件错误(总是有可能出现这种情况)。

现在是 2022 年,PCI 总线已经被 PCI-Express 所取代,它在 DAC 地址方面没有同样的性能问题。人们可能会认为,目前的硬件不会再在 64 位地址方面出现问题了,因为目前 64 位地址并不是什么新技术了。不过,32 位的限制仍然存在,而且它正在给自己带来一些麻烦。早在六月,Robin Murphy 就发布了一个 patch,描述了这里的麻烦:

一旦 32 位空间变满,IOVA 分配器的表现就不那么好了。随着 DMA working set (工作集)越来越大,这种优化越来越适得其反,并为高带宽网络等使用场景下的 dma_map 代码执行路径增加了大量的开销。我们已经给 allocator 代码打了越来越多的修补补丁,试图减轻这种情况,但它仍然无法满足所有其他合理需求,尤其是尽可能地在给定的限制内满足请求。

乍一看来,4GB 的 DMA 地址空间似乎对任何人都足够了,但是一个大的系统,如果有合适的 workload,就会把这个空间分成碎片,后续分配就变得困难了。既然内核看起来是在进行没有必要的限制,仅仅是满足不再有意义的场景的限制,这里应该改变了,于是 Murphy 改变了默认值,这样 IOMMU 层将不再试图寻找一个 32 位兼容的地址,而是使用目标设备声称能支持的全部地址范围。这使得性能问题消失了,这是件好事。

但是,有问题的设备还是存在的,无法通过一个简单的内核 patch 来消灭掉。在某种意义上,这个问题现在甚至更糟糕了,因为 32 位的限制可能在过去一直掩盖了设备和相应的驱动程序中多年存在的 bug。驱动程序的作者,也许是一个没有经验的开发者,他还没有了解到硬件 data sheet 并不是完全可信的,他可能相信了这个文档描述,并告诉 DMA mapping 层,说他们的硬件可以正常处理 64 位 IOVA,而事实上,这个硬件不能处理。那么现在唯一能使该硬件正常工作的方案就是 IOMMU 层里面施加的 32 位的限制。

Murphy 承认,这个改动可能会暴露出这种 bug;patch 中包括了几个可以恢复旧日行为的选项。但 Murphy 想把它合入:

我们可以勇敢一点,把它默认设置为关闭,希望 CI 系统和开发者能发现并修复这些 bug,但预计那些重点面向桌面环境发行版的 config 中可能会想把它重新打开从而获得最大的兼容性。

IOMMU 的维护者 Joerg Roedel 合入了这个 patch,但是有保留意见。"我感到不是很乐观,但正如你所说的,让我们勇敢起来吧"。该 patch 随后在 6.0 合并窗口期间进入了 mainline。

但是,它并没有在 mainline 里停留多长时间。内核开发的核心规则之一就是不要破坏 Linus Torvalds 的工作机,这次就发生了这样的情况。他迅速 revert 了这个改动,说 "事实证明,既然我们一直都是这样做的,那么大家如果以为这样做会成功的话,那就是无可救药的天真了。我实际测试的第一台机器在启动时就坏了"。他补充说,Murphy 可以 "在十年之后再试试"。

当然,问题是由 32 位限制造成的问题在未来十年不可能自己就改善了。今后将会有越来越大的压力,至少在已知的那些可以正常工作的硬件上,应该把这种行为留下来。无论如何,社区将不得不找到一种方法来做改变,而又不破坏整个地球上的其他系统。也许驱动程序可以为已知的能正常工作的硬件设置一个新的 flag,或者可以单独维护某个 list。内核已经花了很多年的时间来掩盖硬件和驱动的缺陷;从这些补救措施中爬出来可能也需要一段时间。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

format,png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值