前排提醒
本文内容已有更新。最新最快直通方法可见我的Github Repo:cmd2001/build-edk2-gvtd
不用再折腾编译,直接点开下现成的就行!
(可能需要一定英文基础)
(过气的)正文
温馨提示:本教程有较强时效性
本文写于 2023年8月26日
软件版本为:Proxmox Virtual Environment 8.0.4
内核版本:Linux 6.2.16-6-pve
测试硬件:
ASRock Deskmini B660 + Intel 12900 es(QXQ3)/Intel 13900T es(Q0PV)
Gigabyte Z490I AORUS ULTRA + Intel 10900T es(QTB0)
写这篇教程,主要是国内折腾 核显直通 的玩家很多,但真正可用的教程却很少。很多教程只是说需要提前安装系统,无法看到 BIOS
界面,进入系统后可正常使用,但对其中的原理却没有任何讲述。或者单纯以有偿或免费的形式提供一个可用的 OVMF
固件,却也不讲解其中原理。而英文论坛对这方面的叙述却很明确。这里,我就来做一个总结者和搬运工,在提供教程的同时讲解一些最基本的原理。
本文所有使用的工具均为互联网可获得的开源项目/免费软件,以及厂商提供的闭源固件。
笔者承认付费定制提供者的劳动价值,本文也无意打扰你们的生意。只是为广大 DIYer 提供一个自己折腾的选择而已。
理论上本教程定制 OVMF
部分也适用于 AMD,但虚拟机配置可能需要做出一些修改。另外 AMD 核显存在 Reset Bug
可能会导致宿主机卡死,需要在 Windows
中加额外服务进行 Hook。由于笔者手中并没有 AMD 平台的核显主机,因此没有进行相关测试。(当然如果谁愿意给我捐一台那我自然很愿意折腾)
原理:UEFI 启动是怎样点亮显示器的
现在假设你的电脑有一张独显,你的显示器接在独显上,机器采用UEFI固件引导,那么从上电到点亮屏幕,你的机器发生了什么?
答:主板 UEFI
从显卡 VBIOS
中读取 GOP
固件,并利用 GOP
固件驱动独显,点亮屏幕。之后加载操作系统,显卡被驱动接管。
现在假设你的电脑有一张核显,你的显示器接在核显上,机器采用UEFI固件引导,那么从上电到点亮屏幕,你的机器发生了什么?
答:主板 UEFI
为核显初始化内存空间,读取内置的 GOP
固件,并利用 GOP
固件驱动核显,点亮屏幕。之后加载操作系统,显卡被驱动接管。
那么,如果现在是一台虚拟机呢?
答:主板 UEFI
不会为核显初始化内存空间,并尝试读取内置的 GOP
固件,但虚拟机的 UEFI
没有这种东西,加之没有初始化内存空间,所以必然点不亮屏幕。之后加载操作系统,显卡被驱动接管,操作系统的显卡驱动重新初始化内存空间并驱动屏幕。因此屏幕会在操作系统驱动加载后启动。
那么,如果我们想要虚拟机 UEFI
点亮屏幕呢?
答:为核显外挂 VBIOS
初始化内存空间,并为虚拟机的 UEFI
集成 GOP
固件。核显外挂 VBIOS
初始化内存空间,主板 UEFI
读取内置的 GOP
固件,并利用 GOP
固件驱动独显,点亮屏幕。之后加载操作系统,显卡被驱动接管。
为核显外挂 VBIOS
已是一个十分成熟的技术,因此我们的重点就是,并为虚拟机的 UEFI
集成 GOP
固件。
(以上描述只是一个方便小白理解的,非常简化的版本,本人学艺不精,如有错误请各位大神多多指教)
宿主机准备
首先你需要安装 PVE
(废话)
在 /etc/modules
中添加以下4行
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
运行 update-initramfs -u -k all
修改 /etc/default/grub
在 GRUB_CMDLINE_LINUX_DEFAULT
中添加
intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction
运行 update-grub
最后重启机器 reboot
虚拟机创建
直通 Intel 核显
所选的虚拟机类型 必须为 440fx
系统类型 必须为 Linux
(一定不要选 Windows
,否则装驱动后会冻屏死机,二者传递的 虚拟 CPU 参数不同)
固件类型 选择 UEFI
,这是安装 Windows 11
必备的
TPM
选择开启,安全启动随意
CPU
类型选 HOST
,否则装不上驱动
创建后进入 Options,打开 QEMU Guest Agent
和 Use Local Time for UTC
以获得更好体验
懒人办法
直接下载我编译的 FV
文件替换 PVE
自带版本,并进行测试。
首先测试 PVE
文件夹的版本,如果可用则直接使用。TPM/安全启动
等功能一切完美。
如果 PVE
文件夹的版本存在点不亮屏幕/花屏等问题,再测试 EDK2
文件夹的版本。本版本存在 TPM感叹号/安全启动不能启用
等小问题。
Intel 台式 6-10代/笔记本标压6-10代/笔记本低压6-9代 选择 SKYLAKE
版本,该版本采用的 GOP/VBT
固件提取自 Gigabyte Z490I AORUS ULTRA F22 BIOS(Jun 13, 2023)
。
Intel 台式11-14代/笔记本标压11-14代/笔记本低压10-14代 选择 TIGERLAKE
版本,该版本采用的 GOP/VBT
固件提取自 ASRock B660M-STX BIOS 12.02 (2022/12/23)
。
PVE
版本采用的 PVE
基础固件:pve-edk2-firmware/stable 3.20230228-4
下载链接:PVE_GVT
替换位置:/usr/share/pve-edk2-firmware/
如何确定你要替换的文件名?
sudo qm show $VM_ID --pretty | grep .fd
这里显示我要替换的文件为:/usr/share/pve-edk2-firmware//OVMF_CODE_4M.fd
除了 OVMF
固件外,我们还需要一个 vbios_gvt_uefi.rom
文件。将这个文件放到 /usr/share/kvm/
并修改虚拟机配置文件,添加以下两行:
hostpci0: 0000:00:02,legacy-igd=1,romfile=vbios_gvt_uefi.rom
这行用于添加核显,开启 legacy-igd
模式,加载 romfile
。
args: -set device.hostpci0.addr=02.0 -set device.hostpci0.x-igd-gms=1 -set device.hostpci0.x-igd-opregion=on
这行用于设置核显额外参数,包括把设备地址设置为02.0
,设置x-igd-gms
大小并启用x-igd-opregion
。
然后,把虚拟机的 显卡改为 None
,避免虚拟显卡和直通的核显争抢总线地址。
这里上一下我完整的虚拟机配置,可以参考一下
agent: 1
args: -set device.hostpci0.addr=02.0 -set device.hostpci0.x-igd-gms=6 -set device.hostpci0.x-igd-opregion=on
balloon: 0
bios: ovmf
cores: 8
cpu: host
efidisk0: local:200/vm-200-disk-0.qcow2,efitype=4m,pre-enrolled-keys=1,size=528K
hookscript: local:snippets/hooks-igpupt.pl
hostpci0: 0000:00:02,legacy-igd=1,romfile=vbios_gvt_uefi.rom
kvm: 1
localtime: 1
memory: 32768
meta: creation-qemu=8.0.2,ctime=1690013047
name: WinDE
net0: virtio=C2:38:CF:B1:8C:F8,bridge=vmbr0,firewall=1
numa: 0
ostype: l26
scsihw: virtio-scsi-single
smbios1: uuid=b99591a9-ec26-4171-9754-da593fa04e70
sockets: 1
startup: up=5
tablet: 0
tpmstate0: local:200/vm-200-disk-1.raw,size=4M,version=v2.0
vga: none
vmgenid: 20ae49f0-385a-4bcb-a14c-13e96af30625
配置完成后 运行 sudo qm start $VM_ID
等待几秒,屏幕亮起并看到屏幕显示 Proxmox
或 Tianocore
的 Logo,说明你已经成功了。
此时你可直通 USB
键盘,并按 ESC
进入 UEFI
设置。
之后正常安装 Windows 11
,并利用 Windows Update
自动安装驱动即可。
固件编译
看完之前的懒人版教程,你一定会好奇:
懒人版教程已经这么复杂了
请问我们的固件是怎么来的呢,岂不是要困难上天
不不不,取得我们的固件,并不困难啦!
下载 BIOS
并提取 VBT/GOP
找到你的主板官网,下载最新的 BIOS
。
下载最新版的 UEFI BIOS Updater
(当前为:UBU_v1.79.17
)。
如果找不到下载地址,可从本站下载:UBU_v1.79.17
接着运行 UBU.bat
,打开你下载的 BIOS
文件。
UBU
会自动分析你的 BIOS
映像。
根据提示按2
,按S
提取 VBT
和 GOP
。GOP
如上文所说的,是用于 UEFI
固件点亮显示器的。 VBT
是用于传统 BIOS
模式的。为了更好的兼容性,这里我们选择同时集成两个文件。
这里能找到我们所需的两个文件,IntelGopDriver.efi
和 vbt.bin
。
编译 OVMF 固件
系统准备
在你的 PVE
上创建一个 Ubuntu LXC
容器,并安装 Docker
和 Git
。
遵循这个项目,编译 OVMF
固件
https://github.com/Kethen/edk2-build-intel-gop
注意原作者在脚本里用的是 Podman
,而目前 LXC
中运行 Podman
仍存在一些问题,因此我们可以编辑脚本,将所有 podman
替换成 docker
,即可运行。
由于目前的网络环境,可能需要为 Docker
换源,并为脚本配置快速上网方式。
编译固件
接着,将你上一步提取的 GOP
和 VBT
移动到指定位置。
mkdir gop
cp <intel gop driver efi> gop/IntelGopDriver.efi
cp <intel gop vbt> gop/Vbt.bin
这里如何将你的 GOP
和 VBT
传输到 LXC
容器?sftp
即可。(你都折腾 PVE
了肯定会这个吧)
最后 sudo bash build_ovmf.sh
开始构建。
生成的 ./edk2/Build/OvmfX64/DEBUG_GCC5/FV/OVMF_CODE.fd
就是你所需要的文件。
用它替换 PVE
的 /usr/share/pve-edk2-firmware/OVMF_CODE_4M.fd
试试看,你的虚拟机是不是能看到 TianoCore
的启动界面了?
二进制移植
如果细心的你成功地用上面的固件引导 Windows 11
,可能会发现一些问题:
最明显的:设备管理器 TPM设备
黄色感叹号,设备固件无法初始化。
这是因为我们采用的 https://github.com/Kethen/edk2 的基础版太老了,没有 PVE
最新的 TPM
支持。
怎么办?最正规的方法当然是 fork
一份最新的pve-edk2
,自己打核显补丁!
不过我们自然不想把大量的时间耗费在移植代码上,因此我们选择一个投机取巧的方法:二进制移植!
从 /usr/share/pve-edk2-firmware/
提取 PVE
原版的 OVMF_CODE_4M.fd
和 OVMF_CODE_4M.secboot.fd
,和我们编译的 OVMF_CODE.fd
放到同一个文件夹里。
接着,下载 mmtool_ v5.0.0.7
放到相同文件夹。注意一定要是 5.0.0.7
这个版本。因为 AMI 在更高版本的 mmtools
禁用了编辑非 Aptio
平台映像的功能。(而我们的 OVMF
固件显然不基于 Aptio
平台)
如果找不到下载地址,可从本站下载:mmtool_v5.0.0.7
用 mmtool
打开 OVMF_CODE.fd
,提取其中的 IntelGopDriver
,PlatformGOPPolicy
和中间的无名文件,提取方式选择未压缩的。
这 3
个文件分别是:编译过的 GOP
段,加载GOP
需要的段和VBT
段。
接着用 mmtool
打开 OVMF_CODE_4M.fd
,在卷索引 02:00-00
按顺序插入 3
个文件(GOPDriver
,VBT
,PlatformGOPPolicy
),插入选项选择不压缩。
最后别忘了保存映像。另一个 OVMF_CODE_4M.secboot.fd
也如法炮制。
最后将文件复制回 PVE
并替换原有文件,启动虚拟机。
看看 TianoCore
的 Logo
是不是变成 Proxmox
了?进入系统,看看 TPM
是不是已经可用了?
最终效果图:
最后,祝大家折腾顺利,玩机开心!
参考
https://wiki.archlinux.org/title/Intel_GVT-g#Using_DMA-BUF_with_UEFI/OVMF
https://projectacrn.github.io/latest/tutorials/gpu-passthru.html
评论~ 13 条评论
李晓流 博主
GOPDriver,VBT,PlatformGOPPolicy这三个只需要提取platform的个,gop和vbt可以通过ubu提取以后转ffs 就是,然后三个一起插入。另外可以用最新edk2项目加入手工代码编译,详见我最新文章,不过直接mmtool操作方便。
Amagi_Yukisaki 博主
@李晓流
PlatformGOPPolicy我印象里SKL和TGL是不一样的,似乎和具体GOP文件相关;GOP和VBT这样提取的和直接转FFS应该是一样的,16进制查看FFS,和裸的GOP、VBT就差了个文件头;顺便求一下dalao文章地址~
anysoft 博主
@Amagi_Yukisaki
感谢博主的文章指路,遇到这么多大佬。
层主可能、也许、应该是这位 https://www.bilibili.com/read/cv27009520/?spm_id_from=333.999.0.0
Amagi_Yukisaki 博主
@anysoft
实际上这篇文章已经可以标记为deprecated了,最新的代码和这篇文章完全不一样。直接看GitHub就行。
好在现在这玩意已经很普及了(记得我刚开始折腾直通,4月份的时候,基本上一点中文资料都没有;8月的时候,有b站大大帅做出的成品二进制(付费)但没有代码,b站李晓流有代码但不是完整项目所以我并不知道怎么编译,最后我只能一点点整合大家的思路做出了这个勉强能用的教程。现在现成的视频教程/源码到处都是,这篇文章不更新其实也没什么大不了的,毕竟抛砖引玉的目的已经达到了)
gangqizai 博主
试试我的rom:无需定制ovmf 下载:https://github.com/gangqizai/igd
Amagi_Yukisaki 博主
@gangqizai
好活!蹲一波制作教程!
Bixlku 博主
感谢!
anysoft 博主
活捉一群大佬。
UEFI启动时候pve的OVMF直接直通这块网上资料比较少,还在研究逻辑和手动替换gop+vbios,大佬们就已经开源一条龙了。
anysoft 博主
我就是年初参考外网资料研究到编译ovmf没时间折腾去搞移植编译,然后搜到了大大帅的,花钱买了…
现在确实遍地开花了
rick 博主
请问我没法直通usb是为什么呢?我根据教程操作,dp口已经可以输出画面了,但是卡在了press any key to boot cd or dvd,usb无论如何都没法直通,没想到卡在了这里
Amagi_Yukisaki 博主
@rick
我遇到了同样的问题,edk2的uefi rom不一定能驱动你直通进去的usb控制器,因此可能会导致usb无响应/特定的usb设备引发虚拟机启动卡死。解决方案为通过pve的web ui将主机上的特定usb设备加入虚拟机,而不是直通控制器。