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