Perf¶
Perf 事件属性¶
- 作者:
Andrew Murray <andrew.murray@arm.com>
- 日期:
2019-03-06
exclude_user¶
此属性排除用户空间。
用户空间始终运行在 EL0,因此此属性将排除 EL0。
exclude_kernel¶
此属性排除内核。
在启用了 VHE 的系统中,内核运行在 EL2;未启用 VHE 时运行在 EL1。客户机(Guest)内核总是运行在 EL1。
对于宿主机(host),此属性将排除 EL1,如果在 VHE 系统上,还会额外排除 EL2。
对于客户机,此属性将排除 EL1。请注意,在客户机内部永远不会对 EL2 进行计数。
exclude_hv¶
此属性排除虚拟机监控程序(hypervisor)。
对于 VHE 宿主机,此属性会被忽略,因为我们将宿主机内核视为虚拟机监控程序。
对于非 VHE 宿主机,此属性将排除 EL2,因为我们将任何运行在 EL2 上的代码(主要用于客户机/宿主机切换)视为虚拟机监控程序。
对于客户机,此属性没有效果。请注意,在客户机内部永远不会对 EL2 进行计数。
exclude_host / exclude_guest¶
这些属性分别排除 KVM 宿主机和客户机。
KVM 宿主机可以运行在 EL0(用户空间)、EL1(非 VHE 内核)和 EL2(VHE 内核或非 VHE 虚拟机监控程序)。
KVM 客户机可以运行在 EL0(用户空间)和 EL1(内核)。
由于宿主机和客户机之间的异常级别(exception level)存在重叠,我们不能完全依赖 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 时,在客户机进入/退出处会有一个小的盲区窗口(blackout window),在此期间无法捕获宿主机事件。
在 VHE 系统上,没有盲区窗口。
Perf 用户空间 PMU 硬件计数器访问¶
概述¶
perf 用户空间工具依赖 PMU 来监视事件。由于底层实现取决于 CPU,它为硬件计数器提供了一个抽象层。Arm64 允许用户空间工具直接访问存储硬件计数器值的寄存器。
这专门针对自监视(self-monitoring)任务,旨在通过直接访问寄存器而不通过内核来减少开销。
如何使用¶
重点放在 armv8 PMUv3 上,它确保启用对 pmu 寄存器的访问,并且用户空间能够访问相关信息以使用它们。
为了访问硬件计数器,必须首先启用全局 sysctl kernel/perf_user_access
echo 1 > /proc/sys/kernel/perf_user_access
必须使用设置了 config1:1 属性位的 perf 工具接口打开事件:sys_perf_event_open 系统调用返回一个文件描述符(fd),随后可将其与 mmap 系统调用一起使用,以检索包含事件相关信息的内存页。PMU 驱动程序使用此页面向用户公开硬件计数器的索引和其他必要数据。使用此索引可以使用户能够使用 mrs 指令访问 PMU 寄存器。对 PMU 寄存器的访问仅在序列锁(sequence lock)未改变时有效。特别是,每次序列锁改变时,PMSELR_EL0 寄存器都会被清零。
libperf 中使用 perf_evsel__mmap() 和 perf_evsel__read() 函数支持用户空间访问。有关示例,请参见 tools/lib/perf/tests/test-evsel.c。
关于异构系统¶
在诸如 big.LITTLE 等异构系统上,只有当任务被绑定(pinned)到同构的核心子集并且通过指定“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 计数器递增 2 或更多时,PMU 计数器才会递增。
要在通过阈值条件后递增 1(而不是该周期的事件数量),请在命令行中添加 ‘threshold_count’ 选项。
如何使用¶
以下是用于控制该功能的参数
参数 |
描述 |
|---|---|
阈值 |
用于对事件进行阈值限制的值。值为 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 遍历次数少于 10 的每个周期上按 1 进行计数。
可以从每个 PMU 的 caps 中读取支持的最大阈值,例如
cat /sys/bus/event_source/devices/armv8_pmuv3/caps/threshold_max
0x000000ff
如果给定高于此值的数值,则打开事件将导致错误。最高可能的最大值为 4095,因为阈值的配置字段限制为 12 位,并且 Perf 工具将拒绝解析更高的值。
如果 PMU 不支持 FEAT_PMUv3_TH,则 threshold_max 将读取为 0,并且尝试设置阈值也将导致错误。在 aarch32 客户机上,threshold_max 也将读取为 0,即使宿主机运行在具备该功能的硬件上也是如此。