[PATCH v3 2/2] cpufreq: update capacity_freq_ref when the boost state changes

Dietmar Eggemann dietmar.eggemann at arm.com
Thu Sep 17 02:57:57 PDT 2026


On 10.09.26 08:34, Oleg Keri wrote:
> capacity_freq_ref is latched from policy->cpuinfo.max_freq by
> init_cpu_capacity_callback() on CPUFREQ_CREATE_POLICY, and never
> updated afterwards.
> 
> cpufreq_frequency_table_cpuinfo() excludes CPUFREQ_BOOST_FREQ entries
> while boost is disabled, so on a system that boots with boost off the
> latched value is the non-boost maximum.  Enabling boost later raises
> policy->cpuinfo.max_freq but leaves capacity_freq_ref behind.
> 
> Two things then go wrong on arm64, where the AMU drives frequency
> invariance.  amu_scale_freq_tick() caps the computed scale at
> SCHED_CAPACITY_SCALE, so a CPU running above capacity_freq_ref
> saturates at 1024: the scheduler cannot tell a boosted CPU from one at
> the sustained maximum, and utilisation is underestimated.  And

IMHO, this is where the concept of 'cpufreq pressure' on CPU capacity
comes in.

The cpu_capacity value is calculated based on highest_perf.	(1)

In case you start with 'boost == 0' nominal_perf might might be lower
than highest_perf.

cpufreq_update_pressure() calculates this value:

cpufreq_pressure = Cmax * (1 - fcapped - fmax)			(2)

[ fcapped = policy->max, fmax = capacity_freq_ref ]

Example on RADXA Orion 06 CPU10:

$ grep . /sys/devices/system/cpu/cpu10/acpi_cppc/*
...
/sys/devices/system/cpu/cpu10/acpi_cppc/highest_perf:7876
/sys/devices/system/cpu/cpu10/acpi_cppc/lowest_freq:800
/sys/devices/system/cpu/cpu10/acpi_cppc/lowest_nonlinear_perf:2520
/sys/devices/system/cpu/cpu10/acpi_cppc/lowest_perf:2520
/sys/devices/system/cpu/cpu10/acpi_cppc/nominal_freq:2500
/sys/devices/system/cpu/cpu10/acpi_cppc/nominal_perf:6600   <-- hacked
/sys/devices/system/cpu/cpu10/acpi_cppc/reference_perf:1000
...

# cat /sys/devices/system/cpu/cpu10/cpu_capacity	<-- (1)
984

# cat /sys/devices/system/cpu/cpu10/cpufreq/boost
0

dmesg (added log)

[    8.065337] cpufreq_update_pressure(): policy->related_cpus=[10-11]
policy->max=2500000 pressure=173			<-- (2)

# echo 1 > /sys/devices/system/cpu/cpufreq/boost

# cat /sys/devices/system/cpu/cpu10/cpufreq/boost
1

dmesg (added log)

[38137.194134] cpufreq_update_pressure(): policy->related_cpus=[10-11]
policy->max=3031666 pressure=0				<-- (2)

The task scheduler gets informed via:

get_actual_cpu_capacity(int cpu)

  capacity = arch_scale_cpu_capacity(cpu);

  capacity -= max(hw_load_avg(cpu_rq(cpu)), cpufreq_get_pressure(cpu));
                                            ^^^^^^^^^^^^^^^^^^^^
  return capacity;

[...]



More information about the linux-arm-kernel mailing list