[PATCH v1 0/2] arm64/cpufreq: report and track frequencies above 4.19 GHz

From: Oleg Keri

Date: Sun Sep 06 2026 - 12:41:26 EST


The Snapdragon X2 Elite (Glymur) is the first arm64 laptop part I have
seen whose boost OPP, 4723200 kHz, sits above 4194304 kHz. Two
independent problems become visible there, both of which make the
kernel believe a boosted CPU is running slower than it is.

Patch 1 fixes an overflow in arch_freq_get_on_cpu(): the u64 product of
the frequency scale and the reference frequency is truncated to
unsigned int before being shifted back down, which wraps for any
reference frequency above 2^32 / SCHED_CAPACITY_SCALE = 4194304 kHz.

Patch 2 makes capacity_freq_ref follow the boost state. It is latched
once on CPUFREQ_CREATE_POLICY, and boost frequencies are excluded from
policy->cpuinfo.max_freq while boost is off, so on a machine that boots
with boost disabled it keeps the sustained maximum forever. On arm64
that saturates the AMU frequency scale at SCHED_CAPACITY_SCALE, so the
scheduler cannot distinguish a boosted CPU from one at the sustained
maximum, and arch_freq_get_on_cpu() cannot report above it.

The order matters: patch 2 is what raises capacity_freq_ref past
4194304 kHz on this machine, so patch 1 has to land with or before it.

Measured on a Lenovo Yoga Slim 7x Gen 11 (Glymur, 4032000 kHz
sustained, 4723200 kHz boost), pinning a policy to a single OPP and
timing a fixed workload on one of its CPUs:

requested OPP time cpuinfo_avg_freq
---------------------------------------------------------
4032000 kHz 2.011s 4031325 (0.02% low)
4723200 kHz 1.726s 524283 before
4723200 kHz 1.726s 4032000 with patch 1 only
4723200 kHz 1.726s 4718587 with both (0.10% low)

The timings never change: 2.011 / 1.726 = 1.165 against a frequency
ratio of 4723200 / 4032000 = 1.171, so the hardware was running at the
requested frequency throughout. Only the kernel's view of it was wrong.

Note that cpuinfo_cur_freq still reports 4032000 kHz at the boost OPP
on this machine. That is a separate path -- scmi_dvfs_freq_get()
asking firmware for the current performance level -- with no clamp in
the kernel, and it is not addressed here.

Oleg Keri (2):
arm64: topology: fix arch_freq_get_on_cpu() overflow above 4.19 GHz
cpufreq: update capacity_freq_ref when the boost state changes

arch/arm/include/asm/topology.h | 1 +
arch/arm64/include/asm/topology.h | 1 +
arch/arm64/kernel/topology.c | 5 +++--
arch/riscv/include/asm/topology.h | 1 +
drivers/base/arch_topology.c | 19 +++++++++++++------
drivers/cpufreq/cpufreq.c | 2 ++
include/linux/arch_topology.h | 1 +
include/linux/cpufreq.h | 7 +++++++
8 files changed, 29 insertions(+), 8 deletions(-)

base-commit: 9d80aa4617b32f5054c5aa471d06b66704854935
--
2.55.0