CPU Frequency Scaling
MediaTek IoT platform supports dynamic CPU frequency scaling to allow users to adjust CPU frequencies at runtime to meet requirements of applications. IoT Yocto implements the driver which leverages Linux CPUFreq framework to provide the capability. The de-facto, familiar user space interfaces are provided so that developers can use their own tools to tweak system performance.
For more information about Linux CPUFreq subsystem, please refer to kernel document and Arch Linux wiki.
The following sections will describe cpufreq interface provided by IoT Yocto.
sysfs attributes
We can list content of the directory /sys/devices/system/cpu/cpufreq
:
ls -l /sys/devices/system/cpu/cpufreq
total 0
drwxr-xr-x 4 root root 0 Sep 20 10:46 policy0
Where the subfolder policyX
represents a policy object in cpufreq subsystem, which is a set
of CPUs sharing the same P-state controlling interface. In the policyX
subfolder, there are
sysfs attributes exported:
ls -l /sys/devices/system/cpu/cpufreq/policyX
total 0
-r--r--r-- 1 root root 4096 Sep 20 17:29 affected_cpus
-r-------- 1 root root 4096 Sep 20 17:54 cpuinfo_cur_freq
-r--r--r-- 1 root root 4096 Sep 20 17:54 cpuinfo_max_freq
-r--r--r-- 1 root root 4096 Sep 20 17:54 cpuinfo_min_freq
-r--r--r-- 1 root root 4096 Sep 20 17:54 cpuinfo_transition_latency
-r--r--r-- 1 root root 4096 Sep 20 17:29 related_cpus
-r--r--r-- 1 root root 4096 Sep 20 17:54 scaling_available_frequencies
-r--r--r-- 1 root root 4096 Sep 20 17:54 scaling_available_governors
-r--r--r-- 1 root root 4096 Sep 20 10:46 scaling_cur_freq
-r--r--r-- 1 root root 4096 Sep 20 17:54 scaling_driver
-rw-r--r-- 1 root root 4096 Sep 20 10:47 scaling_governor
-rw-r--r-- 1 root root 4096 Sep 20 17:54 scaling_max_freq
-rw-r--r-- 1 root root 4096 Sep 20 17:54 scaling_min_freq
-rw-r--r-- 1 root root 4096 Sep 20 17:54 scaling_setspeed
drwxr-xr-x 2 root root 0 Sep 20 17:54 schedutil
drwxr-xr-x 2 root root 0 Sep 20 17:54 stats
To read CPUs belonging to this policy object, run the command:
cat /sys/devices/system/cpu/cpufreq/policyX/related_cpus
0 1 2 3
Note that all policy-specific operations (e.g. changing governor, setting frequencies, etc.) affects all CPUs belonging to the same policy.
To read current CPU frequency, run the command:
cat /sys/devices/system/cpu/cpufreq/policyX/scaling_cur_freq
1308000
Note the unit of the value is KHz.
To list current supported frequencies, run:
cat /sys/devices/system/cpu/cpufreq/policyX/scaling_available_frequencies
To list current supported frequency governors, run:
cat /sys/devices/system/cpu/cpufreq/policyX/scaling_available_governors
ondemand userspace performance schedutil
Note the default governor is schedutil, which uses CPU utilization data of the in-kernel scheduler to determine CPU frequencies.
To keep CPU running at the highest frequency, run:
echo performance > /sys/devices/system/cpu/cpufreq/policyX/scaling_governor
Note the highest frequency will be capped by the frequency set in scaling_max_freq
. The user
can use the attribute to limit the highest frequency the governor can set.
To disable automatic scaling in kernel and let userspace application determine frequencies, run:
echo userspace > /sys/devices/system/cpu/cpufreq/policyX/scaling_governor
echo <FREQ> > /sys/devices/system/cpu/cpufreq/policyX/scaling_setspeed
Statistics
If the kernel configuration CONFIG_CPU_FREQ_STAT is enabled, another subfolder stats
will be
created under the policyX
folder, which contains read-only attributes to examine statistics.
Here is list of attributes:
ls -l > /sys/devices/system/cpu/cpufreq/policyX/stats
total 0
--w------- 1 root root 4096 Sep 20 14:27 reset
-r--r--r-- 1 root root 4096 Sep 20 13:58 time_in_state
-r--r--r-- 1 root root 4096 Sep 20 13:58 total_trans
-r--r--r-- 1 root root 4096 Sep 20 13:58 trans_table
To read the amount of time spent in each frequency, run:
cat /sys/devices/system/cpu/cpufreq/policyX/stats/time_in_state
850000 1334115
918000 166
987000 72
1056000 31
1125000 5
1216000 16
1308000 130
1400000 14
1466000 19
1533000 4
1633000 3
1700000 3
1767000 8674
1834000 1713
1917000 1
2001000 233393
The first column represents the supported frequency, and the second one is the time the CPU spends at that frequency. The time unit is 10ms.
The attribute total_trans gives total number of frequency transition happened:
cat /sys/devices/system/cpu/cpufreq/policyX/stats/total_trans
533
The attribute trans_table gives detailed information of frequency transition:
# cat /sys/devices/system/cpu/cpufreq/policyX/stats/trans_table
From : To
: 850000 918000 987000 1056000 1125000 1216000 1308000 1400000 1466000 ...
850000: 0 15 11 4 1 1 126 5 2
918000: 18 0 2 0 0 1 1 0 1
987000: 18 1 0 1 0 1 1 0 0
1056000: 6 1 1 0 1 0 2 1 0
1125000: 1 2 3 1 0 2 0 0 2
1216000: 3 3 1 4 4 0 6 1 0
1308000: 107 0 4 1 3 14 0 11 1
1400000: 10 0 0 1 0 1 5 0 6
1466000: 2 0 0 0 2 1 0 4 0
...
The output is a two dimension matrix with i rows and j columns, where each cell represents the number of transition happened from Freq_i to Freq_j.
The counters in statistics are accumulated since the driver (cpufreq_stats) is loaded or counters are reset. The counters can be reset by running the command:
echo 1 > /sys/devices/system/cpu/cpufreq/policyX/stats/reset
Note the value written to the attribute doesn’t matter. It is the write operation causing reset of counters.