Perf

Perf 事件属性

作者:

Andrew Murray <andrew.murray@arm.com>

日期:

2019-03-06

exclude_user

此属性排除用户空间。

用户空间总是在 EL0 运行,因此此属性将排除 EL0。

exclude_kernel

此属性排除内核。

内核在有 VHE 的 EL2 以及没有 VHE 的 EL1 运行。客户机内核总是在 EL1 运行。

对于主机,此属性将排除 EL1,并在 VHE 系统上额外排除 EL2。

对于客户机,此属性将排除 EL1。请注意,EL2 永远不会在客户机中被计数。

exclude_hv

此属性排除 Hypervisor。

对于 VHE 主机,此属性将被忽略,因为我们认为主机内核就是 Hypervisor。

对于非 VHE 主机,此属性将排除 EL2,因为我们认为 Hypervisor 是任何在 EL2 运行的代码,主要用于客户机/主机转换。

对于客户机,此属性无效。请注意,EL2 永远不会在客户机中被计数。

exclude_host / exclude_guest

这些属性分别排除 KVM 主机和客户机。

KVM 主机可能在 EL0(用户空间)、EL1(非 VHE 内核)和 EL2(VHE 内核或非 VHE Hypervisor)运行。

KVM 客户机可能在 EL0(用户空间)和 EL1(内核)运行。

由于主机和客户机之间的异常级别重叠,我们不能完全依赖 PMU 的硬件异常过滤 - 因此我们必须在进入和退出客户机时启用/禁用计数。这在 VHE 和非 VHE 系统上执行的方式不同。

对于非 VHE 系统,我们为 exclude_host 排除 EL2 - 在进入和退出客户机时,我们根据 exclude_host 和 exclude_guest 属性适当地禁用/启用事件。

对于 VHE 系统,我们为 exclude_guest 排除 EL1,并为 exclude_host 排除 EL0 和 EL2。在进入和退出客户机时,我们根据 exclude_host 和 exclude_guest 属性适当地修改事件以包含/排除 EL0。

上述声明也适用于在非 VHE 客户机中使用这些属性的情况,但是请注意,EL2 永远不会在客户机中被计数。

准确性

在非 VHE 主机上,我们会在 EL2 的主机/客户机转换的进入/退出时启用/禁用计数器 - 但是,在启用/禁用计数器与进入/退出客户机之间存在一段时间。 通过为 exclude_host 过滤掉 EL2,我们可以消除计数器在客户机进入/退出边界上计数主机事件的情况(当计数客户机事件时)。 但是,当使用 !exclude_hv 时,在客户机进入/退出时存在一个小的中断窗口,在此期间主机事件不会被捕获。

在 VHE 系统上,不存在中断窗口。

Perf 用户空间 PMU 硬件计数器访问

概述

perf 用户空间工具依赖于 PMU 来监视事件。 它在硬件计数器上提供了一个抽象层,因为底层实现是 CPU 相关的。 Arm64 允许用户空间工具直接访问存储硬件计数器值的寄存器。

这专门针对自监控任务,以便通过直接访问寄存器而不必通过内核来减少开销。

操作方法

重点是 armv8 PMUv3,它确保已启用对 pmu 寄存器的访问,并且用户空间可以访问相关信息以便使用它们。

为了访问硬件计数器,必须首先启用全局 sysctl kernel/perf_user_access

echo 1 > /proc/sys/kernel/perf_user_access

必须使用 perf 工具接口打开事件,并设置 config1:1 attr 位:sys_perf_event_open 系统调用返回一个 fd,随后可以将其与 mmap 系统调用一起使用,以便检索包含有关事件信息的内存页。 PMU 驱动程序使用此页向用户公开硬件计数器的索引和其他必要数据。 使用此索引允许用户使用 mrs 指令访问 PMU 寄存器。 只有在序列锁未更改时,对 PMU 寄存器的访问才有效。 特别是,每次更改序列锁时,PMSELR_EL0 寄存器都会归零。

libperf 中使用 perf_evsel__mmap() 和 perf_evsel__read() 函数支持用户空间访问。 有关示例,请参见 tools/lib/perf/tests/test-evsel.c

关于异构系统

在诸如 big.LITTLE 之类的异构系统上,只有在将任务绑定到同构内核子集并通过指定 “type” 属性打开相应的 PMU 实例时,才能启用用户空间 PMU 计数器访问。 在这种情况下不支持使用通用事件类型。

请查看 tools/perf/arch/arm64/tests/user-events.c 以获取示例。 可以使用 perf 工具运行它,以检查从用户空间对寄存器的访问是否正确。

perf test -v user

关于链接事件和计数器大小

用户可以请求一个 32 位 (config1:0 == 0) 或 64 位 (config1:0 == 1) 计数器以及用户空间访问。 如果请求 64 位计数器并且硬件不支持 64 位计数器,则 sys_perf_event_open 系统调用将失败。 链接事件不支持与用户空间计数器访问结合使用。 如果在具有 64 位计数器的硬件上请求 32 位计数器,则用户空间必须将从计数器读取的高 32 位视为 UNKNOWN。 用户页面中的 “pmc_width” 字段将指示计数器的有效宽度,应使用该字段根据需要屏蔽高位。

事件计数阈值

概述

FEAT_PMUv3_TH (Armv8.8) 允许 PMU 计数器仅在事件的计数满足指定的阈值条件时才递增。 例如,如果 threshold_compare 设置为 2(“大于或等于”),并且阈值设置为 2,则 PMU 计数器现在仅在事件先前会在单个处理器周期内将 PMU 计数器递增 2 或更多时才递增。

要在通过阈值条件后递增 1,而不是该周期中的事件数,请将 “threshold_count” 选项添加到命令行。

操作方法

这些是用于控制该功能的参数

参数

描述

threshold

用于对事件进行阈值化的值。 值为 0 表示禁用阈值化,其他参数无效。

threshold_compare

要使用的比较函数,支持以下值

0:不等于
1:等于
2:大于或等于
3:小于

threshold_count

如果设置了此值,则在通过阈值条件后按 1 计数,而不是此周期中事件的值。

可以为每个事件提供 threshold、threshold_compare 和 threshold_count 值,例如

perf stat -e stall_slot/threshold=2,threshold_compare=2/ \
          -e dtlb_walk/threshold=10,threshold_compare=3,threshold_count/

在此示例中,stall_slot 事件将在每次发生 2 个或更多 stall 的周期中计数 2 或更多。 dtlb_walk 将在每次 dtlb walk 数量小于 10 的周期中计数 1。

可以从每个 PMU 的 caps 读取支持的最大阈值,例如

cat /sys/bus/event_source/devices/armv8_pmuv3/caps/threshold_max

0x000000ff

如果给定的值高于此值,则打开事件将导致错误。 可能的最高最大值为 4095,因为 threshold 的 config 字段限制为 12 位,并且 Perf 工具将拒绝解析更高的值。

如果 PMU 不支持 FEAT_PMUv3_TH,则 threshold_max 将读取为 0,并且尝试设置阈值也会导致错误。 即使主机在具有该功能的硬件上运行,threshold_max 也将在 aarch32 客户机上读取为 0。