使用PMU计数ARM

时间:2019-05-15 14:19:23

标签: arm

我正在尝试从ARM用户空间中使用PMU(具体来说,使用PMCCNTR来确定每个usec的滴答声)。我有一个运行arm32位用户空间应用程序的arm64内核。

我创建了一个LKM来强制PMUSERENR.EN位被打开,这可以工作。然后,我从用户空间运行了一个测试程序:

asm volatile ("mrc p15, 0, %[en], c9, c14, 0" 
      : [en] "=r" (pmuserenr));
printf(" -- %08x\n", pmuserenr);

运行此工具的前几次,该位已正确标记为已打开。但是每运行第三或第四次,该位就会显示为关闭。在对此感到困惑之后,我遇到了this link,用户正在为每个CPU启用此位。每个内核都有自己的PMU实例,还是每个SoC只有一个?如果每个SoC有多个,PMUCCNTR寄存器是否已同步? (也就是说,如果我读了PMUCCNTR,然后将上下文切换到另一个内核,然后再次读了PMUCCNTR,我可以安全地比较两者以查看经过了多少滴答吗?)。

即使我修改了LKM以在每个在线CPU上进行初始化(并注册了一个通知程序以在即将出现的所有新CPU上启用它),我仍然会看到相同的行为,其中从用户空间读取的每n次读取都会显示该位没有设置。

我的另一个问题是PMCCNTR没有递增。我设置了PMCR.E位,但是它仍然没有递增。我找到了一个网站,上面说我需要设置PMCR.C位-但这有清除计数器的副作用,由于担心会导致出现竞争状况(在其他人处于这种情况下,我不想这样做)在清除计数器时使用计数器)。任何帮助或见解都将受到欢迎。

1 个答案:

答案 0 :(得分:1)

每个cpu都有自己的PMU实例,它们是完全独立的(少数少数集群范围的事件除外,其中每个PMU都有自己的计数)。

例如,请参见今天"debug memory map pmu"的第一篇,记住v7和v8调试内存映射标准是不同的。实际答案过于“明显”,无法期望将其明确记录在案。

0x010000 - 0x010FFF   CPU 0 Debug
0x030000 - 0x030FFF   CPU 0 PMU
0x110000 - 0x110FFF   CPU 1 Debug
0x130000 - 0x130FFF   CPU 1 PMU
0x210000 - 0x210FFF   CPU 2 Debug
0x230000 - 0x230FFF   CPU 2 PMU
0x310000 - 0x310FFF   CPU 3 Debug
0x330000 - 0x330FFF   CPU 3 PMU