kvm多显卡直通

  1. 主板bios打开虚拟化(有的老旧cpu不支持)
  2. 宿主机系统中启用iommu组
    打开/etc/default/grub,找到GRUB_CMDLINE_LINUX_DE FAULT,修改为下面内容
    1
    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_iommu=on"
    更新grub
    1
    2
    sudo grub-mkconfig -o /boot/grub/grub.cfg # Arch Linux
    sudo update-grub -u # Ubuntu
    重启电脑,检查iommu是否正确启用
    1
    dmesg | grep -i iommu
    如果你在输出中看到很多pci xxxx:xx:xx.x: Adding to iommu group xx,那么恭喜你,第一步完成了。
    系统中的所有设备只能按照iommu group为单位分配给宿主机或者虚拟机。因此如果你看到两个不相关的设备在一个group里,那也没招,你只能给这俩设备一起丢虚拟机里去。
    很可惜的是,Linux系统并不支持预留iommu group。
    iommu group是硬件实现上的分组。在Linux的实现中,只认得各个在总线上的硬件,并挨个挨个的启动起来。
    我们要做的就是阻止Linux内核在启动时初始化某些组里的硬件。
  3. 寻找需要预留的iommu组
    首先确认我们显卡所在的PCIE总线和产品型号:
    1
    lspci -nnv | grep -i nvidia
    我的电脑上输出如下:
    1
    2
    3
    4
    5
    6
    7
    01:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2203] (rev a1) (prog-if 00 [VGA controller])
    Kernel driver in use: nvidia
    Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia
    01:00.1 Audio device [0403]: NVIDIA Corporation GA102 High Definition Audio Controller [10de:1aef] (rev a1)
    05:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2203] (rev a1) (prog-if 00 [VGA controller])
    Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia
    05:00.1 Audio device [0403]: NVIDIA Corporation GA102 High Definition Audio Controller [10de:1aef] (rev a1)
    可以看到输出分成两部分,编号加设备描述。01:00.0和01:00.1是编号通过冒号 “:” 又分成了三部分,第一个部分是PCIe的 domain ID,第二个部分是 bus ID,第三个部分是 device id.function id。PCI设备的组织形式是一个树形,这表示一个domain可以包含多个bus,一个bus又包含了多个device,一个device又包含多个function。
    0300 是一个用来区分不同设备的编号,网络设备、存储设备、多媒体设备、显卡都有自己的编号。
    10de:2203 这是一个厂商特有的编号,10de是 Nvidia的编号(Vendor ID),Nvidia所有的设备都是使用这一编号,2203 表示这是一个3090Ti显卡。
    接下来我们需要找出我们的设备所在的iommu group:
    1
    sudo dmesg | grep iommu | grep 01:00.0
    输出如下:
    1
    2
    3
    [    0.536462] pci 0000:01:00.0: Adding to iommu group 17
    $ sudo dmesg | grep iommu | grep 05:00.0
    [ 0.536491] pci 0000:05:00.0: Adding to iommu group 20
    确认iommu group中的所有设备:
    1
    sudo dmesg | grep "iommu group 17"
    输出如下:
    1
    2
    [    0.536462] pci 0000:01:00.0: Adding to iommu group 17
    [ 0.536467] pci 0000:01:00.1: Adding to iommu group 17
  4. 屏蔽显卡
  • 型号屏蔽法:
    如果只有一张显卡,或者两张显卡的ID不同,可以直接用pci-stub或者vfio-pci的方法来屏蔽即可,修改/etc/default/grub:
    1
    2
    3
    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_iommu=on pci-stub.ids=10de:2203,10de:1aef"
    或者
    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_iommu=on vfio-pci.ids=10de:2203,10de:1aef"
    更新内核,并重启:
    1
    2
    sudo grub-mkconfig -o /boot/grub/grub.cfg # Arch Linux
    sudo update-grub -u # Ubuntu
    如果屏蔽成功,内核驱动就会显示如下:
    1
    lspci -nnv | grep -E "(^\S|Kernel driver in use)" | grep 01:00 -A 1
    1
    2
    3
    4
    01:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2203] (rev a1) (prog-if 00 [VGA controller])
    Kernel driver in use: vfio-pci
    01:00.1 Audio device [0403]: NVIDIA Corporation GA102 High Definition Audio Controller [10de:1aef] (rev a1)
    Kernel driver in use: vfio-pci
    否则下面还是驱动被nvidia接管的状态(其实nvidia-smi就能看了):
    1
    lspci -nnv | grep -E "(^\S|Kernel driver in use)" | grep 01:00 -A 1
    1
    2
    3
    4
    01:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2203] (rev a1) (prog-if 00 [VGA controller])
    Kernel driver in use: nvidia
    01:00.1 Audio device [0403]: NVIDIA Corporation GA102 High Definition Audio Controller [10de:1aef] (rev a1)
    Kernel driver in use: snd_hda_intel
  • 脚本屏蔽法
    当然如果两张显卡都是同一个型号,是不能用上面的方法屏蔽的。这个时候我们要为显卡指定驱动:
    1
    sudo vim /etc/initramfs-tools/scripts/init-top/vfio.sh
    脚本内容为:
    1
    2
    3
    4
    5
    6
    #!/bin/sh
    echo "vfio-pci" > /sys/bus/pci/devices/0000:01:00.0/driver_override
    echo "vfio-pci" > /sys/bus/pci/devices/0000:01:00.1/driver_override
    #echo "0000:01:00.0" > /sys/bus/pci/drivers/vfio-pci/bind # 这里我没有加这个绑定,有人加了这两句,但我注释了,因为本地找不到这个文件夹
    #echo "0000:01:00.1" > /sys/bus/pci/drivers/vfio-pci/bind # 需要modprobe -i vfio-pci之后才有这个文件夹,但不加仍然可用
    exit 0
    给脚本增加权限,否则无法执行:
    1
    sudo chmod 744 /etc/initramfs-tools/scripts/init-top/vfio.sh
    完成后刷新initramfs,这个命令会执行上面的脚本:
    1
    sudo update-initramfs -u -k all
    输出下面的结果,重启就可以正常屏蔽了。
    1
    2
    update-initramfs: Generating /boot/initrd.img-6.2.0-31-generic
    update-initramfs: Generating /boot/initrd.img-6.2.0-26-generic
    重启配置成功后按照上一节的命令就能看到显卡的驱动被vfio-pci接管了,nvidia-smi也能发现显卡已经无法识别了。
    如果想恢复显卡的挂载,就把脚本中的两行echo…注释掉,并刷新initramfs,重启机器即可。
  1. 打开kvm,加入该显卡即可

参考

https://blog.csdn.net/ahmclishihao/article/details/132679686