Application Note: Apple M1 和虚拟机
都在说各种 M1 的使用体验,我来说点别的(这机器拿到之后本来就打算是纯折腾用的)。本文基本上就是个 Application Note,供打算写 VM 的人做参考。
macOS on Apple Silicon 有两个虚拟化的框架,一个是 high-level 的 (Virtualization.Framework),一个是 low-level 的 (Hypervisor.Framework)。前者暴露了一系列 VirtIO 设备和经过包装的 Bootloader,后者提供了细粒度的虚拟硬件控制,需要自己处理 vCPU vmexit/interrupt/timer 和内存的映射。
在 Apple Silicon 上调用这两个框架需要合适的 entitlements (com.apple.security.hypervisor
,也有可能需要 com.apple.vm.networking
)
Virtualization.Framework
这里有一个非常简单的 SimpleVM 的实现。
Virtualization.Framework 的使用方法非常简单:
- 创建好简单的 VM 配置
- 提供一个解压后的 arm64 Linux Kernel (not Image.gz) 并把它喂给 VZLinuxBootloader
- 开机,x0 会提供 Device Tree 的指针,没有 ACPI 支持
Virtualization.Framework 的虚拟了以下 vCPU 和外设:
- ARMv8.3 CPU (带一部分 v8.4 扩展), GICv3
- ARM PMUv3,但是 Device Tree 没有暴露
- 4KB/16KB/64KB Page Table
- PSCI v1.1 via HVC call
- PCIe ECAM Root Bridge
- VirtIO {Block Device, Network, Console, Memory Balloon}
Virtualization.Framework 的私有类里面还暗示了 ARM PL011 UART, 16550 UART, FrameBuffer, Virtual USB, EFI Bootloader 之类的存在,但是目前它们是坏的,不要尝试了。
Red Hat 的人跟我说他们发现 Virtualization.Framework 存在一些潜在的内存问题,所以可能它还需要一段时间来稳定一下
Hypervisor.Framework
提供了细粒度的硬件控制。一些细节如下:
- 每个 vCPU 对应一个线程,尽可能不要在 Dispatch thread 上开 vCPU,有可能会跑飞
- 可以操作 EL1 的常规和系统寄存器。默认 vCPU 所有寄存器是 0 (其实这不是个好主意),所以没有配置 CPSR/PState 的话 vCPU 会从 EL0 出生
- 设置 EL1 的 PC 来决定 vCPU 的入口点
- 尽管 A14/M1 有 4KB 页支持,host 程序在分配 aligned page 并映射到虚拟机的时候依旧需要以 16KB 为对齐单位。虚拟机自己可以用 4KB 页
- 虽然 A14/M1 没有实现 EL3,但是 EL2 可以 trap 来自 EL1 的 smc call 。注意返回的时候需要
eret_el1 += 4
(trapped SMC 不会自动把 eret 设置到下一条指令,和 HVC 不同)。在虚拟机的 vmexit handler 里直接设置 EL1 的 PC 即可。 - Interrupt Line 需要人工处理,GIC 需要在 host 里实现
- Debug Instruction / Register Access 不默认 trap,需要人工设置
hv_vcpu_set_trap_debug_exceptions
- VmExit 有 Synchronous Exception 和 Timer Event 。Synch Exception 需要处理的内容可以参见 ARM 文档的
esr_el2
里的ec
部分,一般来说只需要处理一个子集 (trapped register, stage 2 translation, hvc/smc, MMIO, debug): https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/esr_el2 ; Timer 可以看 Apple 文档
一个 Hypervisor.Framework 使用的玩具例子可以看这里: https://gist.github.com/imbushuo/51b09e61ecd7b7ac063853ad65cedf34
Misc
Qemu + HVF 支持有人在做了,另外 Windows 早就有人偷偷跑过了