前言
之前一直在Intel平台下部署深度学习训练环境,但近来牙膏厂的CPU性能拉胯,尝试了一下AMD平台,没想到才安装 ubuntu 就翻车了,记录一下故障修复过程。
安装失败
官网上下载了 ubuntu 20.04 LTS,U盘纯净方式安装,收获一堆‘的”AMD-Vi completion-wait loop timed out“。
禁用 IOMMU
折腾半天,原来是AMD内存管理引擎引起的,可以简单关闭 IOMMU 先让安装可进行下去。
进入BIOS,选择 Chipset,找到 IOMMU 选择 Disable,禁用虚拟化
IOMMU设置
IOMMU 是什么?
在计算机领域,IOMMU(Input/Output Memory Management Unit)
是一个内存管理单元(Memory Management Unit
),它的作用是连接DMA-capable I/O
总线(Direct Memory Access-capable I/O Bus
)和主存(main memory
)。传统的内存管理单元会把CPU
访问的虚拟地址转化成实际的物理地址。而IOMMU
则是把设备(device
)访问的虚拟地址转化成物理地址。为了防止设备错误地访问内存,有些IOMMU
还提供了访问内存保护机制。参考下图:
IOMMU
的一个重要用途是在虚拟化技术(virtualization
):虚拟机上运行的操作系统(guest OS
)通常不知道它所访问的host-physical
内存地址。如果要进行DMA
操作,就有可能破坏内存,因为实际的硬件(hardware
)不知道guest-physical
和host-physical
内存地址之间的映射关系。IOMMU
根据guest-physical
和host-physical
内存地址之间的转换表(translation table
),re-mapping
硬件访问的地址,就可以解决这个问题。
优点
与内存的直接物理寻址 (DMA) 相比,拥有 IOMMU 的优势包括:
- 无需在物理内存中连续即可分配大内存区域——IOMMU 将连续的虚拟地址映射到底层的碎片物理地址。因此,有时可以避免使用向量 I/O。
- 不支持内存地址足够长以寻址整个物理内存的设备仍然可以通过 IOMMU 寻址整个内存,从而避免与将缓冲区复制到外设的可寻址内存空间或从外设的可寻址内存空间复制缓冲区相关的开销。
- 例如,x86 计算机可以使用 x86 处理器中的物理地址扩展(PAE) 功能对超过 4 GB 的内存进行寻址。尽管如此,普通的 32 位 PCI 设备根本无法寻址 4 GiB 边界以上的内存,因此无法直接访问它。如果没有 IOMMU,操作系统将不得不实现耗时的反弹缓冲区。
- 内存受到保护,免受尝试 DMA 攻击的
- 恶意设备和尝试错误内存传输的故障设备的影响,因为设备无法读取或写入尚未明确分配(映射)的内存。内存保护基于运行在 CPU 上的操作系统(见图)独占控制 MMU 和 IOMMU。这些设备在物理上无法绕过或破坏配置的内存管理表。
- 在虚拟化中,客户操作系统可以使用不是专门为虚拟化设计的硬件。显卡等性能更高的硬件使用DMA直接访问内存;在虚拟环境中,所有内存地址都由虚拟机软件重新映射,这会导致 DMA 设备出现故障。IOMMU 处理这种重新映射,允许在客户操作系统中使用本机设备驱动程序。
- 在某些架构中,IOMMU 还执行硬件中断重新映射,其方式类似于标准内存地址重新映射。
- IOMMU 可以支持外设内存分页。使用 PCI-SIG PCIe 地址转换服务 (ATS) 页面请求接口 (PRI) 扩展的外设可以检测内存管理器服务的需求并发出信号。
对于端口 I/O 是与内存地址空间不同的地址空间的系统架构,当 CPU 通过I/O 端口与设备通信时,不使用 IOMMU 。在端口 I/O 和内存映射到合适地址空间的系统架构中,IOMMU 可以转换端口 I/O 访问。
缺点
与内存的直接物理寻址相比,拥有 IOMMU 的缺点包括:
- 由于转换和管理开销(例如,页表遍历)而导致性能下降。
- 添加的 I/O页(转换)表的物理内存消耗。如果可以与处理器共享表,则可以缓解这种情况。
- 容易成为间谍软件的目标。通过内存访问进行内核级攻击是外部威胁滥用此漏洞的常见方式。
改进
显然简单关闭 IOMMU 并不是一个最佳选择,除非你想运行32位linux。在AMD 64位处理器系统上,IOMMU能力对于许多事情都是必要的,特别是 PCIE 的显卡加速。而采用"soft" IOMMU 则无法使用虚拟化,这里有一个推荐设置来修复这个问题。
- 编辑 /etc/default/grub 文件
sudo nano /etc/default/grub
- 修改 GRUB_CMDLINE_LINUX 参数
GRUB_CMDLINE_LINUX="amd_iommu=on iommu=pt"
- 更新 GRUB,重启电脑
sudo update-grub && sudo reboot
- 最后记得在 BIOS 中设置 IOMMU 为 enable(前文禁用的选项)
参考链接
https://bbs.archlinux.org/viewtopic.php?id=224265
https://en.wikipedia.org/wiki/Input-output_memory_management_unit
https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
https://forum.giga-byte.co.uk/index.php?topic=14802.msg105102#msg1051022