概述¶
Linux 内核包含各种代码,用于作为 Microsoft Hyper-V 虚拟机管理程序上的完全启动的来宾运行。Hyper-V 主要由裸机虚拟机管理程序以及在父分区中运行的虚拟机管理服务组成(大致相当于 KVM 和 QEMU)。来宾虚拟机在子分区中运行。在本文档中,对 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,并将其报告为热添加 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 是跨架构的通用底层代码,必须内置。