mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
cpufreq: cppc: Sanitize lockless policy limit snapshots
cppc_cpufreq_update_perf_limits() reads policy->min and policy->max
without holding the policy lock. The cpufreq core updates those fields
with separate stores, so a reader can observe the old minimum together
with the new maximum and construct MIN_PERF greater than MAX_PERF.
Read both fields once and, if the lockless snapshot is inconsistent,
reduce the minimum to the observed maximum. This matches the conservative
correction used by cpufreq_driver_resolve_freq() and ensures that CPPC
never receives an inverted limit pair.
Fixes: ea3db45ae4 ("cpufreq: cppc: Update MIN_PERF/MAX_PERF in target callbacks")
Cc: stable@vger.kernel.org
Signed-off-by: Christian Loehle <christian.loehle@arm.com>
Link: https://patch.msgid.link/20260722093825.1030594-3-christian.loehle@arm.com
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
11055a46f3
commit
9753c0ab89
|
|
@ -290,19 +290,32 @@ static inline void cppc_freq_invariance_exit(void)
|
|||
}
|
||||
#endif /* CONFIG_ACPI_CPPC_CPUFREQ_FIE */
|
||||
|
||||
static void cppc_cpufreq_get_perf_limits(struct cppc_cpudata *cpu_data,
|
||||
struct cpufreq_policy *policy,
|
||||
u32 *min_perf, u32 *max_perf)
|
||||
{
|
||||
struct cppc_perf_caps *caps = &cpu_data->perf_caps;
|
||||
unsigned int min_freq, max_freq;
|
||||
u32 min, max;
|
||||
|
||||
min_freq = READ_ONCE(policy->min);
|
||||
max_freq = READ_ONCE(policy->max);
|
||||
if (unlikely(min_freq > max_freq))
|
||||
min_freq = max_freq;
|
||||
|
||||
min = cppc_khz_to_perf(caps, min_freq);
|
||||
max = cppc_khz_to_perf(caps, max_freq);
|
||||
|
||||
*min_perf = clamp_t(u32, min, caps->lowest_perf, caps->highest_perf);
|
||||
*max_perf = clamp_t(u32, max, caps->lowest_perf, caps->highest_perf);
|
||||
}
|
||||
|
||||
static void cppc_cpufreq_update_perf_limits(struct cppc_cpudata *cpu_data,
|
||||
struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cppc_perf_caps *caps = &cpu_data->perf_caps;
|
||||
u32 min_perf, max_perf;
|
||||
|
||||
min_perf = cppc_khz_to_perf(caps, policy->min);
|
||||
max_perf = cppc_khz_to_perf(caps, policy->max);
|
||||
|
||||
cpu_data->perf_ctrls.min_perf =
|
||||
clamp_t(u32, min_perf, caps->lowest_perf, caps->highest_perf);
|
||||
cpu_data->perf_ctrls.max_perf =
|
||||
clamp_t(u32, max_perf, caps->lowest_perf, caps->highest_perf);
|
||||
cppc_cpufreq_get_perf_limits(cpu_data, policy,
|
||||
&cpu_data->perf_ctrls.min_perf,
|
||||
&cpu_data->perf_ctrls.max_perf);
|
||||
}
|
||||
|
||||
static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user