内核与 HYP 之间的内部 ABI

此文件记录了当 Linux 作为虚拟机监控程序(例如 KVM)运行时,Linux 内核和虚拟机监控程序层之间的交互。它不包括当内核作为访客(在 Xen、KVM 或任何其他虚拟机监控程序下)运行时内核与虚拟机监控程序的交互,或当内核用作主机时任何特定于虚拟机监控程序的交互。

注意:KVM/arm 已从内核中删除。但是,此处描述的 API 仍然有效,因为它允许内核在以 HYP 启动时进行 kexec。如果需要,其他虚拟机监控程序也可以使用它。

在 arm 和 arm64(没有 VHE)上,内核不在虚拟机监控程序模式下运行,但仍然需要与之交互,从而允许安装或拆除内置的虚拟机监控程序。

为了实现这一点,内核必须在 HYP (arm) 或 EL2 (arm64) 处启动,允许它在降级到 SVC/EL1 之前安装一组存根。这些存根可以通过使用“hvc #0”指令访问,并且仅在单个 CPU 上起作用。

除非另有说明,任何内置的虚拟机监控程序都必须实现这些功能(请参阅 arch/arm{,64}/include/asm/virt.h)

  • r0/x0 = HVC_SET_VECTORS
    r1/x1 = vectors
    

    将 HVBAR/VBAR_EL2 设置为“vectors”以启用虚拟机监控程序。“vectors”必须是物理地址,并遵守架构的对齐要求。仅由初始存根实现,而不是由 Linux 虚拟机监控程序实现。

  • r0/x0 = HVC_RESET_VECTORS
    

    关闭 HYP/EL2 MMU,并将 HVBAR/VBAR_EL2 重置为初始存根的异常向量值。这有效地禁用了现有的虚拟机监控程序。

  • r0/x0 = HVC_SOFT_RESTART
    r1/x1 = restart address
    x2 = x0's value when entering the next payload (arm64)
    x3 = x1's value when entering the next payload (arm64)
    x4 = x2's value when entering the next payload (arm64)
    

    屏蔽所有异常,禁用 MMU,清除 I+D 位,将参数移动到位(仅限 arm64),并在 HYP/EL2 处跳转到重启地址。此系统调用不应返回其调用者。

  • x0 = HVC_FINALISE_EL2 (arm64 only)
    

    根据命令行选项完成 EL2 的配置,包括尝试通过启用 VHE 模式将内核的异常级别从 EL1 升级到 EL2。这取决于 CPU 是否支持 VHE,EL2 MMU 是否关闭,以及 VHE 是否未被任何其他方式(例如,命令行选项)禁用。

r0/x0 的任何其他值都会触发虚拟机监控程序特定的处理,此处没有记录。

存根系统调用的返回值由 r0/x0 保存,成功时为 0,错误时为 HVC_STUB_ERR。存根系统调用可以破坏任何调用者保存的寄存器(arm64 上的 x0-x18,arm 上的 r0-r3 和 ip)。因此,建议使用函数调用来执行系统调用。