AArch64 Linux 中的活动监视器单元 (AMU) 扩展

作者:Ionela Voinescu <ionela.voinescu@arm.com>

日期:2019-09-10

本文档简要描述了 AArch64 Linux 中活动监视器单元的支持情况。

架构概述

活动监视器扩展是 ARMv8.4 CPU 架构引入的可选扩展。

活动监视器单元在每个 CPU 中实现,提供用于系统管理的性能计数器。AMU 扩展提供了一个系统寄存器接口来访问计数器寄存器,并支持可选的外部内存映射接口。

活动监视器架构的第 1 版实现了一个由四个固定且架构定义的 64 位事件计数器组成的计数器组。

  • CPU 周期计数器:以 CPU 的频率递增。

  • 常量计数器:以系统时钟的固定频率递增。

  • 指令已执行:随着每次架构执行的指令而递增。

  • 内存停顿周期:计算时钟域内最后一级缓存中未命中导致的指令分派停顿周期。

在 WFI 或 WFE 中时,这些计数器不会递增。

活动监视器架构提供了多达 16 个架构事件计数器的空间。该架构的未来版本可能会使用此空间来实现额外的架构事件计数器。

此外,第 1 版还实现了一个由最多 16 个辅助 64 位事件计数器组成的计数器组。

冷复位时,所有计数器都会重置为 0。

基本支持

内核可以安全地运行混合使用支持和不支持活动监视器扩展的 CPU。因此,当选择 CONFIG_ARM64_AMU_EXTN 时,我们会无条件启用该功能,以允许任何后期 CPU(辅助或热插拔)检测和使用该功能。

当在 CPU 上检测到该功能时,我们会标记该功能的可用性,但这并不能保证计数器的正确功能,仅保证扩展的存在。

固件(在较高异常级别运行的代码,例如 arm-tf)需要提供以下支持:

  • 允许较低异常级别(EL2 和 EL1)访问 AMU 寄存器。

  • 启用计数器。如果未启用,这些计数器将读取为 0。

  • 在 CPU 从“关闭”电源状态启动/恢复之前/之后保存/恢复计数器。

当使用启用了此功能的内核但在启动时使用了损坏的固件时,用户在访问计数器寄存器时可能会遇到崩溃或死锁。即使没有观察到这些症状,寄存器读取返回的值也可能无法正确反映实际情况。最常见的是,计数器将读取为 0,表示它们未启用。

如果固件中未提供适当的支持,最好禁用 CONFIG_ARM64_AMU_EXTN。请注意,出于安全原因,这不会绕过 AMUSERENR_EL0 的设置以捕获从 EL0(用户空间)到 EL1(内核)的访问。因此,固件仍应确保对 AMU 寄存器的访问不会在 EL2/EL3 中被捕获。

AMUv1 的固定计数器可以通过以下系统寄存器定义访问:

  • SYS_AMEVCNTR0_CORE_EL0

  • SYS_AMEVCNTR0_CONST_EL0

  • SYS_AMEVCNTR0_INST_RET_EL0

  • SYS_AMEVCNTR0_MEM_STALL_EL0

可以使用 SYS_AMEVCNTR1_EL0(n) 访问辅助平台特定的计数器,其中 n 是 0 到 15 之间的值。

详细信息可以在以下位置找到:arch/arm64/include/asm/sysreg.h。

用户空间访问

目前,由于以下原因,禁用从用户空间对 AMU 寄存器的访问:

  • 安全原因:它们可能会暴露有关在安全模式下执行的代码的信息。

  • 目的:AMU 计数器用于系统管理。

此外,用户空间无法看到该功能的存在。

虚拟化

目前,由于以下原因,禁用从 KVM 客户机侧的用户空间 (EL0) 和内核空间 (EL1) 的访问:

  • 安全原因:它们可能会暴露有关其他客户机或主机执行的代码的信息。

任何访问 AMU 寄存器的尝试都会导致将 UNDEFINED 异常注入到客户机中。