qemu显卡直通详细教程

虚拟机的3d性能,除了直通以外,都是模拟的,性能一般有好有坏,无论是virtualbox还是vmware,其实他们的3d性能,不论好与坏,都是模拟的驱动,
这点你可以通过windows的设备管理器看出来,与真实的差距其实还是不小的,2d的游戏可以玩,但是3d的游戏,就算是能玩,综合各方面的因素,体验也是上不去的,
所以,如果你想要一个强大的虚拟机,显卡直通是必然的,只有这一条路,只有显卡直通以后,3d性能变成原生的,你的虚拟机,才会没有短板,综合体验也上去

什么是显卡直通

显卡直通拿qemu为列,就是linux启动的时候,一张独显,不加载驱动,保留下来,然后虚拟机启动以后直接使用,到时候虚拟机的显卡驱动,直接就是对应显卡型号
的原生驱动

显卡直通需要具备什么条件

显卡直通也分很多种,比如单显卡直通,双显卡直通,但是双显卡直通是最优的,一般是主机使用集显,虚拟机使用独显(反过来可以吗,我没试过,也可能因为技术原因根本就没法反过来),以我自身为例,双显卡,双显示器

  1. cpu 9600k,带集显(一般bios有独显的时候,会默认屏蔽集显,需要把集显调成可用,这点需要注意)
  2. amd的rx560显卡
  3. 最好有两个显示器,一个集显插口用,一个独显插口用,(注意,如果是4k显示器,集显需要用dp接口(hdmi低版本不支持4k60hz),如果没有两个显示器,到时候回流过来,也麻烦,我就没用这种)

现在我就有了两张显卡,到时候,我会linux用集显,然后windows的虚拟机使用独显

显卡直通以后,会带来什么新问题

  1. 显卡直通以后,你的linux主机,不能用另外一块显示器
  2. 你的虚拟机的声音,qemu的spice驱动就没法使用,你的虚拟机的声音需要回流过来
  3. 你的虚拟机,此时,qemu的spice驱动,也不会帮你同步鼠标和键盘,这个时候,你需要使用别的方案来操作另一台虚拟机

不过,这些问题都不是事,接下来,都有完美的方案可以解决

qemu显卡直通步骤

这里,我会以我的硬件为例,一步步的讲解我的直通步骤,参考资料是arch PCI passthrough via OVMF,
arch的资料都写的非常详细,而且细节也照顾的很到位

更新你的系统,确保你的内核更新

1
2
# manjaro 更新系统
sudo pacman -Syu

开启IOMMU

我是intel的cpu,需要手动开启,amd的cpu,默认开启

1
2
3
4
# /etc/default/grub
# For Intel CPUs (VT-d) set intel_iommu=on. Since the kernel config option CONFIG_INTEL_IOMMU_DEFAULT_ON is not set in linux.
# iommu=pt You should also append the iommu=pt parameter. This will prevent Linux from touching devices which cannot be passed through.
GRUB_CMDLINE_LINUX_DEFAULT="... intel_iommu=on iommu=pt ..."

查找显卡所在的iommu group

1
2
3
4
5
6
7
8
#!/bin/bash
shopt -s nullglob
for g in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do
echo "IOMMU Group ${g##*/}:"
for d in $g/devices/*; do
echo -e "\t$(lspci -nns ${d##*/})"
done;
done;

部分输出如下,可以看到我的显在group 1

1
2
3
4
5
6
7
8
9
10
IOMMU Group 0:
00:00.0 Host bridge [0600]: Intel Corporation 8th Gen Core Processor Host Bridge/DRAM Registers [8086:3ec2] (rev 0a)
IOMMU Group 1:
00:01.0 PCI bridge [0604]: Intel Corporation 6th-10th Gen Core Processor PCIe Controller (x16) [8086:1901] (rev 0a)
01:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] [1002:67ef] (rev cf)
01:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] [1002:aae0]
IOMMU Group 2:
00:02.0 VGA compatible controller [0300]: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630] [8086:3e98]
IOMMU Group 3:
00:08.0 System peripheral [0880]: Intel Corporation Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model [8086:1911]

隔离GPU

绑定设备id

1
2
3
# /etc/modprobe.d/kvm.conf
# 防止Windows 10 1803蓝屏
options kvm ignore_msrs=1
1
2
3
# /etc/modprobe.d/vfio.conf
# 按隔离整组组设备
options vfio-pci ids=8086:1901,1002:67ef,1002:aae0

注意一下事项

  1. 绑定都是需要绑定整个group所有设备

提前加载驱动

1
2
3
4
# /etc/mkinitcpio.conf
MODULES=(... vfio_pci vfio vfio_iommu_type1 vfio_virqfd ...)
# manjaro hooks 里面已经有了 modconf,所以,不需要再添加了
HOOKS=(... modconf ...)

重新构建,让配置生效

1
sudo mkinitcpio -P

重启,验证配置

1
lspci -nnk

输出部分如下,可以看到,现在驱动都使用vfio-pci,表明成功,至此,已经提前做好了所有的准备

1
2
3
4
5
6
7
8
01:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] [1002:67ef] (rev cf)
Subsystem: Hightech Information System Ltd. Device [1787:3000]
Kernel driver in use: vfio-pci
Kernel modules: amdgpu
01:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] [1002:aae0]
Subsystem: Hightech Information System Ltd. Device [1787:aae0]
Kernel driver in use: vfio-pci
Kernel modules: snd_hda_intel

qemu设置PCI直通

amd gpu hyperv 检测

这里需要设置允许xml编辑

支持hyperv检测gpu,这里是一个优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<features>
<acpi/>
<apic/>
<hyperv mode="custom">
<relaxed state="on"/>
<vapic state="on"/>
<spinlocks state="on" retries="8191"/>
<vpindex state="on"/>
<runtime state="on"/>
<synic state="on"/>
<stimer state="on">
<direct state="on"/>
</stimer>
<reset state="on"/>
<vendor_id state="on" value="notavm"/> <!-- 就是这一句 -->
<frequencies state="on"/>
<reenlightenment state="on"/>
</hyperv>
<vmport state="off"/>
</features>

video qxl,添加PCIe

先使用模拟显卡

添加PCI设备,把整组加上,我的组有个PCIe Controller,不用加

安装驱动

windows一般会自动安装驱动,上面安装好驱动以后,另一个屏幕,接得独显接口这个显示器,就会亮,这个时候,就是独显驱动安装好了

video none启动

然后我们就可以去掉虚拟显卡

这个时候,启动之前,你需要至少给虚拟机添加一个usb鼠标,添加一个usb host device即可,这样才可以控制你的电脑,如果有密码的话,使用屏幕键盘即可,
这样整个独显直通就做好了,但是还有两个问题,需要解决,上面已经提到了

添加鼠标和键盘

不论你豪不豪,分别用两套鼠标和键盘都不是好的方案,以下有几种方案

  1. 硬件切换,如带kvm切换器的鼠标键盘,需要按一下,不好
  2. 现在有些蓝牙键盘和鼠标,也是支持多设备,但是人家是蓝牙的,我们这里模拟蓝牙设备就算了
  3. 最好的方案,应该是软件方案,代表作就是barrier(开源免费)和synergy(开始开源,后面收费了,但是你可以自己编译)

这里我们选择开源的barrier,只需要主机和虚拟机都装好,配好,然后,就可以直接一个鼠标划到另外一个屏幕了,非常方便,不用任何切换,而且比局域网还快的速度,没有任何延迟

可以看到,我的两个屏幕,主机的屏幕在左边,虚拟机的屏幕在右边,比如你玩游戏的时候,想把你的鼠标锁到虚拟机里面,按下scroll lock就好了,这样就能把他锁进去了,经过我这么长时间的体验,发现,
barrier鼠标没有任何延迟,文字复制粘贴没有任何问题,图片粘贴容易出问题,我把图片粘贴禁用了,这样就完全没问题了

虚拟机声音广播到主机

开源的广播声卡,可以把你虚拟机的声音广播到你的主机,效果非常棒,具体的原理就是虚拟机的声音,通过局域网(注意,此时,你的虚拟机必须使用桥接网卡模式),广播到你的主机linux,然后类似你主机linux的一个程序再放声音

Scream - Virtual network sound card for Microsoft Windows

这个项目,帮你编译scream,然后设置成开机启动,这样你虚拟机的声音都可以广播到主机了,同时你windows也安装好了scream,并且设置为scream为主声卡

Scream Helper

主机和虚拟机文件共享

linux的samba,就是专门解决linux和windows文件共享的问题的

我的设置如下,samba和windows共享的时候,还可以支持软连接,我的配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# /etc/samba/smb.conf
[global]
workgroup = workgroup
server string = manjaro
security = user
allow insecure wide links = yes
[share]
comment = share
path = /home/ss/share
public = yes
writable = yes
printable = no
follow symlinks = yes
wide links = yes

最后的效果如下

总结

通过各种设置,我们准备了显卡直通的条件,然后,虚拟机安装驱动以后,我们又把声音和鼠标键盘的问题,搞定了,总之,折腾吧
最后,如果遇到问题,可以参考这个资料,arch的资料写的非常详细,非常好arch PCI passthrough via OVMF,
这里我把链接再贴一次