虚拟机对显卡的支持一向并不是非常完美,比如 VirtualBox 虚拟机设置,显存部分一般最多拉到 128MB,是虚拟的,无法用物理机的显卡,哪怕这张显卡是闲置的
VMware 很久没用了,据我所知,也是不支持物理显卡(这里不考虑企业级软件)
而 KVM + QEMU 却可以通过 PCI passthrough 的方式将物理机的显卡直通给虚拟机用,非常厉害
前提准备
下面所有操作都是基于 Arch Linux,其他系统未测试,未来也不会测试
因为本质上还是虚拟机,所以要确保 BIOS 设置好了开启虚拟化
接着就是要开启 IOMMU,这个也要硬件的支持
- 如果是 Intel 的 CPU,修改内核参数
intel_iommu=on iommu=pt
- 如果是 AMD 的 CPU,默认就有一些设置,因此只需加
iommu=pt
(Yes?)
修改完内核参数要重新跑 sudo grub-mkconfig -o /boot/grub/grub.cfg
,重启生效
然后就是要拿到硬件的一些 id,这些 id 将会作为硬件的唯一标识在直通的过程中被使用到(这个脚本可以在 Arch Wiki 找到)
1 |
|
PCI passthrough 的处理是通过将显卡从你的宿主机隔离出来,其中又有多种处理方式
多显卡
如果你的电脑是多显卡,并且 Linux 系统没有独显需求,就可以使用这种方法
这种情况多数出现在笔记本,当然台式机也有,只是很多 CPU 型号都把核显砍了
如果有独显,CPU 里又已经有核显了,厂商会进行一些优化,平时用核显,但是当有专业需求的时候,走的就是独显;自己也可以通过 Optimus 或者 Bumblebee 来进行控制
我的笔记本之前只拿来写写 Java,就是用 nvidia-xrun 把整个独显都禁用掉,neofetch 也查不到,相当于不通电,这样来稍微省点电池消耗
如果宿主机跑的是 Linux,虚拟机跑的是 Windows,那就可以通过这种方式来进行设置
这种方法可以实现物理机和虚拟机同时存在,物理机显示用核显,因为都不用独显了,所以可以在物理机系统启动时就把显卡隔离出来,这个就需要修改 Linux 内核参数
将上面准备阶段拿到的 id,写进内核参数 vfio-pci.ids=xxx
,也要重新生成 grub 配置,也是重启生效
接着修改 /etc/mkinitcpio.conf
1 | MODULES=(... vfio_pci vfio vfio_iommu_type1 vfio_virqfd ...) |
修改完这个后也要重新生成 sudo mkinitcpio -p linux
,同样是重启生效
然后多显卡的前提配置就完成了
单显卡
单显卡有点特殊,物理机输出到显示器也要显卡,所以不能提前将其隔离
QEMU 提供了一个 hook
功能,当虚拟机执行到某个阶段时,可以执行一些特定的脚本
因此思路就有了
- 系统开机,正常使用显卡显示
- 开启虚拟机时,执行 hook,释放掉占用的资源,将显卡在物理机上隔离出来
- 关闭虚拟机时,执行 hook,重新把显卡模块启用,开启 DM
首先 id 要写在一个单独配置文件 /etc/modprobe.d/vfio.conf
里,这个起到的作用就是可以动态进行模块的加载
1 | options vfio-pci ids=xxx |
接着要准备好 hook 脚本,路径是 /etc/libvirt/hooks/qemu
1 |
|
这里的 win10
是虚拟机的名称
开启虚拟机的监听脚本 prepare.sh
1 | set -x |
其中的 pci_0000_xxx
是在查 id 的阶段拿到的,比如输出
1 | 06:00.0 VGA compatible controller [0300]: NVIDIA Corporation GA104 [GeForce RTX 3060 Ti] [10de:2486] (rev a1) |
则 options vfio-pci ids=10de:2486
,virsh nodedev-detach pci_0000_06_00_0
关闭虚拟机的监听脚本 release.sh
,关闭其实就是一个反向的回滚操作
1 | set -x |
这些脚本需要在安装完系统后再设置,或者先换别的名字,不然安装的时候就会被执行,然后黑屏
这个就是单显卡的前提配置
系统安装及测试
多显卡进行系统安装时可以直接把显卡设置进去
单显卡则不可以,需要先安装系统,如果显卡设置进去,那物理机也要用,虚拟机也要用,就会卡住
平时 Windows 在系统安装完成后会自动在系统更新那里帮用户安装好显卡驱动,但是显卡直通这种方式最好是手动进行安装,Windows 不一定识别得出来,安装完驱动后,一切都和正常使用就没什么区别了