我对这一切都很陌生,并尝试设置具有单 GPU 直通功能的虚拟机。我的主机正在运行 Ubuntu 24.04,我正在尝试在 Virt-Manager 中设置 Windows 11 虚拟机。
我主要遵循 Youtube 上 SomeOrdinaryGamers 的教程并结合一些指南来使其适应 Ubuntu。
我已经在虚拟机中成功安装了 Win11,并设置了所有挂钩,但是,设置挂钩后,每当我尝试启动虚拟机时,什么都没有发生(没有错误消息,没有窗口出现并立即重新出现,也没有显示器变黑)。但是,下次我尝试重新启动或关闭主机时,它不会先关闭,而是先将我带到用户的登录屏幕(如果我登录,它会显示我的桌面,但没有打开任何程序)。几秒钟后,无论我是否登录,它都会进入典型的 ubuntu 关闭屏幕,并且无法真正关闭。它只是进入黑屏,然后我不得不按下机箱上的重置按钮。
尝试了一次后,我的机器就无法再启动了(只显示所有已启动服务的屏幕,旁边有一个“确定”),我不得不重新安装 Ubuntu(没问题 - 反正都是全新安装)
当我单独运行启动脚本时,它成功断开了我的监视器的连接。
如果效果更好的话,我也不反对尝试使用 Windows 10,但是我宁愿不要再花 6 个小时等待 Windows 在 VM 中安装,而只是为了得到相同的结果。
我的电脑有 Ryzen 9 3900X 和 RTX 3080 以及 32GB RAM,我正在单独硬盘上的 3TB 分区中安装 Windows。
我的脚本目前如下:
/etc/libvirt/hooks/kvm.conf
VIRSH_GPU_VIDEO=pci_0000_09_00_0
VIRSH_GPU_AUDIO=pci_0000_09_00_1
/etc/libvirt/钩子/qemu
#!/usr/bin/env bash
#
# Author: SharkWipf
#
# Copy this file to /etc/libvirt/hooks, make sure it's called "qemu".
# After this file is installed, restart libvirt.
# From now on, you can easily add per-guest qemu hooks.
# Add your hooks in /etc/libvirt/hooks/qemu.d/vm_name/hook_name/state_name.
# For a list of available hooks, please refer to https://www.libvirt.org/hooks.html
#
GUEST_NAME="$1"
HOOK_NAME="$2"
STATE_NAME="$3"
MISC="${@:4}"
BASEDIR="$(dirname $0)"
HOOKPATH="$BASEDIR/qemu.d/$GUEST_NAME/$HOOK_NAME/$STATE_NAME"
set -e # If a script exits with an error, we should as well.
# check if it's a non-empty executable file
if [ -f "$HOOKPATH" ] && [ -s "$HOOKPATH" ] && [ -x "$HOOKPATH" ]; then
eval \"$HOOKPATH\" "$@"
elif [ -d "$HOOKPATH" ]; then
while read file; do
# check for null string
if [ ! -z "$file" ]; then
eval \"$file\" "$@"
fi
done <<< "$(find -L "$HOOKPATH" -maxdepth 1 -type f -executable -print;)"
fi
/etc/libvirt/hooks/qemu.d/win11/prepare/begin/start.sh
#!/bin/bash
# Helpful to read output when debugging
set -x
# load variables
source "/etc/libvirt/hooks/kvm.conf"
# 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 5
# Unload Nvidia
modprobe -r nvidia_drm
modprobe -r nvidia_modeset
modprobe -r drm_kms_helper
modprobe -r nvidia
modprobe -r i2c_nvidia_gpu
modprobe -r drm
modprobe -r nvidia_uvm
# Unbind the GPU from display driver
virsh nodedev-detach $VIRSH_GPU_VIDEO
virsh nodedev-detach $VIRSH_GPU_AUDIO
# Load VFIO Kernel Module
# not sure if these are with a - or an _ since i found both in different guides, so i tried using both
modprobe vfio
modprobe vfio-pci
modprobe vfio_pci
modprobe vfio_iommu_type1
modprobe vfio-iommu-type1
/etc/libvirt/hooks/qemu.d/win11/release/end/revert.sh
#!/bin/bash
set -x
# Load variables
source "/etc/libvirt/hooks/kvm.conf"
# Attach GPU devices to host
# Use your GPU and HDMI Audio PCI host device
virsh nodedev-reattach $VIRSH_GPU_VIDEO
virsh nodedev-reattach $VIRSH_GPU_AUDIO
# Unload vfio module
# not sure if these are with a - or an _ since i found both in different guides, so i tried using both
modprobe -r vfio
modprobe -r vfio-pci
modprobe -r vfio_pci
modprobe -r vfio-iommu-type1
modprobe -r vfio_iommu_type1
# Load AMD kernel module
#modprobe amdgpu
# Rebind framebuffer to host
echo "efi-framebuffer.0" > /sys/bus/platform/drivers/efi-framebuffer/bind
# Load NVIDIA kernel modules
modprobe nvidia_drm
modprobe nvidia_modeset
modprobe nvidia_uvm
modprobe nvidia
modprobe drm
modprobe drm_kms_helper
# Bind VTconsoles: might not be needed
echo 1 > /sys/class/vtconsole/vtcon0/bind
echo 1 > /sys/class/vtconsole/vtcon1/bind
# Restart Display Manager
systemctl start display-manager
最后是 virt-manager 中的 XML:
<domain type="kvm">
<name>win11</name>
<uuid>d2bfd573-8485-43c9-88a8-957bfdfe88aa</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://microsoft.com/win/11"/>
</libosinfo:libosinfo>
</metadata>
<memory unit="KiB">28672000</memory>
<currentMemory unit="KiB">28672000</currentMemory>
<vcpu placement="static">20</vcpu>
<os firmware="efi">
<type arch="x86_64" machine="pc-q35-8.2">hvm</type>
<firmware>
<feature enabled="yes" name="enrolled-keys"/>
<feature enabled="yes" name="secure-boot"/>
</firmware>
<loader readonly="yes" secure="yes" type="pflash">/usr/share/OVMF/OVMF_CODE_4M.ms.fd</loader>
<nvram template="/usr/share/OVMF/OVMF_VARS_4M.ms.fd">/var/lib/libvirt/qemu/nvram/win11_VARS.fd</nvram>
</os>
<features>
<acpi/>
<apic/>
<hyperv mode="custom">
<relaxed state="on"/>
<vapic state="on"/>
<spinlocks state="on" retries="8191"/>
<vendor_id state="on" value="buttplug"/>
</hyperv>
<kvm>
<hidden state="on"/>
</kvm>
<vmport state="off"/>
<smm state="on"/>
</features>
<cpu mode="host-passthrough" check="none" migratable="on">
<topology sockets="1" dies="1" cores="10" 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>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type="file" device="disk">
<driver name="qemu" type="raw"/>
<source file="/mnt/06a918ae-9833-4158-866d-f49b6587c64f/win11.img"/>
<target dev="sda" bus="sata"/>
<boot order="1"/>
<address type="drive" controller="0" bus="0" target="0" unit="0"/>
</disk>
<disk type="file" device="cdrom">
<driver name="qemu" type="raw"/>
<source file="/mnt/06a918ae-9833-4158-866d-f49b6587c64f/Win11_23H2_English_x64v2.iso"/>
<target dev="sdb" bus="sata"/>
<readonly/>
<boot order="2"/>
<address type="drive" controller="0" bus="0" target="0" unit="1"/>
</disk>
<controller type="usb" index="0" model="qemu-xhci" ports="15">
<address type="pci" domain="0x0000" bus="0x02" slot="0x00" function="0x0"/>
</controller>
<controller type="pci" index="0" model="pcie-root"/>
<controller type="pci" index="1" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="1" port="0x10"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="2" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="2" port="0x11"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x1"/>
</controller>
<controller type="pci" index="3" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="3" port="0x12"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x2"/>
</controller>
<controller type="pci" index="4" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="4" port="0x13"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x3"/>
</controller>
<controller type="pci" index="5" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="5" port="0x14"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x4"/>
</controller>
<controller type="pci" index="6" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="6" port="0x15"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x5"/>
</controller>
<controller type="pci" index="7" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="7" port="0x16"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x6"/>
</controller>
<controller type="pci" index="8" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="8" port="0x17"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x7"/>
</controller>
<controller type="pci" index="9" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="9" port="0x18"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="10" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="10" port="0x19"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x1"/>
</controller>
<controller type="pci" index="11" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="11" port="0x1a"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x2"/>
</controller>
<controller type="pci" index="12" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="12" port="0x1b"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x3"/>
</controller>
<controller type="pci" index="13" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="13" port="0x1c"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x4"/>
</controller>
<controller type="pci" index="14" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="14" port="0x1d"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x5"/>
</controller>
<controller type="sata" index="0">
<address type="pci" domain="0x0000" bus="0x00" slot="0x1f" function="0x2"/>
</controller>
<controller type="virtio-serial" index="0">
<address type="pci" domain="0x0000" bus="0x03" slot="0x00" function="0x0"/>
</controller>
<interface type="network">
<mac address="52:54:00:c0:59:8a"/>
<source network="default"/>
<model type="e1000e"/>
<address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
</interface>
<serial type="pty">
<target type="isa-serial" port="0">
<model name="isa-serial"/>
</target>
</serial>
<console type="pty">
<target type="serial" port="0"/>
</console>
<channel type="spicevmc">
<target type="virtio" name="com.redhat.spice.0"/>
<address type="virtio-serial" controller="0" bus="0" port="1"/>
</channel>
<input type="tablet" bus="usb">
<address type="usb" bus="0" port="1"/>
</input>
<input type="mouse" bus="ps2"/>
<input type="keyboard" bus="ps2"/>
<tpm model="tpm-crb">
<backend type="emulator" version="2.0"/>
</tpm>
<graphics type="spice" autoport="yes">
<listen type="address"/>
<image compression="off"/>
</graphics>
<sound model="ich9">
<address type="pci" domain="0x0000" bus="0x00" slot="0x1b" function="0x0"/>
</sound>
<audio id="1" type="spice"/>
<video>
<model type="qxl" ram="65536" vram="65536" vgamem="16384" heads="1" primary="yes"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</video>
<hostdev mode="subsystem" type="usb" managed="yes">
<source>
<vendor id="0x046d"/>
<product id="0xc07d"/>
</source>
<address type="usb" bus="0" port="4"/>
</hostdev>
<hostdev mode="subsystem" type="usb" managed="yes">
<source>
<vendor id="0x046d"/>
<product id="0xc33e"/>
</source>
<address type="usb" bus="0" port="5"/>
</hostdev>
<hostdev mode="subsystem" type="usb" managed="yes">
<source>
<vendor id="0x1397"/>
<product id="0x0507"/>
</source>
<address type="usb" bus="0" port="6"/>
</hostdev>
<hostdev mode="subsystem" type="pci" managed="yes">
<source>
<address domain="0x0000" bus="0x09" slot="0x00" function="0x0"/>
</source>
<rom file="/usr/share/vgabios/vbios.rom"/>
<address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
</hostdev>
<hostdev mode="subsystem" type="pci" managed="yes">
<source>
<address domain="0x0000" bus="0x09" slot="0x00" function="0x1"/>
</source>
<rom file="/usr/share/vgabios/vbios.rom"/>
<address type="pci" domain="0x0000" bus="0x06" slot="0x00" function="0x0"/>
</hostdev>
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="2"/>
</redirdev>
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="3"/>
</redirdev>
<watchdog model="itco" action="reset"/>
<memballoon model="virtio">
<address type="pci" domain="0x0000" bus="0x04" slot="0x00" function="0x0"/>
</memballoon>
</devices>
</domain>
我希望这是发布此问题的正确地方,并且有比我更有经验的人可以帮助我找到我的问题
您只有一个 GPU 吗?除非您通过 SSH 连接并禁用了 GUI,否则您需要为主机配备第二个 GPU。此外,您可能需要在 grub2 配置中隔离 GPU,以便主机不会尝试加载它。
这里有一个很好的 22.04 教程(我认为与 24.04 非常相似):https ://mathiashueber.com/passthrough-windows-11-vm-ubuntu-22-04/
最终我自己成功解决了这个问题。如果其他人也遇到过这个问题,以下是我遇到过的方法:
首先,我通过完全删除 /etc/libvirt/hooks 文件夹来删除我之前安装的所有钩子
按照本指南中的第 1 步到第 6 步进行操作。请勿按照第 7 步进行操作: https://gitlab.com/risingprismtv/single-gpu-passthrough/-/wikis/home (因为我已经安装了虚拟机,所以我跳过了第 5 步)
接下来按照本指南的自动安装(不要转到手动分支。它似乎已经过时了): https://github.com/ilayna/Single-GPU-passthrough-amd-nvidia ?tab=readme-ov-file
接下来,返回原始指南第 8 步。您应该按照指南中的说明删除 XML 块(可能需要启用 XML 编辑),并根据需要删除任何其他 XML 块(Virt-manager 可能会告诉您,如果没有 spice,则无法使用特定功能。删除它提到的块)
接下来,按照指南中步骤 8b 的说明,在 XML 文件中添加和行
<vendor_id state='on' value='123456789123'/>
以及<ioapic driver='kvm'/>
块<kvm> ... </kvm>
(我没有在该步骤中执行其他操作)最后,我按照指南第 9 步的说明启用了 topoext
这使我能够启动具有完全直通 GPU 的 VM(尽管 Windows 还需要大约 10 分钟的时间来安装驱动程序并检测两个显示器)。