Windows 10 UEFI 物理机到 KVM/libvirt 虚拟机

Windows 10 UEFI 物理机到 KVM/libvirt 虚拟机

原始帖子

我正在将我的 PC 从 Windows 10 迁移到 Linux。有些事情我仍需要 Windows,而且我目前是双启动的,Windows 和 Linux 位于不同的物理磁盘上。我想摆脱双启动,并在 KVM+libvirt+qemu 下虚拟化运行我的 Windows 10 安装。

这里棘手的部分似乎是我的 Windows 10 安装是通过 UEFI(使用 GPT 分区表)完成的,而不是通过旧式 BIOS MBR。我的 Windows 磁盘如下所示:

$ sudo parted /dev/nvme0n1 print
Model: Unknown (unknown)
Disk /dev/nvme0n1: 500GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number  Start   End    Size    File system  Name                          Flags
 1      1049kB  524MB  523MB   ntfs         Basic data partition          hidden, diag
 2      524MB   628MB  104MB   fat32        EFI system partition          boot, esp
 3      628MB   645MB  16.8MB               Microsoft reserved partition  msftres
 4      645MB   500GB  499GB   ntfs         Basic data partition          msftdata

由于它是作为 UEFI 设置的,因此似乎需要一些额外的步骤才能进行虚拟化,因为 libvirt 似乎不支持开箱即用的 UEFI。我尝试使用以下命令将上述每个分区导出为 qcow2 映像:

$ qemu-img convert -f raw -O qcow2 /dev/nvme0n1p1 win10_part1.qcow2

并对所有四个分区重复此操作。然后我在 virt-manager 下创建了一个虚拟机,导入了所有四个 qcow2 驱动器。我为我的发行版 (Manjaro) 安装了“ovmf”包,并在虚拟机的 XML 配置文件的“os”部分中添加了此行:

<loader type='rom'>/usr/share/ovmf/x64/OVMF_CODE.fd</loader>

当我启动虚拟机时,我看到了 TianoCore 启动画面。但它只是让我进入 grub2 shell,而不是找到 Windows 引导加载程序。

我还尝试从 Windows 10 安装 ISO 启动此虚拟机,希望可以“修复”系统以启动。但这没有用。

我肯定我漏掉了什么。更好的办法是将其转换为 MBR 启动,以避免对 OVMF 的依赖。


编辑/更新...

根据 Dylan 的评论,我确实让它工作了,但在此过程中出现了一些小问题,我想我应该把它们发布在这里,以防其他人遇到类似的问题。

第一步是,正如迪伦所写,创造一个形象整个磁盘,而不是每个分区一个单独的磁盘。我使用了这个命令:

qemu-img convert -f raw -O qcow2 /dev/nvme0n1 win10_import.qcow2

然后,我在 virt-manager 中创建了虚拟机,并将上述磁盘映像(“win10_import.qcow2”)指定为我的驱动器。

接下来是使用 OVMF (TianoCore) UEFI 固件。这是通过安装 ovmf 包(Manjaro 上为“ovmf”),然后将其添加到虚拟机的 XML 定义中来完成的:

  <os>
    <type arch='x86_64' machine='pc-q35-3.0'>hvm</type>
    <loader type='rom'>/usr/share/ovmf/x64/OVMF_CODE.fd</loader>
  </os>

此后,Windows 将仍然启动时崩溃,出现蓝屏和错误“系统线程异常未处理”。出于某种原因,它不喜欢“复制主机 CPU 配置”CPU 设置。我将其更改为“core2duo”,然后启动。现在我正在使用“SandyBridge”,它也可以正常工作。(值得一提的是,我确实创建了另一个单独的 Win10 VM,从头开始进行全新安装。 VM 确实与“复制主机 CPU 配置”配合使用。我的 CPU 是 AMD Ryzen 5 2400G。)

我遇到的下一个问题是 Windows 10 运行速度慢得令人无法忍受。不知怎的,我设法用“QEMU TCG”虚拟机管理程序创建了虚拟机,而不是“KVM”。这是有道理的,因为前者仿真并且速度非常慢,而后者是真正的硬件辅助虚拟化。(这是怎么发生的:在尝试使其工作时,我还对物理系统进行了 BIOS 升级,重置了我的所有 BIOS 设置,其中一个禁用了虚拟化(在我的 BIOS 中称为“SVM”)。一旦我纠正了这个问题,我就能够使用接近原生速度的 KVM 虚拟机管理程序。)

下一个问题是屏幕分辨率卡在 800x600。Windows 不允许我更改它。我可以通过按Esc键机器一启动,就在 TianoCore 启动画面出现时。这会将我带入 UEFI 设置,在那里我可以强制使用更高的分辨率。但这不是永久的解决方案。

由于我的虚拟机指定 QXL 作为视频设备,因此我需要在 Windows 中安装 QXL 驱动程序。此页面使用 virtIO 驱动程序创建 Windows 虚拟机解释了如何做到这一点。简短的版本是这样的:下载virtio-win iso在主机上。将其作为 CD-ROM 驱动器添加到 VM。然后,启动 VM,导航到 CD-ROM 上的正确文件夹,并安装所有所需的 VirtIO 驱动程序。具体来说,对于 Windows 10 上的 QXL 视频,“qxldod”文件夹有正确的驱动程序。

答案1

QEMU/Libvirt 要求您提供虚拟磁盘:您的 QCOW2 文件应该是磁盘而不是分区。通过执行上述操作,您得到了 4 个 qcow2 文件,每个文件都有一个分区。您破坏了以前的结构,因此 GRUB 无法再启动您的系统也就不足为奇了。

我建议您将整个物理驱动器转换为单个 QCOW2 文件,然后将该虚拟驱动器附加到您的 VM。

您应该能够从 EFI 分区中删除 GRUB EFI 文件(参见 libguestfs 工具)并获取启动菜单,因为 Windows 启动加载程序应该由 VM 的 UEFI 加载。

答案2

如果其他人偶然发现了这个问题,还有另一种选择,即在 Linux 中使用本机 Windows 安装作为 VM:

  1. 按照 Dylan 接受的答案对整个设备进行成像。
  2. 从原始存储运行虚拟机。

我设法解决了上面的 #2 问题,但这可能相当复杂。如果 Linux 和 Windows 共享同一设备,情况会变得相当复杂且有风险。

出于以下原因,这样做是值得的:

  • 已经有并且喜欢双启动设置。
  • 需要直接在硬件上运行 Windows。
    • 游戏的图形性能(并且没有能够通过 2x GPU 进行 PCI 直通的主板/设置等)。
    • 过于敏感的音频应用程序(例如 Skype for Business)通过虚拟化音频设备运行不佳。
  • 想要利用虚拟机的便利来运行其他要求不高的 Windows 应用程序,如 MS Office 等。

有许多注意事项/解决方法:

  • 我费了好大劲才让 Windows 保持激活状态,因为它显然将许可证与硬件绑定在一起。添加主板/BIOS 序列号、确切的 CPU 型号和存储设备序列号似乎有所帮助。
  • 添加 udev 规则以使 Linux/Nautilus/Gnome 文件管理器忽略 Windows 分区。
  • 由于担心(担心 Windows 更新可能会影响 grub/boot 设置),我没有与 VM 共享我的整个原始驱动器。相反:
    • 我将分区表(GPT)和 EFI 分区克隆到文件中,并且还创建了一个伪造的设备映像文件结束。
    • 使用环回驱动程序将克隆的图像视为设备
    • 通过 mdadm linear setup 使用 MD(多设备)驱动程序将所有需要的部件链接在一起,作为 VM 的混合映像和原始设备。例如md0从 构建<GPT table clone image/loopback> + <recovery raw> + <EFI clone image/loopback> + <windows system raw> + <end of device GPT backup table/loopback>
    • 根据需要使用 gdisk 和 testdisk 来纠正/调整分区表。
    • 1803 Windows 10 更新增加了一个额外的分区,我必须进行调整!安装 Windows 10 四月更新后出现新分区。需要再次更正...

我在第二个系统上使用了类似的设置,但通过拥有两个独立的存储设备(一个用于 Linux,另一个用于 Windows),我的生活变得更加轻松。

相关内容