概述¶
Linux 内核包含各种代码,用于在 Microsoft 的 Hyper-V 虚拟机监控程序上作为完全启用的来宾运行。Hyper-V 主要由裸机虚拟机监控程序以及在父分区中运行的虚拟机管理服务组成(大致相当于 KVM 和 QEMU 等)。来宾 VM 在子分区中运行。 在本文档中,对 Hyper-V 的引用通常包括虚拟机监控程序和 VMM 服务,而不区分哪些功能由哪个组件提供。
Hyper-V 在 x86/x64 和 arm64 架构上运行,并且两种架构都支持 Linux 来宾。除非另有说明,否则 Hyper-V 的功能和行为在两种架构上通常是相同的。
Linux 来宾与 Hyper-V 的通信¶
Linux 来宾通过四种不同的方式与 Hyper-V 通信
隐式陷阱:按照 x86/x64 或 arm64 架构的定义,某些来宾操作会陷阱到 Hyper-V。Hyper-V 模拟该操作并将控制权返回给来宾。这种行为通常对 Linux 内核不可见。
显式超调用:Linux 对 Hyper-V 进行显式函数调用,传递参数。Hyper-V 执行请求的操作并将控制权返回给调用者。参数在处理器寄存器中或 Linux 来宾和 Hyper-V 之间共享的内存中传递。在 x86/x64 上,超调用使用 Hyper-V 特定的调用序列。在 arm64 上,超调用使用 ARM 标准 SMCCC 调用序列。
合成寄存器访问:Hyper-V 实现了各种合成寄存器。在 x86/x64 上,这些寄存器以 MSR 的形式出现在来宾中,并且 Linux 内核可以使用 x86/x64 架构定义的正常机制来读取或写入这些 MSR。在 arm64 上,必须使用显式超调用来访问这些合成寄存器。
VMBus:VMBus 是一个更高层次的软件构造,它建立在其他 3 个机制之上。它是 Hyper-V 主机和 Linux 来宾之间的消息传递接口。它使用 Hyper-V 和来宾之间共享的内存,以及各种信令机制。
前三种通信机制记录在 Hyper-V 顶层功能规范 (TLFS) 中。TLFS 描述了 Hyper-V 的一般功能,并提供了有关超调用和合成寄存器的详细信息。TLFS 目前仅针对 x86/x64 架构编写。
VMBus 没有记录。本文档提供了 VMBus 的高级概述及其工作方式,但详细信息只能从代码中辨别出来。
CPU 管理¶
Hyper-V 无法从正在运行的 VM 热添加或热删除 CPU。 但是,Windows Server 2019 Hyper-V 及更早版本可能会为来宾提供 ACPI 表,指示的 CPU 数量多于 VM 中实际存在的 CPU 数量。 像往常一样,Linux 将这些额外的 CPU 视为潜在的热添加 CPU,并将其报告为这样,即使 Hyper-V 永远不会实际热添加它们。 从 Windows Server 2022 Hyper-V 开始,ACPI 表仅反映 VM 中实际存在的 CPU,因此 Linux 不会报告任何热添加 CPU。
可以使用正常的 Linux 机制将 Linux 来宾 CPU 脱机,前提是没有 VMBus 通道中断分配给该 CPU。 有关如何重新分配 VMBus 通道中断以允许将 CPU 脱机的更多详细信息,请参阅有关 VMBus 中断的部分。
32 位和 64 位¶
在 x86/x64 上,Hyper-V 支持 32 位和 64 位来宾,并且 Linux 将构建并以任一版本运行。 虽然 32 位版本预计可以工作,但很少使用,并且可能遭受未检测到的回归。
在 arm64 上,Hyper-V 仅支持 64 位来宾。
字节顺序¶
Hyper-V 和来宾 VM 之间的所有通信都使用小端格式,无论是在 x86/x64 还是 arm64 上。 Hyper-V 不支持 arm64 上的大端格式,并且 Linux 代码在访问与 Hyper-V 共享的数据时不使用字节顺序宏。
版本控制¶
当前的 Linux 内核可以与 Windows Server 2012 Hyper-V 的旧版 Hyper-V 正常运行。 对在 Windows Server 2008/2008 R2 的原始 Hyper-V 版本上运行的支持已被删除。
Hyper-V 上的 Linux 来宾会在 dmesg 中输出其运行的 Hyper-V 版本。 此版本采用 Windows 内部版本号的形式,仅用于显示目的。 Linux 代码不会在运行时测试此版本号,以确定可用的特性和功能。 Hyper-V 通过 Hyper-V 提供给来宾的合成 MSR 中的标志指示特性/功能可用性,并且来宾代码会测试这些标志。
VMBus 有其自己的协议版本,该版本在来宾到 Hyper-V 的初始 VMBus 连接期间协商。 此版本号也在启动期间输出到 dmesg。 代码中的一些位置会检查此版本号,以确定是否存在特定功能。
此外,VMBus 上的每个合成设备也有一个协议版本,该版本与 VMBus 协议版本分开。 这些合成设备的设备驱动程序通常会协商设备协议版本,并且可能会测试该协议版本以确定是否存在特定设备功能。
代码打包¶
与 Hyper-V 相关的代码出现在 Linux 内核代码树中的三个主要区域
drivers/hv
arch/x86/hyperv 和 arch/arm64/hyperv
各个设备驱动程序区域,例如 drivers/scsi、drivers/net、drivers/clocksource 等。
一些杂项文件出现在其他位置。 请参阅 MAINTAINERS 文件中“Hyper-V/Azure 核心和驱动程序”和“适用于 HyperV 合成视频设备的 DRM 驱动程序”下的完整列表。
只有在设置了 CONFIG_HYPERV 时,才会构建 #1 和 #2 中的代码。 同样,只有在设置了 CONFIG_HYPERV 时,才会构建大多数与 Hyper-V 相关的驱动程序的代码。
#1 和 #3 中的大多数与 Hyper-V 相关的代码都可以构建为模块。 #2 中的特定于架构的代码必须内置。 此外,drivers/hv/hv_common.c 是跨架构的通用底层代码,必须内置。