在Linux系统中,IOMMU(Input/Output Memory Management Unit)是一种硬件设备,用于管理输入输出设备的内存映射以及访问权限。IOMMU可以提高系统的安全性和性能,通过对DMA(直接内存访问,即设备与内存直接通信,而无需经过CPU)请求进行隔离和管理,防止恶意设备访问系统内存并提高内存使用效率。
在IOMMU的实现中,一个IOMMU设备通常会管理多个I/O设备,而这些IO设备可能需要共享同一块物理内存。为了有效管理这些IO设备,Linux内核使用IOMMU Group进行设备的分组和隔离。
IOMMU Group是一组物理设备和其对应的DMA地址空间,一般来说,IOMMU Group中的所有设备共享相同的DMA地址空间,并受到相同的IOMMU保护,如果一个设备与多个IOMMU GROUP关联,或者一个IOMMU Group中包含多个设备,可能需要重新配置系统以确保正确的IOMMU保护,在IOMMU GROUP中,IO设备可以访问统一块物理内存。但不能访问其它IOMMU GROUP的内存,这样可以保护系统的安全性。
1. 虚拟化工具的版本需求
libvirtd 和 qemu 需要新的版本,太旧不支持iommu的设置。
查看 virsh 版本:
virsh version
需求如下:
- libvirt: >= 4.5.0
- QEMU: >= 4.5.0
- hypervision: >= QEMU 2.12.0
2. 物理机配置开启嵌套虚拟化
查看是否开启嵌套虚拟化
cat /sys/module/kvm_intel/parameters/nested
指令输出:
N # 没有开启嵌套虚拟化
添加 kvm-nested.conf
vi /etc/modprobe.d/kvm-nested.conf
文件内容如下:
options kvm-intel nested=1
options kvm-intel enable_shadow_vmcs=1
options kvm-intel enable_apicv=1
options kvm-intel ept=1
重新插入 kvm 驱动
# remove rather than insert a module.
modprobe -r kvm_intel
# Insert all module names on the command line.
modprobe -a kvm_intel
查看是否开启嵌套虚拟化
cat /sys/module/kvm_intel/parameters/nested
指令输出:
Y # 有开启嵌套虚拟化
3. 物理机开启vt-d并配置开启iommu
添加内核启动参数,往/etc/grub/grub.cfg文件中添加intel_iommu=on iommu=pt
然后重启物理机。
reboot
使用cat /proc/cmdline查看配置是否生效
cat /proc/cmdline
指令输出如下结果(出现intel_iommu=on iommu=pt 配置)即为生效成功:
4. 创建虚拟机并修改虚拟机的xml文件配置
注意:
- 在创建虚拟机的时候chipset需要选择为Q35。
- 生效虚机配置前,需要先关机。
导出虚机配置:
# 在宿主机上导出虚拟机的配置文件
virsh dumpxml 虚机名称 > xxx.xml
# 执行dumpxml操作前可以使用virsh list --all命令查看虚拟机列表
# xxx.xml为导出后的文件,可以随意命名,但是后缀需要是.xml
修改虚拟机的xml文件,按照下述内容修改相关参数进行配置:
<!-- =================================================================== -->
<!--os/type.machine='pc-q35-7.2'-->
<os>
<type arch='x86_64' machine='pc-q35-7.2'>hvm</type>
<boot dev='hd'/>
</os>
<!-- =================================================================== -->
<!--features/ioapic.driver='qemu'-->
<features>
<ioapic driver='qemu'/>
</features>
<!-- =================================================================== -->
<!--cpu.mode='host-passthrough'-->
<cpu mode='host-passthrough' check='none' migratable='on'>
<feature policy='require' name='vmx'/>
</cpu>
<!-- =================================================================== -->
<devices>
<!-- iommu -->
<iommu model='intel'>
<driver intremap='on' caching_mode='on' iotlb='on'/>
</iommu>
</devices>
生效虚机配置:
# 从xml配置文件定义虚拟机生效配置
virsh define xxx.xml
5. 启动虚拟机配置开启iommu,然后重启检查iommu_groups是否开启
添加内核启动参数,往grub.cfg文件中添加intel_iommu=on iommu=pt
然后重启虚拟机。
reboot
重启虚拟机后,使用dmesg|grep -i iommu命令检查iommu_groups是否开启以及分组情况
也可以执行下述脚本查看pci和iommu_group分组详细信息:
root@debian-deb:~# cat iommu_group.sh
#!/bin/bash
for d in $(find /sys/kernel/iommu_groups -type l |sort -n -k5 -t/); do
n=${d#*/iommu_groups/*}; n=${n%%/*}
printf 'IOMMU GROUS %s ' "$n"
lspci -nns "${d##*/}"
done;
可以看到当前虚拟机已经开启iommu_groups,且自动配置了iommu_group分离。