我正在尝试从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
位-但这有清除计数器的副作用,由于担心会导致出现竞争状况(在其他人处于这种情况下,我不想这样做)在清除计数器时使用计数器)。任何帮助或见解都将受到欢迎。
答案 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