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 或热插拔 CPU)检测并使用该特性。

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

需要固件(运行在更高异常级别上的代码,例如 arm-tf)支持来完成以下工作:

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

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

  • 在 CPU 进入或从“关闭(off)”电源状态唤醒之前/之后,保存/恢复计数器。

当使用启用了此特性但引导时带有缺陷固件的内核时,用户在访问计数器寄存器时可能会遇到内核崩溃或死锁。即使没有观察到这些症状,寄存器读取返回的值也可能无法正确反映实际情况。最常见的情况是,计数器读取的值为 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 异常。