QEMU 嵌套虚拟机

QEMU 嵌套虚拟机

我正在尝试在 Debian 12 上使用 qemu 和 virt-manager 构建一个测试环境,以托管运行 WSL2 的 Windows 11 客户机。

我已经设法安装了 Windows 11(使用 swtpm 和 ovmf 来满足 TPM 和 UEFI 的要求),但是当我尝试安装 WSL 时,安装本身似乎成功了,但是当客户机重新启动以完成安装过程时,它会启动到 Windows 11 自动修复屏幕,并且再也无法恢复。

我认为问题与 CPU 仿真不支持嵌套虚拟化有关,因此为了检查客户机是否支持嵌套虚拟化,我在客户机上全新安装了 Debian 12,然后在客户机上安装了 qemu 和 virt-manager,然后成功创建了嵌套客户机。

WSL 的系统要求似乎有点模糊(常问问题只是说需要嵌套虚拟化),但显然有些不对劲,因为即使我可以嵌套 QEMU 客户机,WSL2 也无法工作!

我需要对下面的模板或者在 Windows 11 客户机上做什么才能使 WSL2 正常工作——或者我的物理主机的处理器缺少一个关键功能?

编辑 15/11:这不是硬件问题,我可以使用 VMware Player 17 在 Windows 11 客户机上安装 WSL2。

谢谢。

Debian 12 安装以下版本的软件。

gir1.2-libvirt-glib-1.0:amd64        4.0.0-2
ipxe-qemu                            1.0.0+git-20190125.36a4c85-5.1
libvirt-clients                      9.0.0-4
libvirt-daemon                       9.0.0-4
libvirt-daemon-config-network        9.0.0-4
libvirt-daemon-config-nwfilter       9.0.0-4
libvirt-daemon-driver-qemu           9.0.0-4
libvirt-daemon-system                9.0.0-4
libvirt-daemon-system-systemd        9.0.0-4
libvirt-glib-1.0-0:amd64             4.0.0-2
libvirt0:amd64                       9.0.0-4
ovmf                                 2022.11-6
python3-libvirt                      9.0.0-1
qemu-system-common                   1:7.2+dfsg-7+deb12u2
qemu-system-data                     1:7.2+dfsg-7+deb12u2
qemu-system-x86                      1:7.2+dfsg-7+deb12u2
qemu-utils                           1:7.2+dfsg-7+deb12u2
swtpm                                0.7.1-1.3
swtpm-libs:amd64                     0.7.1-1.3
swtpm-tools                          0.7.1-1.3
virt-manager                         1:4.1.0-2
virtinst                             1:4.1.0-2

我的客户机是使用以下 XML 模板定义的。

<domain type='kvm'>
  <name>guest</name>
  <uuid>68171bfe-29f3-4e19-93b6-00b8d9501469</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'>4194304</memory>
  <currentMemory unit='KiB'>4194304</currentMemory>
  <vcpu placement='static'>2</vcpu>
  <os firmware='efi'>
    <type arch='x86_64' machine='pc-q35-7.2'>hvm</type>
    <boot dev='hd'/>
    <bootmenu enable='no'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <hyperv mode='custom'>
      <relaxed state='on'/>
      <vapic state='on'/>
      <spinlocks state='on' retries='8191'/>
    </hyperv>
    <vmport state='off'/>
  </features>
  <cpu mode='host-passthrough' check='none' migratable='on'/>
  <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='qcow2'/>
      <source file='/home/.../disk1.qcow2'/>
      <target dev='sda' bus='sata'/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw'/>
      <target dev='sdb' bus='sata'/>
      <readonly/>
      <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='bridge'>
      <mac address='52:54:00:fe:66:8e'/>
      <source bridge='br0'/>
      <model type='e1000e'/>
      <link state='up'/>
      <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>
    <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>
    <memballoon model='virtio'>
      <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
    </memballoon>
  </devices>
</domain>

Cat/proc/cpuinfo给出了物理主机上的以下详细信息(仅第一个核心);

processor   : 0
vendor_id   : GenuineIntel
cpu family  : 6
model       : 142
model name  : Intel(R) Core(TM) i7-10610U CPU @ 1.80GHz
stepping    : 12
microcode   : 0xf8
cpu MHz     : 400.000
cache size  : 8192 KB
physical id : 0
siblings    : 8
core id     : 0
cpu cores   : 4
apicid      : 0
initial apicid  : 0
fpu     : yes
fpu_exception   : yes
cpuid level : 22
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities
vmx flags   : vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec
bugs        : spectre_v1 spectre_v2 spec_store_bypass swapgs taa itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips    : 4599.93
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

并在客人身上取得了以下成果。

processor   : 0
vendor_id   : GenuineIntel
cpu family  : 6
model       : 142
model name  : Intel(R) Core(TM) i7-10610U CPU @ 1.80GHz
stepping    : 12
microcode   : 0xf8
cpu MHz     : 2303.996
cache size  : 16384 KB
physical id : 0
siblings    : 1
core id     : 0
cpu cores   : 1
apicid      : 0
initial apicid  : 0
fpu     : yes
fpu_exception   : yes
cpuid level : 22
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology cpuid tsc_known_freq pni pclmulqdq vmx ssse3 fma cx16 pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves arat umip md_clear arch_capabilities
vmx flags   : vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest shadow_vmcs pml
bugs        : spectre_v1 spectre_v2 spec_store_bypass swapgs taa srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips    : 4607.99
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

# cat /sys/module/kvm_intel/parameters/nested
Y
#

即使重新安装 Windows 11 后,按照下面的建议启用ignore_msrs也没有任何区别。

# cat /sys/module/kvm/parameters/ignore_msrs
Y
#

QEMU 似乎认为一切正常(只有一个警告,而且我知道安全启动已启用,因为 Windows 11 在安装 WSL 之前一直有效)。

# virt-host-validate
  QEMU: Checking for hardware virtualization                                 : PASS
  QEMU: Checking if device /dev/kvm exists                                   : PASS
  QEMU: Checking if device /dev/kvm is accessible                            : PASS
  QEMU: Checking if device /dev/vhost-net exists                             : PASS
  QEMU: Checking if device /dev/net/tun exists                               : PASS
  QEMU: Checking for cgroup 'cpu' controller support                         : PASS
  QEMU: Checking for cgroup 'cpuacct' controller support                     : PASS
  QEMU: Checking for cgroup 'cpuset' controller support                      : PASS
  QEMU: Checking for cgroup 'memory' controller support                      : PASS
  QEMU: Checking for cgroup 'devices' controller support                     : PASS
  QEMU: Checking for cgroup 'blkio' controller support                       : PASS
  QEMU: Checking for device assignment IOMMU support                         : PASS
  QEMU: Checking if IOMMU is enabled by kernel                               : PASS
  QEMU: Checking for secure guest support                                    : WARN (Unknown if this platform has Secure Guest support)

重复全新安装 Windows 11,它运行良好,直到我安装 WSL,它才进入启动/修复循环......

如果出现 BSOD,我看不到它。

答案1

在这种情况下,少即是多。

在物理主机的 BIOS 中禁用 SGX CPU 功能允许我在作为 QEMU 客户机运行的 Windows 11 上安装 WSL2。无需更改 QEMU 或客户机配置。

我怀疑这可能与讨论的 EPC 内存部分有关这里(或者可能是缺乏这些)但是现在我对这个主题了解不够多,无法说出来。

希望这对某人有帮助!

答案2

我相信它确实反复出现SYSTEM THREAD EXCEPTION NOT HANDLEDBSOD,最终导致它自动修复。

这似乎是一个长期存在的问题,可以通过将模块设置ignore_msrskvm来解决1

为此,请/etc/modprobe.d/kvm.conf在文件中创建并包含以下行:

options kvm ignore_msrs=1

然后以 root 身份使用 sudo / 运行以下命令:

modprobe -r kvm_intel
modprobe kvm_intel

(是的,kvm_intel不是kvm。请确保您包含了-r,这样它kvm也会被卸载。如果愿意,您也可以重新启动。)

您可以检查以/sys/module/kvm/parameters/ignore_msrs确认Y配置是否生效。

PS 这假设您的发行版已将两者kvm作为kvm_intel模块构建。如果没有,请kvm.ignore_msrs=1在内核命令行中使用。

答案3

在 Linux 主机上的 Windows 11 客户机中安装 Docker Desktop(默认情况下使用 WSL)后,Windows 虚拟机无法启动,但该问题已通过 AnthonyK 的评论得到修复(QEMU 嵌套虚拟机):

禁用 CPU 直通,然后单击 Virt-manager 中模型下拉菜单中的清除 CPU 配置即可解决问题。

然而,Docker Desktop 和 WSL 仍然无法工作,但我找到了一个解决方案(https://stackoverflow.com/questions/62274613/run-wsl2-in-windows-10-guest-vm-running-on-a-linux-host/70321015#70321015基于Kvm 嵌套 Virtualbox Windows 客户机) 通过在 Google 上搜索“virt-manager wsl Passthrough”来找到。

由于出现错误,我不得不通过在 virt-manager 的 XML 设置中添加最后一行来调整解决方案(https://gitlab.com/libvirt/libvirt/-/issues/608):

<cpu mode="custom" match="exact" check="partial">
    <model fallback="allow">Skylake-Client-noTSX-IBRS</model>
    <feature policy="disable" name="hypervisor"/>
    <feature policy="require" name="vmx"/>
    <feature policy='disable' name='mpx'/>
</cpu>

注意:我遇到了一个临时启动错误,该错误已通过使用 virt-manager 配置中的所有 CPU 核心得到修复,但这似乎不再必要。当我尝试将 RAM 从 24576 MiB 更改为 22528 MiB 时也出现了启动错误。我看到 Docker Desktop 正在运行“hello world”程序,该程序可能需要一段时间才能安装。

相关内容