直接从汇编语言访问性能计数器的 ARMv7 指令

ARMv7 instructions to access performance counters directly from assembly language

我想收集性能计数器信息,例如ARMv7 处理器的分支预测错误。我正在做一个项目,我需要能够计算错误预测 但是我使用的设备(我的 Chromebook)没有正确的 Linux 内核来使用 'perf' 实用程序。我无法在这台旧机器上安装支持 perf 的 Linux。本来可以支持的项目似乎在 Internet 上不可用,因为它们太旧了。我知道有一种方法可以使用 ARMv7 指令直接从汇编语言访问性能计数器,但我不确定该怎么做。

有一些直接在 ARM 上使用 PMU 性能计数器的示例,例如

armv7: http://neocontra.blogspot.com/2013/05/user-mode-performance-counters-for.html

armv8: http://zhiyisun.github.io/2016/03/02/How-to-Use-Performance-Monitor-Unit-(PMU)-of-64-bit-ARMv8-A-in-Linux.html

So the first thing is to create a kernel module to enable user-mode access to PMU counters. Below is the code to set PMU register PMUSERENR_EL0 to enable user-mode access.

/*Enable user-mode access to counters. */
asm volatile("msr pmuserenr_el0, %0" : : "r"((u64)ARMV8_PMUSERENR_EN_EL0|ARMV8_PMUSERENR_ER|ARMV8_PMUSERENR_CR));

/*   Performance Monitors Count Enable Set register bit 30:0 disable, 31 enable. Can also enable other event counters here. */ 
asm volatile("msr pmcntenset_el0, %0" : : "r" (ARMV8_PMCNTENSET_EL0_ENABLE));

/* Enable counters */
u64 val=0;
asm volatile("mrs %0, pmcr_el0" : "=r" (val));
asm volatile("msr pmcr_el0, %0" : : "r" (val|ARMV8_PMCR_E));

但是性能计数器是系统的特权部分,默认情况下它们只能从内核模式访问。您不能只在用户 space 代码中使用汇编指令来使用它们,您得到的唯一结果是 SIGSEGV 或其他权限被拒绝的变体。要启用从 user-space 的访问,一些工作应该在内核模式下完成。它可以是任何现有的 PMU 驱动程序:perf 或 oprofile(旧的 pmu 访问工具),或者它可以是一些自定义内核模块,它将允许用户 space 访问 PMU 寄存器。但是要编译你的模块,你仍然需要你的内核的大部分内核开发基础设施(我希望标准的 chromebook 内核没有内核包含 "kbuild" 来进行模块构建,并且这个内核可能不接受标准配置中的未签名模块)。

你能做什么:

  • 使用另一台机器,比您过时的 chromebook 更新。你的项目可能有一些远程访问的机器,你可以尝试购买一些小型流行的linux(如raspberry pi 3/4)的ARM单板机。那个流行的主板将有更新的 arm cpu 内核,并且它将有 ubuntu 或 debian
  • 检查 oprofile 子系统,它可能在您的内核中启用。 Oprofile tools 比 perf 旧,但也可以访问 PMU 计数器。
  • 重新编译 linux 内核并启用 perf_events 子系统。您只需要正确的内核,它将在您的 chromebook 上启动,以及任何编译器从 https://mirrors.edge.kernel.org/pub/linux/kernel/tools/perf/ 重建 perf out-of-tree(使用任何版本的 perf)。或者直接使用perf_event_open系统调用
  • 检查 /lib/modules/`uname -r`/build 目录。如果存在,您可以尝试构建自定义内核模块以启用 user-space 直接访问

pmcr_el0 上的 TRM 和其他 PMU 寄存器:https://developer.arm.com/documentation/100442/0100/debug-registers/aarch64-pmu-registers/pmcr-el0--performance-monitors-control-register--el0 https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/pmcr_el0 https://developer.arm.com/docs/ddi0595/h/aarch32-system-registers/pmccntr https://developer.arm.com/documentation/ddi0535/c/performance-monitoring-unit and some overview https://people.inf.ethz.ch/markusp/teaching/263-2300-ETH-spring14/slides/08-perfcounters.pdf