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 异常注入到客户机中。