Using PMU to count ticks on ARM

I'm trying to use the PMU (specifically use PMCCNTR to determine ticks per usec) from userspace in ARM. I have an arm64 kernel running an arm32 bit userspace app.

I created an LKM to force the PMUSERENR.EN bit to be on, which works. I then I ran a test program from userspace:

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

The first few times I ran this, the bit was correctly marked as turned on. But every third or fourth time I run it, the bit shows up as off. After puzzling over this, I came across this link, where the user is enabling this bit for each cpu. Does each core have it's own instance of a PMU, or is there only one per SoC? If there are multiple per SoC, are the PMUCCNTR registers synced up? (That is, if I read the PMUCCNTR, then do a context switch to another core, and read PMUCCNTR again, can I safely compare the two to see how many ticks have elapsed?).

Even if I modify my LKM to initialize on every online-cpu (and register a notifier to enable it on all new cpu's coming up), I'm still seeing the same behavior, where every nth read from userspace shows the bit not set.

My other issue is that the PMCCNTR is not incrementing. I set the PMCR.E bit but it's still not incrementing. I found one website that says I need to set the PMCR.C bit -- but this has a side effect of clearing the counter, which I don't want to do in fear of creating a race condition (where someone else is using the counter as I clear it). Any help or insights would be very welcome.

- - Source


answered 1 week ago Sean Houlihane #1

Each cpu has its own PMU instance, they are entirely independant (except for a small number of cluster wide events, where each PMU keeps its own count).

See, for example, the first hit today for "debug memory map pmu", remembering that v7 and v8 debug memory map standards are different. The actual answer is too 'obvious' to expect it to be explicitly documented.

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

comments powered by Disqus