显卡直通方案
一、前期准备
安装所需要软件
1 | |
添加用户组
1 | |
其中user为自己的用户名
启用并设置虚拟机服务和虚拟网卡开机自启
1 | |
编辑qemu配置文件
编辑/etc/libvirt/qemu.conf
把user = “ “ 这行和group = “ “ 这行取消注释
在user = “ “ 中填入自己的用户名
在group = “ “ 中填入libvirt

重启libvirt服务
1 | |
二、创建一个非直通的虚拟机
安装系统
打开virt-manager新建虚拟机
选择win的iso,并手动选择对应的操作系统
内存看情况设置,但是建议不要超过宿主机物理内存的80%
cpu无须关注后续会再次设置
按需要设置镜像大小
注:不会直接占用空间
选择在安装前自定义配置
选择固件如图所示(在virt-manager中的一切操作需要手动点击apply确认)
手动设置cpu拓扑
一般情况下嵌套字都填1
核心数按需分配(不要超过物理核心数)
线程数应与物理cpu线程数相同
硬盘总线和网卡型号选择virtIO

添加硬件
选择储存
设备类型选择CDROM设备
选中下载的virtio-win驱动
接着添加tpm设备选择直通
编辑XML
在</features>的上方添加如下代码
1 | |
并且在cpu中插入如下代码,这可以避免后续loogking-glass的问题
1 | |

开始安装
一定要选择专业版方便后续操作
选择加载驱动
选择win11驱动
按正常流程安装windows
按SHIFT + F10召唤cmd并且输入
1 | |
来跳过联网验证
接下来继续按正常流程安装windows
不要设置密码
安装如下两个驱动,无须进行更改
三、正式开始直通
编译并安装IDD驱动
安装Visual Studio并安装使用C++的桌面开发 (MSVC)、通用Windwos平台开发 (Windows SDK)
接着点修改->单个组建->安装MSVC Spectre缓解库和WDK
在文章中找到WDK最新版本并下载安装
下载此项目用vs打开.sln后缀文件
打开IddSampleDriver中的Driver.cpp并按需编辑
在s_SampleResolutionList[]{}中添加自己所需的分辨率,例如{2560,1600}
接着在s_SampleVSyncList[]{}中添加自己所需的刷新率,例如240
继续在s_SampleDefaultModes[]{}中添加自己所需的分辨率和刷新率的组合,例如{ 2560, 1600, 240 }
执行以下命令获取显示器的edid备用
1 | |
接着找到s_SampleMonitors[]{}把里面的内容全部删去换成
1 | |
接着注释或删除#define EDID_LESS
项目->属性->c/c++ ->代码生成->运行库->多线程(/MT)->确定
生成->生成解决方案
打开构建目录找到IddSampleDriver.cer安装证书->本地计算机->将所有的证书都放入下列存储->浏览->受信任的根证书颁发机构
进入IddSampleDriver目录找到IddSampleDriver.inf文件并安装
接着返回上级目录
找到IddSampleApp.exe右键->属性->兼容性->以管理员身份允许此程序
来默认申请以管理员权限运行
键入win+R输入taskschd.msc
创建基本任务->给任务取个名->触发器:计算机启动时->操作:启动程序->启动程序:选择IddSampleApp->完成
然后找到这个任务->安全选项->选择不管用户是否登录都要运行->打开不存储密码,该任务只有本地计算机的访问权限->打开使用最高权限运行
配置looking-glass
编辑/etc/tmpfiles.d/10-looking-glass.conf文件加入
1 | |
user(uid)中填入用户的uid
接着编辑/etc/udev/rules.d/99-kvmfr.rules文件添加
1 | |
按照以下公式计算数据
1 | |
其中BPP为4表示SDR,8表示HDR
然后把这个数据向上取整到2的整数次幂
编辑/etc/modprobe.d/looking-glass.conf文件添加
1 | |
编辑/etc/modules-load.d/looking-glass.conf文件添加
1 | |
编辑/etc/libvirt/qemu.conf文件找到cgroup_device_acl 这行取消它所包括的注释加入/dev/kvmfr0。如图
如果存在AppArmor也同时创建/etc/apparmor.d/local/abstractions/libvirt-qemu并且加入
1 | |
编辑/etc/looking-glass-client.ini文件加入
1 | |
接着重构内核并重启
编辑XML
修改首行为
1 | |
再在倒数二行加入
1 | |
在</devices>内加入两行
1 | |
找到<memballoon model=”virtio”>将其改成<memballoon model=”none”/>
启动虚拟机
下载并安装looking-glass-host
键入win+R输入taskschd.msc
创建基本任务->给任务取个名->触发器:当前用户登录时->操作:启动程序->启动程序:选择C:\Program Files\Looking Glass (host)\looking-glass-host.exe->完成
然后找到这个任务->安全选项->打开使用最高权限运行
接着关闭windows自动休眠
然后把显卡设置成none
编辑grub
编辑grub配置文件/etc/default/grub添加启动参数
1 | |
如果在直通时出现整个iommu组退回宿主机的问题(之后简称问题1)
可以进一步添加以下内核参数(需要包含了ACS补丁的内核)
1 | |
并更新配置文件并且重启
1 | |
进行检验,执行
1 | |
如果出现输出结果则说明成功
查询iommu分组
运行以下脚本
1 | |
找到需要直通显卡的iommu分组,记下分组中所有硬件对应的id备用
如图我要直通的显卡是3060,它处于iommu16分组,那么我需要记下的id为10de:2520和10de:228e(如果出现问题1,则只需要记下显卡所对应的id,不需要直通整个iommu组)
接着编辑/etc/modprobe.d/vfio.conf
在其中以如下格式添加记下的所有id
1 | |
配置hooks
随意找个目录执行
1 | |
进入目录再进入hooks文件夹
编辑vfio-startup把里面内容换成
1 | |
注意:此脚本一旦执行就会杀死所有占用n卡的程序
接着编辑vfio-teardown把里面内容换成
1 | |
sleep的时间自行测试
pci_0000_A1_B1_C1填iommu分组与显卡同组的所有ID
重启libvirt服务
1 | |
修改qemu
把$OBJECT == “”里面替换成自己的虚拟机名
之后运行install_hooks.sh
打开virt-manager -> 添加硬件 -> PCI主机设备
添加需要直通的显卡和显卡同iommu组的其他设备
启动虚拟机
再次打开virt-manager可以看到虚拟机已经启动
接着为虚拟机安装驱动
大功告成!
你在重启后可以使用looking-glass-client来访问虚拟机
四、参考教程
https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF
https://looking-glass.io/
https://gitlab.com/risingprismtv/single-gpu-passthrough
https://www.bilibili.com/video/BV1Er4y1i7pq/?spm_id_from=333.337.search-card.all.click&vd_source=8090ef867fc52ca54eca33de8f1ff58f
https://lostattractor.net/archives/nixos-gpu-vfio-passthrough#%E4%BD%BF%E7%94%A8
https://gitlab.com/liucreator/LEDs-single-gpu-passthrough
https://lantian.pub/article/modify-computer/laptop-muxed-nvidia-passthrough.lantian/
https://blog.rachelt.one/articles/fake-display-for-moonlight/