硬件环境确认
首先要确定主板和 CPU 都支持虚拟化技术,在 BIOS 将 VT-d、VT-x 设置成 enable。
以 Intel 为例:
VT: Intel Virtualization Technology
VT-d: Intel VT for Directed I/O
软件环境配置
开启 iommu
关于 iomuu 和 vfio 参考这里:VFIO 简介
使用如下命令确认是否支持 iommu
cat /proc/cmdline | grep iommu
如果没有输出,说明不支持 iommu,需要手动开启。编辑/etc/default/grub,在 GRUB_CMDLINE_LINUX 中添加 intel_iommu=on 配置项:
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="intel_iommu=on crashkernel=auto rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
更新 grub,并重启设备:
grub2-mkconfig -o /boot/grub2/grub.cfg
shutdown -r now
重启以后如下确认是否正常:
#使用下面命令
dmesg | grep -i iommu
#如果输出类似下面的内容,说明正确
[ 0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-3.10.0-862.6.3.el7.x86_64 root=UUID=4e83b2b5-5ff1-4b1b-af0f-3f6a7f8275ea ro intel_iommu=on crashkernel=auto rhgb quiet
[ 0.000000] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-3.10.0-862.6.3.el7.x86_64 root=UUID=4e83b2b5-5ff1-4b1b-af0f-3f6a7f8275ea ro intel_iommu=on crashkernel=auto rhgb quiet
[ 0.000000] DMAR: IOMMU enabled
[ 0.257808] DMAR-IR: IOAPIC id 3 under DRHD base 0xfbffc000 IOMMU 0
[ 0.257810] DMAR-IR: IOAPIC id 1 under DRHD base 0xd7ffc000 IOMMU 1
[ 0.257812] DMAR-IR: IOAPIC id 2 under DRHD base 0xd7ffc000 IOMMU 1
确认虚拟化支持
egrep -c '(vmx|svm)' /proc/cpuinfo
如果输入非 0,则说明支持
配置 vfio
检查当前显卡设备信息
lspci -nn
......
02:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP102 [GeForce GTX 1080 Ti] [10de:1b06] (rev a1)
02:00.1 Audio device [0403]: NVIDIA Corporation GP102 HDMI Audio Controller [10de:10ef] (rev a1)
03:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP102 [GeForce GTX 1080 Ti] [10de:1b06] (rev a1)
03:00.1 Audio device [0403]: NVIDIA Corporation GP102 HDMI Audio Controller [10de:10ef] (rev a1)
05:00.0 PCI bridge [0604]: ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge [1a03:1150] (rev 03)
06:00.0 VGA compatible controller [0300]: ASPEED Technology, Inc. ASPEED Graphics Family [1a03:2000] (rev 30)
可以看到,其实我的这台设备上有三个 vga 设备,两个 1080Ti,一个 ASPEED(这是服务器经常见到的集成显卡),1080Ti 显卡同时带了声卡
确认设备使用的驱动
lspci -vv -s 02:00.0 | grep driver
Kernel driver in use: nvidia
lspci -vv -s 02:00.1 | grep driver
Kernel driver in use: snd_hda_intel
lspci -vv -s 03:00.0 | grep driver
Kernel driver in use: nvidia
lspci -vv -s 03:00.1 | grep driver
Kernel driver in use: snd_hda_intel
lspci -vv -s 06:00.0 | grep driver
Kernel driver in use: ast
可以看到,两块 N 卡使用的驱动为 nvidia(显卡驱动)和 snd_hda_intel(声卡驱动),ASPEED 使用的是 ast 驱动
配置 vfio
为了保证设备不被宿主机使用,我们建议将上面查到的两个驱动禁用,编辑/etc/modprobe.d/blacklist.conf,添加如下配置(似乎并不需要此步骤):
blacklist nvidia
blacklist snd_hda_intel
配置加载 vfio-pci 模块,编辑/etc/modules-load.d/vfio-pci.conf,添加如下内容:
vfio-pci
配置使用 vfio 驱动的设备(这里的设备就是上面我们查到的设备的)编辑/etc/modprobe.d/vfio.conf,添加如下配置:
# GTX 1080Ti and its audio controller
options vfio-pci ids=10de:1b06,10de:10ef
重新生成内核
重新生成内核文件之前,我们先备份已有的:
mv /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r)-nouveau.img
重新生成:
dracut /boot/initramfs-$(uname -r).img $(uname -r)
重启设备
shutdown -r now
验证 vfio 是否生效
查看启动信息,确认 vfio 模块是否加载:
dmesg | grep -i vfio
[ 6.755346] VFIO - User Level meta-driver version: 0.3
[ 6.803197] vfio_pci: add [10de:1b06[ffff:ffff]] class 0x000000/00000000
[ 6.803306] vfio_pci: add [10de:10ef[ffff:ffff]] class 0x000000/00000000
查看配置以后,显卡使用的驱动:
lspci -nnk -d 10de:1b06
02:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP102 [GeForce GTX 1080 Ti] [10de:1b06] (rev a1)
Subsystem: ZOTAC International (MCO) Ltd. Device [19da:1470]
Kernel driver in use: vfio-pci
Kernel modules: nouveau, nvidia_drm, nvidia
03:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP102 [GeForce GTX 1080 Ti] [10de:1b06] (rev a1)
Subsystem: ZOTAC International (MCO) Ltd. Device [19da:1470]
Kernel driver in use: vfio-pci
Kernel modules: nouveau, nvidia_drm, nvidia
从 Kernel driver in use 的结果可以看出,vfio 已经加载成功。
配置虚拟机使用宿主机的 GPU
配置之前,我们首先需要查看 pci 设备的 pci 标识,virsh nodedev-list 可以列出宿主机设备的所有 pci 设备的标识,结果如下:
virsh nodedev-list | grep pci | grep 03
pci_0000_00_03_0
pci_0000_03_00_0
pci_0000_03_00_1
查看 pci_0000_03_00_0 设备的详细信息:
#使用下面的命令查看
virsh nodedev-dumpxml pci_0000_03_00_0
#输出结果为如下
<device>
<name>pci_0000_03_00_0</name>
<path>/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0</path>
<parent>pci_0000_00_03_0</parent>
<driver>
<name>vfio-pci</name>
</driver>
<capability type='pci'>
<domain>0</domain>
<bus>3</bus>
<slot>0</slot>
<function>0</function>
<product id='0x1b06'>GP102 [GeForce GTX 1080 Ti]</product>
<vendor id='0x10de'>NVIDIA Corporation</vendor>
<iommuGroup number='47'>
<address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
<address domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
</iommuGroup>
<numa node='0'/>
<pci-express>
<link validity='cap' port='0' speed='8' width='16'/>
<link validity='sta' speed='8' width='16'/>
</pci-express>
</capability>
</device>
从结果中,我们可以看到,该设备在宿主机中的硬件信息为:
<iommuGroup number='47'>
<address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
<address domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
</iommuGroup>
编辑虚拟机配置文件(virsh edit xxxx),在 devices 代码块中增加如下内容:
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x06' slot='0x00' function='0x1'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</hostdev>
重启虚拟机:
virsh destroy xxx;virsh start xxx
进入系统以后,可以使用 lspci 查看虚拟机的 pci 设备,会发现设备已经在虚拟机中显示
可能问题解决
ERROR CODE 43(尚未验证)
#编辑VM XML
virsh edit win
#修改第一行
<domain type='kvm'>
#为
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
#找到<features>节点,添加内容
<features>
...
<kvm>
<hidden state='on'/>
</kvm>
...
</features>
#找到</device>节点,在device后添加内容
<qemu:commandline>
<qemu:arg value='-cpu'/>
<qemu:arg value='host,hv_time,kvm=off,hv_vendor_id=null'/>
</qemu:commandline>
#重启VM
virsh destroy win
virsh start win
参考:GPU PassThrough in KVM
参考:kvm 显卡透传(centos)
参考:centos 7.3 下为虚拟机透传 GPU.md