CPU Frequency Scaling

MediaTek AIoT platform supports dynamic CPU frequency scaling to allow users to adjust CPU frequencies at runtime to meet requirements of applications. AIoT 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 AIoT 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.