ubuntu 24.04 qemu 虚拟机 inter 和 nvidia 显卡直通,linux 下游戏3D加速全图详解,一学就会!

Source

ubuntu 24.04 安装 qemu ,并实现 Intel 核显和 Nvidia 显卡直通,让 Linux 可以也可以玩大型游戏,性能不输 Windows ——Linux 下游戏3D加速全图详解,一看就会!

众所周知,linux 下玩游戏绝对是硬伤,即便有 wine 这样的 windows 工具,可以运行 windows 程序,但是也只有部分游戏可以运行,大多数需要显卡支持的 3D 游戏很难运行。即使能运行,效果也很不理想。

一种解决思路是通过安装 Virtual Box 或 Vmware 虚拟机软件来模拟 Windows 环境,从而运行游戏。但是有个缺点,游戏比较吃显卡,Virtual Box 显存只有64M,根本无法运行3D类游戏,会提示各种运行库错误,即使安装上也不能正常运行,基本上是不能用。Vmware 的显卡加速效果比 Virtual Box 好,能够正常启动游戏,一般对显卡要求不高的游戏,Vmware 是可以流畅玩游戏的。笔者上学之前玩《仙剑奇侠传五》就是在 Vmware 虚拟机里玩的,一点都不卡,3D效果也很好。不过如果是要运行最新的游戏,虚拟机就不行了。

所以要让 linux 可以正常玩游戏,就必须直通显卡给虚拟机,让虚拟机中使用真实的物理显卡,而不是虚拟加速卡,这样就能在 linux 下玩各种游戏了。

本教程在 TinkPad E470C 测试通过。这款电脑,显卡属于 MUXless 架构,独显没有单独的显示输出,都是需要经过核显输出,因此有些小问题,具体见文尾。

硬件直通(Passthrough) VT-d 、DirectPath I/O,通过 DirectPath I/O,虚拟机可以使用 I/O 内存管理单元访问平台上的物理 PCI 功能,虚拟机会以直通独占的方式使用硬件,宿主机将不能再使用此硬件。

1. 检查 cpu 是否支持 VT-d(Intel)或 AMD-Vi(AMD),近年来的 cpu 如 intel i3 和 i5 都支持,10 代以上驱动有变化

在电脑 BIOS 中,开启虚拟化 VT-x、VT-d 的支持。可以到 Intel 的官方网站:https://www.intel.cn/ 输入cpu型号查询。

查看cpu信息,检查是否支持虚拟化:

egrep -c '(svm|vm)' /proc/cpuinfo

如果显示0,则不支持虚拟化。

查看显卡的架构:

lspci|egrep '(VGA|NVIDIA)'

查看有关Intel 和 NVIDIA 显卡的相关信息:

  • 如果独显设备名以 3D Controller 开头,那你的就是MUXless架构(核显直连显示器),独显通过核显输出。
  • 如果独显设备名以 VGA Controller 开头,并且有一个 HD Graphics 核显,那你的电脑是第二种 MUXed 架构(核显、独显切换),独显和核显可各自输出。
  • 如果独显设备名以 VGA Controller 开头,并且没有 HD Graphics 核显,那你的电脑是第三种屏蔽核显的架构,单独核显输出。

我的显卡是以 3D Controller开头的,所以属于MUXless架构,先把核显直通了,再直通NVIDIA。

在这里插入图片描述

2.启用 IOMMU 组,配置 Intel GVT-g 虚拟核显

打开/etc/default/grub,在找到GRUB_CMDLINE_LINUX=“”,添加内核启动参数:

GRUB_CMDLINE_LINUX=“intel_iommu=on”

AMD 开启参数为“ amd_iommu=on”

更新grub:

sudo update-grub

重启电脑。

检查内核是否启用了iommu:

sudo dmesg|grep -i iommu

在这里插入图片描述

如果看到 “pci XXXXX:XXX:XX.XX: Adding to iommu grep 1 ”这种字样,那么iommu 就启用成功了。没有看到的话,检查 BIOS 是否开启了虚拟化和 IOMMU,部分主板会在BIOS中设置这样的选项,有的话就开启,没有的话检查grub命令行是否拼写有错。

注意:显卡所在的 group 组可能还有其他设备,比如台式机 NVIDIA 显卡会有一个声音设备,在做显卡直通时,需要将group组内的所有设备都直通,不能单独直通其中的某一个设备。当然,也有可能将其中的显卡设备单独直通,这需要给内核打补丁,比较复杂,在此不做深入讨论,有兴趣的可以研究讨论。

在 qemu 中安装好 win 10 虚拟机,确保虚拟机能正常运行,安装教程见下:

qemu 安装 win 10 教程

安装好 win 10 系统后,关闭虚拟机,接下来开始显卡直通。

3.启用 GVT-g,添加内核所需的模块。

编辑grub,添加内核启动参数:

GRUB_CMDLINE_LINUX="i915.enable_gvt=1 kvm.ignore_msrs=1 intel_iommu=on"

添加vfio虚拟化模块:

sudo nano /etc/modules

添加以下内容,每个一行:

kvmgt
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

更新grub:

sudo update-grub

重启电脑。

4.创建 Intel 虚拟显卡

查找核显的 PCIe 总线编号:

lspci | grep "HD Graphics"

输出如下:

在这里插入图片描述

"00:02.0"就是核显的总线位置,记住它,一会需要用到。

首先生成UUID:

uuidgen

会生成一串16进制的数字,复制它,类似这样的“12e482d1-3b98-457f-8f2b-6eb52370e0e0”。

创建虚拟显卡:

sudo su
echo "12e482d1-3b98-457f-8f2b-6eb52370e0e0" > "/sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/create"

其中核显的 PCIe 编号,根据实际编号替换,UUID 同样根据生成的编号替换,不确定路径是否正确的话,可以打开/sys/devices目录,对应目录下查找是否存在相应的目录或文件。第一次配置虚拟机的时候,一定!!!先运行这个代码,不然后面虚拟机配置的时候会找不到虚拟显卡。

可以将此添加开机启动脚本,也可以将此代码写入 qemu 钩子脚本,在虚拟机开启的时候注入脚本:

sudo nano /etc/libvirt/hooks/qemu

将下列代码粘贴进去,注意 GVT_PCI、GVT_GUID、MDEV_TYPE、DOMAIN 这些变量换成你自己的,变量一定要用“ ”包起来。

#!/bin/bash
GVT_PCI="0000:00:02.0"
GVT_GUID="12e482d1-3b98-457f-8f2b-6eb52370e0e0"
MDEV_TYPE="i915-GVTg_V5_4"
DOMAIN="win10"
if [ $# -ge 3 ]; then
    if [[ " $DOMAIN " =~ .*\ $1\ .* ]] && [ "$2" = "prepare" ] && [ "$3" = "begin" ]; then
        echo "$GVT_GUID" > "/sys/devices/pci0000:00/$GVT_PCI/mdev_supported_types/$MDEV_TYPE/create"
    elif [[ " $DOMAIN " =~ .*\ $1\ .* ]] && [ "$2" = "release" ] && [ "$3" = "end" ]; then
        echo 1 > "/sys/devices/pci0000:00/$GVT_PCI/$GVT_GUID/remove"
    fi
fi
5.禁用 QXL,启用虚拟机 intel 核显

打开虚拟机管理器,查看虚拟机配置,点击“添加硬件”。此时,应该会看到“MDEV Host Device"中有主机设备:“MDEV_12e482d1_3b98_457f_8f2b_6eb52370e0e0”这样的设备,添加进主机。

在这里插入图片描述

在这里插入图片描述

启动虚拟机,打开设备管理器,应该会多出一个 Microsoft 基本显示适配器或者带感叹号的显示适配器,右键它选择自动更新驱动,系统会自动装好 Intel 的核显驱动,开始菜单里会出现 Intel 控制面板。如果无法使用自动更新,提前下好驱动拷贝到虚拟机里手动安装。

安装好驱动后,在任务管理器中能正常显示 Intel 核显后,关闭虚拟机。

禁用QXL

运行 virsh edit Win10,其中 Win10 是你的虚拟机名,找到如下内容,把 display='off' 改成 display='on',添加 ramfb='on'

<hostdev mode='subsystem' type='mdev' managed='no' model='vfio-pci' display='on' ramfb='on'>
  <source>
    <address uuid='12e482d1-3b98-457f-8f2b-6eb52370e0e0'/>
  </source>
</hostdev>

找到 <graphics>...</graphics><video>...</video> ,将中间的所有内容,替换成下列内容:

  <graphics type='spice'>
    <listen type='none'/>
    <image compression='off'/>
    <gl enable='yes'/>
  </graphics>
  <video>
    <model type='none'/>
  </video>

同时在 </domain> 之前添加如下内容:

<qemu:commandline>
    <qemu:arg value='-set'/>
    <qemu:arg value='device.hostdev0.driver=vfio-pci-nohotplug'/>
    <qemu:arg value='-set'/>
    <qemu:arg value='device.hostdev0.x-igd-opregion=on'/>
    <qemu:arg value='-set'/>
    <qemu:arg value='device.hostdev0.xres=1366'/>
    <qemu:arg value='-set'/>
    <qemu:arg value='device.hostdev0.yres=768'/>
    <qemu:arg value='-set'/>
    <qemu:arg value='device.hostdev0.romfile=/usr/share/seabios/vbios_gvt_uefi.rom'/>
</qemu:commandline>

qemu 7.0 以上的版本,要使用<qemu:override> 进行配置:

 <qemu:override>
    <qemu:device alias='hostdev0'>
      <qemu:frontend>
        <qemu:property name='x-igd-opregion' type='bool' value='true'/>
        <qemu:property name='driver' type='string' value='vfio-pci-nohotplug'/>
        <qemu:property name='xres' type='unsigned' value='1366'/>
        <qemu:property name='yres' type='unsigned' value='768'/>
        <qemu:property name='romfile' type='string' value='/usr/share/seabios/vbios_gvt_uefi.rom'/>
      </qemu:frontend>
    </qemu:device>
 </qemu:override>

其中 vbios_gvt_uefi.rom 从 http://120.25.59.132:3000/vbios_gvt_uefi.rom 下载。

把整个文件第一行的<domain type='kvm'> 改成<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

重新启动虚拟机,应该有正常的图像显示,此时虚拟机使用的是 GVT-g 物理虚拟显卡。

6.直通 NVIDIA 显卡

首先在 Windows 系统中使用 GPU-Z 工具导出显卡 BIOS,一般笔记本电脑导出会出错,那就不要管。使用提取官网 BIOS 更新包里的显卡 BIOS。注意,这是显卡的 BIOS,不是电脑的 BIOS。

(1)打开 win10 虚拟机,进入设备管理器,找到你的显卡,查看它的硬件 ID,类似 PCI\VEN_10DE&DEV_134F&SUBSYS_505C17AA&REV_A2,记录下来备用。

(2)到联想官网,找到对应型号电脑的 BIOS 更新程序,比如 ThinkPad E470C:

在这里插入图片描述

(3)选择 BIOS 升级程序,一般是exe格式,不要选择光盘版,比如这里下的是 BIOS-r0duj36w.exe

接着,提取程序里的显卡 BIOS,需要用到几个工具,按照下列代码所示操作:

# 下载 VBiosFinder
git clone https://github.com/coderobe/VBiosFinder.git
mv BIOS-r0duj36w.exe VBiosFinder/
# 安装依赖
sudo apt install ruby ruby-bundler innoextract p7zip upx-ucl
# 安装 rom-parser
git clone https://github.com/awilliam/rom-parser.git
cd rom-parser
make
mv rom-parser ../VBiosFinder/3rdparty
cd ..
# 安装 UEFIExtract
git clone https://github.com/LongSoft/UEFITool.git
cd UEFITool
./unixbuild.sh
mv UEFIExtract/UEFIExtract ../VBiosFinder/3rdparty
cd ..
# 开始提取显卡 BIOS
cd VBiosFinder
bundle update --bundler
bundle install --path=vendor/bundle
./vbiosfinder extract BIOS-r0duj36w.exe
ls output
# output 文件夹内有几个命名类似如下的文件:
# - vbios_10de_134f_1.rom
# - vbi