ARM 固件伪寄存器接口

KVM 处理 guest 请求的 hypercall 服务。 ARM 规范或 KVM(作为供应商服务)会定期提供新的 hypercall 服务,如果它们从虚拟化的角度来看是有意义的。

这意味着在两个不同版本的 KVM 上启动的 guest 可以观察到两个不同的“固件”版本。如果给定的 guest 与特定版本的 hypercall 服务相关联,或者如果迁移导致不同的版本突然暴露给毫无戒心的 guest,这可能会导致问题。

为了解决这种情况,KVM 公开了一组“固件伪寄存器”,可以使用 GET/SET_ONE_REG 接口来操作这些寄存器。 这些寄存器可以由用户空间保存/恢复,并根据需要设置为方便的值。

定义了以下寄存器

  • KVM_REG_ARM_PSCI_VERSION

    KVM 实现了 PSCI(电源状态协调接口)规范,以便为 guest 提供诸如 CPU 开/关、重置和断电等服务。

    • 只有当 vcpu 具有 KVM_ARM_VCPU_PSCI_0_2 功能集(因此已经初始化)时才有效

    • 返回 GET_ONE_REG 上的当前 PSCI 版本(默认为 KVM 实现的且与 v0.2 兼容的最高 PSCI 版本)

    • 允许使用 SET_ONE_REG 设置 KVM 实现的且与 v0.2 兼容的任何 PSCI 版本

    • 影响整个 VM(即使寄存器视图是每个 vcpu 的)

  • KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1

    保存固件支持的状态,以缓解 CVE-2017-5715,由 KVM 通过 HVC 调用提供给 guest。此解决方法在 [1] 中 SMCCC_ARCH_WORKAROUND_1 下进行了描述。

    接受的值为

    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL

    KVM 不提供针对此解决方法的固件支持。guest 的缓解状态未知。

    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL

    此解决方法 HVC 调用可用于 guest,并且是缓解所必需的。

    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED

    此解决方法 HVC 调用可用于 guest,但在此 VCPU 上不需要。

  • KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2

    保存固件支持的状态,以缓解 CVE-2018-3639,由 KVM 通过 HVC 调用提供给 guest。此解决方法在 [1] 中的 SMCCC_ARCH_WORKAROUND_2 下进行了描述。

    接受的值为

    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL

    没有可用的解决方法。 KVM 不提供针对此解决方法的固件支持。

    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN

    此解决方法的状态未知。 KVM 不提供针对此解决方法的固件支持。

    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL

    此解决方法可用,并且可以由 vCPU 禁用。 如果设置了 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED,则它对该 vCPU 处于活动状态。

    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED

    此解决方法始终在此 vCPU 上处于活动状态,或者不需要。

位图功能固件寄存器

与上述寄存器相反,以下寄存器以功能位图的形式向用户空间公开 hypercall 服务。 此位图被转换为可用于 guest 的服务。 每个服务调用所有者定义了一个寄存器,可以通过 GET/SET_ONE_REG 接口进行访问。

默认情况下,这些寄存器设置为受支持功能的上限。 这样,用户空间就可以通过 GET_ONE_REG 发现所有可用的 hypercall 服务。 用户空间可以通过 SET_ONE_REG 将所需的位图写回。 未触及的寄存器的功能(可能是因为用户空间不知道)将按原样暴露给 guest。

请注意,一旦任何 vCPU 至少运行过一次,KVM 将不再允许用户空间配置寄存器。 而是返回 -EBUSY。

伪固件位图寄存器如下

  • KVM_REG_ARM_STD_BMAP

    控制 ARM 标准安全服务调用的位图。

    接受以下位

    Bit-0: KVM_REG_ARM_STD_BIT_TRNG_V1_0

    该位表示 ARM 真随机数生成器 (TRNG) 规范 v1.0 下提供的服务,ARM DEN0098。

  • KVM_REG_ARM_STD_HYP_BMAP

    控制 ARM 标准 Hypervisor 服务调用的位图。

    接受以下位

    Bit-0: KVM_REG_ARM_STD_HYP_BIT_PV_TIME

    该位表示由 ARM DEN0057A 表示的半虚拟化时间服务。

  • KVM_REG_ARM_VENDOR_HYP_BMAP

    控制供应商特定的 Hypervisor 服务调用 [0-63] 的位图。

    接受以下位

    Bit-0: KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT

    该位表示 ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID 和 ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID 函数 ID。

    Bit-1: KVM_REG_ARM_VENDOR_HYP_BIT_PTP

    该位表示精确时间协议 KVM 服务。

  • KVM_REG_ARM_VENDOR_HYP_BMAP_2

    控制供应商特定的 Hypervisor 服务调用 [64-127] 的位图。

    接受以下位

    Bit-0: KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_VER

    这表示 ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID 函数 ID。 这将被重置为 0。

    Bit-1: KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_CPUS

    这表示 ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID 函数 ID。 这将被重置为 0。

错误

-ENOENT

访问了未知寄存器。

-EBUSY

在 VM 启动后尝试“写入”寄存器。

-EINVAL

写入寄存器的位图无效。