Kvm qemu显卡直通部署以及性能调优
参考¶
中文: https://wiki.archlinuxcn.org/wiki/PCI_passthrough_via_OVMF
英文比较全: https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#
https://space.bilibili.com/589560036
搭建教程: https://gitlab.com/liucreator/LEDs-single-gpu-passthrough
去虚拟化: https://github.com/zhaodice/qemu-anti-detection
去虚拟化: https://ivonblog.com/posts/qemu-kvm-bypass-easy-anti-cheat/
cpu隔离: https://github.com/lennard0711/vfio?tab=readme-ov-file#cpu-isolation
安装qemu¶
前置需要先安装ninga
git clone https://gitlab.com/qemu-project/qemu/ -b v8.2.0
cd qemu
# 对源码打过检测补丁
git apply qemu8.2.0.patch
# 创建编译的目录
mkdir qemu_build
cd qemu_build
# 设置编译条件, 安装到/usr/local 目录下
../qemu/configure --target-list=x86_64-softmmu,x86_64-linux-user --prefix=/usr/local
make -j $(nproc)
# 由于安装到/usr/local 目录下, 所以这里需要加sudo
sudo make install
# 如果需要卸载, 可以执行
sudo make uninstall
启用iommu¶
查询是否开启¶
我amd 默认启用了 输入以下命令, 找找有没有amd_IOMMU:Detected
获取组id¶
运行
iommuamd.sh
这个脚本, 找到显卡相关的id, 然后复制下来, 比如我的如下, 分别是1002:73ff
显卡的显示设备和1002:ab28
显卡中的音频设备
OMMU group 18
09:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 23 [Radeon RX 6600/6600 XT/6600M] [1002:73ff] (rev c1)
Driver: amdgpu
IOMMU group 19
09:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:ab28]
Driver: snd_hda_intel
添加vfio到内核模块¶
编辑
/etc/modprobe.d/vfio.conf
文件, 添加以下内容, 记得把自己的id替换掉
options vfio-pci ids=1002:73ff,1002:ab28
options vfio-pci disable_idle_d3=1
options vfio-pci disable_vga=1
安装所需要软件¶
# 连接器, 用于管理kvm
sudo pacman -S libvirt
# edk2-ovmf 提供了uefi引导
sudo pacman -S edk2-ovmf
# 提供了以一个qemu的图形化管理界面
sudo pacman -S virt-manager
# 网络相关
sudo pacman -S dnsmasq ebtables iptables bridge-utils
开机启用服务¶
启用Libvirt¶
启用虚拟网络¶
安装一个win10虚拟机¶
按照正常的步骤, 先安装一个windows系统, 并进入到桌面, 之后我们关掉, 继续进行下一步操作
注意点:
- 不能使用virtio的任何设备, 因为过检测补丁的原因, virtio也无法使用不读盘
- 所以全部使用stat设备
- 网络设备, 和磁盘设备, 记得随便输入几个字符作为串口
- 安装win10在引导界面, 可能选择指定的引导磁盘也没有效果, 这时候选择可以疯狂的按上下左右小键盘 可能就进去了
- 一切正常之后, 配置显卡直通前, 要关掉
virt-manager
,之后再进行下面的一切操作 - 直通前, 记得把本身的显卡视频vga或者qml这个设置为None或者直接删掉这个设备
配置Libvirt¶
hook¶
# 在Libirt里面创建一个hooks文件夹
sudo mkdir /etc/libvirt/hooks
# 把hooks文件夹中的所有文件复制到目录中
sudo cp hooks/* /etc/libvirt/hooks/
# 更改权限
sudo chmod +x /etc/libvirt/hooks/*
# 把两个脚本软链接到根目录的bin文件夹
sudo ln -s /etc/libvirt/hooks/vfio-startup.sh /bin/vfio-startup.sh
sudo ln -s /etc/libvirt/hooks/vfio-teardown.sh /bin/vfio-teardown.sh
防止休眠¶
编辑
/etc/systemd/system/libvirt-nosleep@.service
文件, 添加如下:[Unit] Description=Preventing sleep while libvirt domain "%i" is running [Service] Type=simple ExecStart=/usr/bin/systemd-inhibit --what=sleep --why="Libvirt domain \"%i\" is running" --who=%U --mode=block sleep infinity
更改权限
使其变成系统文件
配置Libvirt.conf¶
首先备份文件
编辑
/etc/libvirt/libvirtd.conf
文件, 找到如下两行,并把#
注释删掉 可以搜索unix_sock_group
和unix_sock_rw_perms
改完就像下面这样:
在该文件最后添加日志配置 如果以后qemu有启动失败, 可以在
sudo tail -f /var/log/libvirt/libvirtd.log
查看日志
配置qemu.conf¶
首先备份文件
编辑
/etc/libvirt/qemu.conf
, 可以搜索#user =
和#group =
, 改为如下:
添加组¶
重启电脑或者重启libvirt
配置显卡vbios¶
我这是a卡, 直接开搞就行, n卡自行搜索, 需要删掉vbios中的一些二进制数据才可以 注意
xxx.rom
文件最好放在~
目录下, 我好想踩过坑, 具体细节忘了
cp vbios文件.rom ~/
cd ~
# 修改权限
sudo chmod -R 660 vbios文件.rom
# 更改拥有者
sudo chown 你自己的用户名:users vbios文件.rom
打开
virt-manager
, 添加自己的pcie设备, 注意需要把上面的保存的那两个都添加进去, 然后在pcie设备管理面板, 右侧编辑xml文件, 在</source>
那一行的下面添加如下注意要修改自己的rom文件的路径:
开机吧¶
记得把本身的显卡视频vga或者qml这个设置为None或者直接删掉这个设备
虚拟机配置¶
在显卡直通完毕, 并且win10启动正常之后, 才可以进行下面的配置
设置cpu绑定¶
可以使用
lscpu -e
查看cpu信息emulatorpin
是设置虚拟机本身的程序习用的核心 下面是配置了一个6核心的虚拟机, 由于我关闭了超线程所以把物理核心的2,3,4,5,6,6
分配给了win10, 我们尽量不要是用物理核心0
隐藏cpu信息¶
cpu段落¶
在XML配置,找到
<cpu>
这一段mode
设为host-passthrough
, 并在段落中添加如下 我这里使用这个配置之后, cpu无论如何也无法有效调度显卡,,, 玩什么游戏fps只有十几的fps, 我没有用注意 上面十几fps是鲁大师测得,QAQ, 我实际进游戏, 是正常的!!!, 所以这个是可以加上去的
硬盘直通¶
就像我的截图, 记得配置好之后, 在引导选项里面也给这个磁盘打勾~
os段落¶
添加一行
features段落添加¶
有重复的就不用再次添加了
<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"/> <reset state="on"/> <frequencies state="on"/> <vendor_id state="on" value="random"/> <reenlightenment state="on"/> <tlbflush state="on"/> <ipi state="on"/> <evmcs state="off"/> </hyperv> <kvm> <hidden state="on"/> </kvm> <vmport state="off"/> <smm state="on"/> <ioapic driver="kvm"/>
屏蔽amdgpu内核模块¶
如果帧率过低需要, 可能是影响到了, 需要下面的方式关掉, 选择自己的设备, 按需复制
修改/etc/modprobe.d/blacklist.conf
#直通 AMD 显卡,请使用下面命令
blacklist radeon
blacklist amdgpu
#直通 Nvidia 显卡,请使用下面命令
blacklist nouveau
blacklist nvidia
blacklist nvidiafb
#直通 Intel 核显,请使用下面命令
blacklist snd_hda_intel
blacklist snd_hda_codec_hdmi
blacklist i915options
对cpu进行隔离¶
https://github.com/lennard0711/vfio?tab=readme-ov-file#cpu-isolation
性能调优¶
- windows内电源管理使用卓越性能
- 关闭smt超线程(这个玩游戏也没什么用), 关掉比较容易更好的配置vcpu
- 设置cpu pin
- 如果鼠标能设置回报率, 别设置那么高导致频繁发生中断
- bios关掉ftpm
- bios关掉cppc, 我没搞
- 关掉高精度计时器 我linux默认用的tsc, win上的我没搞, 记住linux win 都可以关都需要关, ,https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Host_clocksource_is_HPET_rather_than_TSC
- 将amdgpu内核模块屏蔽上面有记录怎么屏蔽, https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Too-low_frequency_limit_for_AMD_GPU_passed-through_to_virtual_machine
参考配置¶
<domain type="kvm">
<name>win10</name>
<uuid>5a534ed8-d2ea-4a2e-8c8c-d6fd9cf435de</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://microsoft.com/win/10"/>
</libosinfo:libosinfo>
</metadata>
<memory unit="KiB">12194304</memory>
<currentMemory unit="KiB">12194304</currentMemory>
<vcpu placement="static">7</vcpu>
<cputune>
<vcpupin vcpu="0" cpuset="1"/>
<vcpupin vcpu="1" cpuset="2"/>
<vcpupin vcpu="2" cpuset="3"/>
<vcpupin vcpu="3" cpuset="4"/>
<vcpupin vcpu="4" cpuset="5"/>
<vcpupin vcpu="5" cpuset="6"/>
<vcpupin vcpu="6" cpuset="7"/>
<emulatorpin cpuset="0"/>
</cputune>
<os firmware="efi">
<type arch="x86_64" machine="pc-q35-8.2">hvm</type>
<firmware>
<feature enabled="no" name="enrolled-keys"/>
<feature enabled="no" name="secure-boot"/>
</firmware>
<loader readonly="yes" type="pflash">/usr/share/edk2/x64/OVMF_CODE.fd</loader>
<nvram template="/usr/share/edk2/x64/OVMF_VARS.fd">/var/lib/libvirt/qemu/nvram/win10_VARS.fd</nvram>
<bootmenu enable="yes"/>
<smbios mode="host"/>
</os>
<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"/>
<reset state="on"/>
<frequencies state="on"/>
<vendor_id state="on" value="random"/>
<reenlightenment state="on"/>
<tlbflush state="on"/>
<ipi state="on"/>
<evmcs state="off"/>
</hyperv>
<kvm>
<hidden state="on"/>
</kvm>
<vmport state="off"/>
<smm state="on"/>
<ioapic driver="kvm"/>
</features>
<cpu mode="host-passthrough" check="none" migratable="on">
<topology sockets="1" dies="1" cores="7" threads="1"/>
<feature policy="disable" name="hypervisor"/>
</cpu>
<clock offset="localtime">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" tickpolicy="delay"/>
<timer name="hpet" present="no"/>
<timer name="hypervclock" present="yes"/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled="no"/>
<suspend-to-disk enabled="no"/>
</pm>
</domain>
上面是关闭smt超线程的, 下面是没有关闭超线程的配置, 只有cpupin不同
<domain type="kvm">
<name>win10</name>
<uuid>5a534ed8-d2ea-4a2e-8c8c-d6fd9cf435de</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://microsoft.com/win/10"/>
</libosinfo:libosinfo>
</metadata>
<memory unit="KiB">12194304</memory>
<currentMemory unit="KiB">12194304</currentMemory>
<vcpu placement="static">12</vcpu>
<cputune>
<vcpupin vcpu="0" cpuset="2"/>
<vcpupin vcpu="2" cpuset="3"/>
<vcpupin vcpu="4" cpuset="4"/>
<vcpupin vcpu="6" cpuset="5"/>
<vcpupin vcpu="8" cpuset="6"/>
<vcpupin vcpu="10" cpuset="7"/>
<vcpupin vcpu="1" cpuset="10"/>
<vcpupin vcpu="3" cpuset="11"/>
<vcpupin vcpu="5" cpuset="12"/>
<vcpupin vcpu="7" cpuset="13"/>
<vcpupin vcpu="9" cpuset="14"/>
<vcpupin vcpu="11" cpuset="15"/>
<emulatorpin cpuset="0,1,8,9"/>
</cputune>
<os firmware="efi">
<type arch="x86_64" machine="pc-q35-8.2">hvm</type>
<firmware>
<feature enabled="no" name="enrolled-keys"/>
<feature enabled="no" name="secure-boot"/>
</firmware>
<loader readonly="yes" type="pflash">/usr/share/edk2/x64/OVMF_CODE.fd</loader>
<nvram template="/usr/share/edk2/x64/OVMF_VARS.fd">/var/lib/libvirt/qemu/nvram/win10_VARS.fd</nvram>
<bootmenu enable="yes"/>
<smbios mode="host"/>
</os>
<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"/>
<reset state="on"/>
<frequencies state="on"/>
<vendor_id state="on" value="random"/>
<reenlightenment state="on"/>
<tlbflush state="on"/>
<ipi state="on"/>
<evmcs state="off"/>
</hyperv>
<kvm>
<hidden state="on"/>
</kvm>
<vmport state="off"/>
<smm state="on"/>
<ioapic driver="kvm"/>
</features>
<cpu mode="host-passthrough" check="none" migratable="on">
<topology sockets="1" dies="1" cores="6" threads="2"/>
</cpu>
<clock offset="localtime">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" tickpolicy="delay"/>
<timer name="hpet" present="no"/>
<timer name="hypervclock" present="yes"/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled="no"/>
<suspend-to-disk enabled="no"/>
</pm>
</domain>