ARM PMU cycle counter not always incrementing at CPU frequency?


I want to benchmark my program running on Linux on an Altera Cyclone V SoC board, but it turns out that the values returned from the ARM PMU cycle counter suggest that some sort of CPU frequency scaling is active, which is confusing me.

So at first I tried to find out at which frequency the CPU was running and if any frequency scaling was happening, which turned out to be difficult.
U-Boot tells me that the CPU is running at 925 MHz during boot, which is fine. But I could not find any way to read the current CPU speed from within Linux, and there seems to be no frequency scaling governor. I compiled Linux following the steps from the RocketBoards website [1], but modified .config to use only one CPU. The output of some commands that I tried is at the end of this post.

The second thing I did was to benchmark some simple code using a cycle counter. I followed a blog post [2] which suggest to use perf [3]. I modified the perf call to measure all threads running on CPU 0. When I benchmarked doing calculations in a loop and measured time and cycles, the result was precisely matching 925 MHz. But when I measured sleep() it was counting much less cycles.
So I tried reading the ARM PMU cycle counter basically following another code example ([2] and also [4]). The result was the same, during 1 second sleep() only roughly ~10.000.000 cycles are counted (but 1s * 925 MHz = 925.000.000 cycles). So I ran a second program to keep CPU usage at 100% while still benchmarking sleep(). The result was then again matching 925 MHz.
Now I wonder if this implies some sort of frequency scaling?

Even more confusing: when I configured perf to measure only cycles used by the calling (sleeping) thread and read the PMU cycle counter register at the same time, the result of the cycle counter unexpectedly matched the perf result. Even when a second program is utilizing 100% CPU at the same time. Configuring the ARM PMU event count registers [5] to measure cycles did not give different results.

Command outputs:

cpufrequtils 008: cpufreq-info © Dominik Brodowski 2004-2009
Report errors and bugs to, please.
analyzing CPU 0:
no or unknown cpufreq driver is active on this CPU

cat /proc/cpuinfo
processor : 0
model name : ARMv7 Processor rev 0 (v7l)
BogoMIPS : 921.60
Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls lpae
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x3
CPU part : 0xc09
CPU revision : 0
Hardware : Altera SOCFPGA
Revision : 0000
Serial : 0000000000000000

ls /sys/devices/system/cpu/
cpu0 kernel_max offline online possible present uevent

ls /sys/devices/system/cpu/cpu0/
subsystem topology uevent

[3] http://
[4] http://
[5] http://

I already got the answer: Linux uses the WFI instruction to put the core into standby, during which the cycle count will not increase. The kernel parameter “nohlt” will disable WFI.

1 Like