本文配置了单显卡下的显卡直通。由于只有一张显卡,因此 Linux 侧的 Display Manager 和虚拟机无法共存。而这就是单显卡直通的原理所在:在直通期间将显卡释放,通过 PCI 直通给虚拟机使用;在虚拟机不再使用显卡时,重新启动 Display Manager 以继续使用 Linux 桌面。

本文中的配置主要参考了 Single-GPU-Passthrough-for-Arch-Linux 的教程。

ToC

IOMMU

由于个人在配置这篇文章之前就已经开启了 IOMMU,所以本文也跳过这一步骤。在 Hooks 之前的步骤可以参考上文提及的教程。

Hooks

单显卡直通配置的核心,通过配置虚拟机启动和关闭的钩子,实现显卡的自动释放和回收。首先线获得脚本:

sudo wget 'https://raw.githubusercontent.com/PassthroughPOST/VFIO-Tools/master/libvirt_hooks/qemu' -O /etc/libvirt/hooks/qemu

创建目录:

sudo mkdir /etc/libvirt/hooks/qemu.d /etc/libvirt/hooks/qemu.d/win10 /etc/libvirt/hooks/qemu.d/win10/prepare /etc/libvirt/hooks/qemu.d/win10/prepare/begin /etc/libvirt/hooks/qemu.d/win10/release /etc/libvirt/hooks/qemu.d/win10/release/end

创建 /etc/libvirt/hooks/qemu.d/win10/prepare/begin/start.sh

#!/bin/bash

## Helpful to read output when debugging

set -x

# Stop display manager

systemctl stop display-manager.service

## Uncomment the following line if you use GDM

#killall gdm-x-session

# Unbind VTconsoles

echo 0 > /sys/class/vtconsole/vtcon0/bind

echo 0 > /sys/class/vtconsole/vtcon1/bind

# Unbind EFI-Framebuffer

echo efi-framebuffer.0 > /sys/bus/platform/drivers/efi-framebuffer/unbind

# Avoid a Race condition by waiting 2 seconds. This can be calibrated to be shorter or longer if required for your system

sleep 2

# Unload all Nvidia drivers

modprobe -r nvidia_drm

modprobe -r nvidia_modeset

modprobe -r nvidia_uvm

modprobe -r nvidia

## Load vfio

modprobe vfio

modprobe vfio_iommu_type1

modprobe vfio_pci

创建 /etc/libvirt/hooks/qemu.d/win10/release/end/stop.sh

#!/bin/bash

set -x

## Unload vfio

modprobe -r vfio_pci

modprobe -r vfio_iommu_type1

modprobe -r vfio

# Rebind VT consoles

echo 1 > /sys/class/vtconsole/vtcon0/bind

echo 1 > /sys/class/vtconsole/vtcon1/bind

nvidia-xconfig --query-gpu-info > /dev/null 2>&1

echo "efi-framebuffer.0" > /sys/bus/platform/drivers/efi-framebuffer/bind

modprobe nvidia_drm

modprobe nvidia_modeset

modprobe nvidia_uvm

modprobe nvidia

# Restart Display Manager

systemctl start display-manager.service

将所有脚本都设置为可执行:

sudo chmod +x /etc/libvirt/hooks/qemu

sudo chmod +x /etc/libvirt/hooks/qemu.d/win10/prepare/begin/start.sh

sudo chmod +x /etc/libvirt/hooks/qemu.d/win10/release/end/stop.sh

创建虚拟机

  1. 打开 virt-manager,在 编辑-Preferences 中找到 启用 XML 编辑 并打勾
  2. 新建虚拟机,选择本地安装,找到 ISO 并加载。 注意,虚拟机的名称必须为 win10
  3. 确定 Customize configuration before install 是勾选的,因为在启动之前我们需要进行一些设置
  4. 将固件设置为 OVMF_CODE
  5. 勾选 CPU 数-拓扑-手动设置 CPU 拓扑,根据实际情况设置
  6. 开始安装
  7. Windows 安装成功后,关闭虚拟机。然后重启 libvirt 以激活 Hook

sudo systemctl restart libvirtd.service

修改 VBIOS

网上很多的教程都需要这一步,但我实际测试下来,现在好像已经不需要这一步的操作了。

最后准备

  1. 删除 USB Redirector 1USB Redirector 2
  2. 删除 Sound ich9
  3. 删除 Channel spice
  4. 进入 概况 页,在 XML 中找到以下内容并删除

<graphics type="spice" autoport="yes">

<listen type="address"/>

<image compression="off"/>

</graphics>

<audio id="1" type="spice"/>

  1. 直通鼠标和键盘:在 添加硬件 - USB 主机设备 的详情页面中找到对应 USB 设备
  2. 直通显卡:在 添加硬件 - PCI 主机设备的详情页中找到显卡和音频设备并添加
  3. 网卡。因为我显示器上还有一张单独的网卡,所以我选择把它也直通进去

配置完成,试着启动一下虚拟机吧(