rocky-rhel-grubby-iommu-学习记录

适用系统:Rocky Linux 9/10、RHEL 9/10、AlmaLinux 9/10、CentOS Stream 9/10


一、背景知识

1.1 什么是 IOMMU?

IOMMU(Input-Output Memory Management Unit)是设备直接内存访问(DMA)的地址翻译与保护单元,Intel 平台对应 VT-d (内核日志中表现为 DMAR),AMD 平台对应 AMD-Vi

场景 是否需要关闭 IOMMU
普通物理机、虚拟机宿主 ❌ 保持开启(安全性更好)
旧硬件兼容性问题 ✅ 考虑关闭
某些 PCIe 直通 / GPU 透传异常 ✅ 临时关闭调试
性能敏感且无虚拟化需求 ⚠️ 评估后决定

1.2 为什么要用 grubby 而不是改配置文件?

在 RHEL 8 之前,修改内核参数的标准做法是编辑 /etc/default/grub 后执行 grub2-mkconfig 重新生成引导配置。而在 RHEL 9/10 系列中,官方推荐直接使用 grubby
#mermaid-svg-f8H9RBvjPfn4ykgx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-f8H9RBvjPfn4ykgx .error-icon{fill:#552222;}#mermaid-svg-f8H9RBvjPfn4ykgx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-f8H9RBvjPfn4ykgx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-f8H9RBvjPfn4ykgx .marker.cross{stroke:#333333;}#mermaid-svg-f8H9RBvjPfn4ykgx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-f8H9RBvjPfn4ykgx p{margin:0;}#mermaid-svg-f8H9RBvjPfn4ykgx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster-label text{fill:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster-label span{color:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster-label span p{background-color:transparent;}#mermaid-svg-f8H9RBvjPfn4ykgx .label text,#mermaid-svg-f8H9RBvjPfn4ykgx span{fill:#333;color:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .node rect,#mermaid-svg-f8H9RBvjPfn4ykgx .node circle,#mermaid-svg-f8H9RBvjPfn4ykgx .node ellipse,#mermaid-svg-f8H9RBvjPfn4ykgx .node polygon,#mermaid-svg-f8H9RBvjPfn4ykgx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-f8H9RBvjPfn4ykgx .rough-node .label text,#mermaid-svg-f8H9RBvjPfn4ykgx .node .label text,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape .label,#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape .label{text-anchor:middle;}#mermaid-svg-f8H9RBvjPfn4ykgx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-f8H9RBvjPfn4ykgx .rough-node .label,#mermaid-svg-f8H9RBvjPfn4ykgx .node .label,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape .label,#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape .label{text-align:center;}#mermaid-svg-f8H9RBvjPfn4ykgx .node.clickable{cursor:pointer;}#mermaid-svg-f8H9RBvjPfn4ykgx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-f8H9RBvjPfn4ykgx .arrowheadPath{fill:#333333;}#mermaid-svg-f8H9RBvjPfn4ykgx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-f8H9RBvjPfn4ykgx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-f8H9RBvjPfn4ykgx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-f8H9RBvjPfn4ykgx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-f8H9RBvjPfn4ykgx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-f8H9RBvjPfn4ykgx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster text{fill:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster span{color:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-f8H9RBvjPfn4ykgx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx rect.text{fill:none;stroke-width:0;}#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape p,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape .label rect,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-f8H9RBvjPfn4ykgx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-f8H9RBvjPfn4ykgx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-f8H9RBvjPfn4ykgx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} grubby 方式(直接、安全)
grubby --update-kernel

一条命令
重启生效
传统方式(步骤多、易出错)
编辑

/etc/default/grub
grub2-mkconfig

重新生成配置
重启生效

核心优势

  • ✅ 直接修改 BTF / BLS(Boot Loader Specification)条目,无需重新生成引导配置
  • ✅ 自动适配 BIOS/Legacy 与 UEFI 的引导配置路径差异(无需记忆 grub.cfg 到底在 /boot/grub2/ 还是 /boot/efi/EFI/rocky/);
  • ✅ 支持精确到单个内核条目全部内核的操作,可脚本化;
  • ✅ 配合 --remove-args 可干净回滚。

1.3 关键参数说明

参数 作用 适用平台
intel_iommu=off 关闭 Intel VT-d Intel
amd_iommu=off 关闭 AMD-Vi AMD
iommu=off 彻底禁用 IOMMU 子系统(一刀切,影响面大) 通用
iommu=pt 直通模式:仅对直通设备启用 IOMMU(折中方案,推荐优先尝试 通用

⚠️ 建议 :生产环境优先尝试 iommu=pt(直通模式),既保留安全性又避免翻译开销;确认无需求后再考虑完全关闭。


二、操作前检查

bash 复制代码
# 1. 确认系统中有多个可回退的内核条目(防止改错后无法启动)
sudo grubby --info=ALL | grep -E "^(index|title|kernel)="

# 2. 查看当前正在运行的内核及其启动参数
uname -r
cat /proc/cmdline

# 3. 确认当前 IOMMU 状态(有 DMAR / AMD-Vi 输出即为开启)
sudo dmesg | grep -i -E "iommu|DMAR|AMD-Vi"

💡 安全原则 :操作前确保系统至少保留 2 个内核条目,万一新参数导致无法启动,可在 GRUB 菜单中选择旧内核进入系统后回滚。


三、使用 grubby 关闭 IOMMU(完整流程)

3.1 流程总览

#mermaid-svg-ZC3uvFPdNN6iwtIT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZC3uvFPdNN6iwtIT .error-icon{fill:#552222;}#mermaid-svg-ZC3uvFPdNN6iwtIT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZC3uvFPdNN6iwtIT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .marker.cross{stroke:#333333;}#mermaid-svg-ZC3uvFPdNN6iwtIT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZC3uvFPdNN6iwtIT p{margin:0;}#mermaid-svg-ZC3uvFPdNN6iwtIT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster-label text{fill:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster-label span{color:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster-label span p{background-color:transparent;}#mermaid-svg-ZC3uvFPdNN6iwtIT .label text,#mermaid-svg-ZC3uvFPdNN6iwtIT span{fill:#333;color:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .node rect,#mermaid-svg-ZC3uvFPdNN6iwtIT .node circle,#mermaid-svg-ZC3uvFPdNN6iwtIT .node ellipse,#mermaid-svg-ZC3uvFPdNN6iwtIT .node polygon,#mermaid-svg-ZC3uvFPdNN6iwtIT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .rough-node .label text,#mermaid-svg-ZC3uvFPdNN6iwtIT .node .label text,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape .label,#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZC3uvFPdNN6iwtIT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .rough-node .label,#mermaid-svg-ZC3uvFPdNN6iwtIT .node .label,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape .label,#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape .label{text-align:center;}#mermaid-svg-ZC3uvFPdNN6iwtIT .node.clickable{cursor:pointer;}#mermaid-svg-ZC3uvFPdNN6iwtIT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .arrowheadPath{fill:#333333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZC3uvFPdNN6iwtIT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZC3uvFPdNN6iwtIT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster text{fill:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster span{color:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZC3uvFPdNN6iwtIT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape p,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape .label rect,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZC3uvFPdNN6iwtIT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZC3uvFPdNN6iwtIT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZC3uvFPdNN6iwtIT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

开始
① 查看当前内核参数

cat /proc/cmdline
② 添加关闭 IOMMU 参数

grubby --update-kernel=ALL --args='...'
③ 验证参数已写入

grubby --info
④ 重启系统

reboot
⑤ 验证运行时生效

cat /proc/cmdline + dmesg
IOMMU 已关闭?
✅ 完成
检查是否漏改内核 /

GRUB 菜单选择错误

3.2 步骤详解

① 查看当前内核启动参数
bash 复制代码
# 方式一:查看运行时生效的参数
cat /proc/cmdline

# 方式二:查看当前内核条目的完整配置(args 行即启动参数)
sudo grubby --info /boot/vmlinuz-$(uname -r)

# 方式三:查看所有内核条目
sudo grubby --info=ALL
② 添加关闭 IOMMU 的参数
bash 复制代码
# Intel + AMD 平台参数同时写入(保留对应项即可,多余的参数无害)
sudo grubby --update-kernel=ALL --args="intel_iommu=off amd_iommu=off"

# 或者:彻底禁用 IOMMU 子系统
sudo grubby --update-kernel=ALL --args="iommu=off"

参数说明

  • --update-kernel=ALL ------ 修改所有已安装内核的条目,保证切换旧内核时参数依然生效;
  • --update-kernel=DEFAULT ------ 只修改默认启动的内核,适合临时调试;
  • --update-kernel=/boot/vmlinuz-<版本> ------ 精确修改指定内核
③ 验证参数已添加(重启前)
bash 复制代码
sudo grubby --info /boot/vmlinuz-$(uname -r) | grep args

输出示例(注意末尾已出现新参数):

复制代码
args="ro crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap rhgb quiet intel_iommu=off amd_iommu=off"
④ 重启系统
bash 复制代码
sudo reboot
⑤ 验证生效(重启后)
bash 复制代码
# 确认参数已进入运行时内核命令行
cat /proc/cmdline

# 确认 IOMMU 已被禁用:无 DMAR / AMD-Vi 初始化输出即为成功
sudo dmesg | grep -i -E "iommu|DMAR|AMD-Vi"

成功标志dmesg 中不再出现 DMAR: Host address width ...(Intel)或 AMD-Vi: ...(AMD)初始化日志。


四、grubby 常用操作速查表

操作 命令
查看默认内核索引 sudo grubby --default-index
查看默认内核路径 sudo grubby --default-kernel
查看所有内核条目 sudo grubby --info=ALL
查看指定内核条目 sudo grubby --info /boot/vmlinuz-<版本>
给所有内核加参数 sudo grubby --update-kernel=ALL --args="参数"
只给默认内核加参数 sudo grubby --update-kernel=DEFAULT --args="参数"
移除参数(回滚) sudo grubby --update-kernel=ALL --remove-args="参数"
设置默认启动内核 sudo grubby --set-default /boot/vmlinuz-<版本>

⚠️ --remove-args 必须与添加时的参数值完全一致 (包括 = 和值),否则无法匹配移除。


五、grubby vs 手动编辑配置对比

维度 grubby 手动编辑 /etc/default/grub + grub2-mkconfig
操作步骤 一条命令 编辑文件 + 重新生成配置 + 重启
UEFI/BIOS 路径差异 自动处理 需手动区分 grub.cfg 路径
粒度控制 可精确到单个内核 对所有内核统一生效
参数管理 分散在各内核条目中 集中在一处,可读性好
回滚 --remove-args 一键回滚 需再次编辑并重新生成
脚本化 / 自动化 ✅ 友好 ❌ 繁琐
误操作风险 较高(配置写错可能导致无法启动)

结论 :在 Rocky / RHEL 系列中,优先使用 grubby 修改内核参数;仅当需要统一管理大量参数或维护多发行版通用配置时,才考虑手动编辑方式。


六、故障排查(Troubleshooting)

现象 可能原因 解决方法
重启后参数未生效 只改了默认内核,实际启动的是其他内核 grubby --info=ALL 检查各条目,用 --update-kernel=ALL 统一修改
cat /proc/cmdline 有参数但 dmesg 仍有 DMAR 参数写法错误(如 iommu=0 确认使用 =off 而不是 =0/=false
--remove-args 移除失败 参数值与添加时不一致 先用 grubby --info 查看当前 args 的准确值
系统无法启动 参数与其他配置冲突 在 GRUB 菜单按 e 编辑启动项临时删除参数进入系统,再执行回滚命令

七、学习笔记与最佳实践

  1. 先小范围测试,再全量应用 :新参数先用 --update-kernel=DEFAULT 验证稳定,再 --update-kernel=ALL 铺开;
  2. 保留回退路径:操作前确认存在 ≥2 个内核条目;
  3. 优先折中方案 :IOMMU 问题优先尝试 iommu=pt,而非直接 iommu=off
  4. grubby 修改即时写入 BLS 文件/boot/loader/entries/*.conf),可查看该目录辅助排查;
  5. 自动化场景(Ansible / Kickstart 脚本)中优先使用 grubby,保证幂等性。

八、参考链接