Skip to content

Commit 13c45a2

Browse files
Sumit Guptarafaeljw
authored andcommitted
ACPI: CPPC: add APIs and sysfs interface for perf_limited
Add sysfs interface to read/write the Performance Limited register. The Performance Limited register indicates to the OS that an unpredictable event (like thermal throttling) has limited processor performance. It contains two sticky bits set by the platform: - Bit 0 (Desired_Excursion): Set when delivered performance is constrained below desired performance. Not used when Autonomous Selection is enabled. - Bit 1 (Minimum_Excursion): Set when delivered performance is constrained below minimum performance. These bits remain set until OSPM explicitly clears them. The write operation accepts a bitmask of bits to clear: - Write 0x1 to clear bit 0 - Write 0x2 to clear bit 1 - Write 0x3 to clear both bits This enables users to detect if platform throttling impacted a workload. Users clear the register before execution, run the workload, then check afterward - if set, hardware throttling occurred during that time window. The interface is exposed as: /sys/devices/system/cpu/cpuX/cpufreq/perf_limited Signed-off-by: Sumit Gupta <sumitg@nvidia.com> Reviewed-by: Pierre Gondois <pierre.gondois@arm.com> Reviewed-by: Lifeng Zheng <zhenglifeng1@huawei.com> Link: https://patch.msgid.link/20260206142658.72583-7-sumitg@nvidia.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent ea3db45 commit 13c45a2

3 files changed

Lines changed: 76 additions & 0 deletions

File tree

drivers/acpi/cppc_acpi.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,6 +1978,62 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
19781978
}
19791979
EXPORT_SYMBOL_GPL(cppc_set_perf);
19801980

1981+
/**
1982+
* cppc_get_perf_limited - Get the Performance Limited register value.
1983+
* @cpu: CPU from which to get Performance Limited register.
1984+
* @perf_limited: Pointer to store the Performance Limited value.
1985+
*
1986+
* The returned value contains sticky status bits indicating platform-imposed
1987+
* performance limitations.
1988+
*
1989+
* Return: 0 for success, -EIO on failure, -EOPNOTSUPP if not supported.
1990+
*/
1991+
int cppc_get_perf_limited(int cpu, u64 *perf_limited)
1992+
{
1993+
return cppc_get_reg_val(cpu, PERF_LIMITED, perf_limited);
1994+
}
1995+
EXPORT_SYMBOL_GPL(cppc_get_perf_limited);
1996+
1997+
/**
1998+
* cppc_set_perf_limited() - Clear bits in the Performance Limited register.
1999+
* @cpu: CPU on which to write register.
2000+
* @bits_to_clear: Bitmask of bits to clear in the perf_limited register.
2001+
*
2002+
* The Performance Limited register contains two sticky bits set by platform:
2003+
* - Bit 0 (Desired_Excursion): Set when delivered performance is constrained
2004+
* below desired performance. Not used when Autonomous Selection is enabled.
2005+
* - Bit 1 (Minimum_Excursion): Set when delivered performance is constrained
2006+
* below minimum performance.
2007+
*
2008+
* These bits are sticky and remain set until OSPM explicitly clears them.
2009+
* This function only allows clearing bits (the platform sets them).
2010+
*
2011+
* Return: 0 for success, -EINVAL for invalid bits, -EIO on register
2012+
* access failure, -EOPNOTSUPP if not supported.
2013+
*/
2014+
int cppc_set_perf_limited(int cpu, u64 bits_to_clear)
2015+
{
2016+
u64 current_val, new_val;
2017+
int ret;
2018+
2019+
/* Only bits 0 and 1 are valid */
2020+
if (bits_to_clear & ~CPPC_PERF_LIMITED_MASK)
2021+
return -EINVAL;
2022+
2023+
if (!bits_to_clear)
2024+
return 0;
2025+
2026+
ret = cppc_get_perf_limited(cpu, &current_val);
2027+
if (ret)
2028+
return ret;
2029+
2030+
/* Clear the specified bits */
2031+
new_val = current_val & ~bits_to_clear;
2032+
2033+
return cppc_set_reg_val(cpu, PERF_LIMITED, new_val);
2034+
}
2035+
EXPORT_SYMBOL_GPL(cppc_set_perf_limited);
2036+
19812037
/**
19822038
* cppc_get_transition_latency - returns frequency transition latency in ns
19832039
* @cpu_num: CPU number for per_cpu().

drivers/cpufreq/cppc_cpufreq.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,16 +985,21 @@ store_energy_performance_preference_val(struct cpufreq_policy *policy,
985985
return count;
986986
}
987987

988+
CPPC_CPUFREQ_ATTR_RW_U64(perf_limited, cppc_get_perf_limited,
989+
cppc_set_perf_limited)
990+
988991
cpufreq_freq_attr_ro(freqdomain_cpus);
989992
cpufreq_freq_attr_rw(auto_select);
990993
cpufreq_freq_attr_rw(auto_act_window);
991994
cpufreq_freq_attr_rw(energy_performance_preference_val);
995+
cpufreq_freq_attr_rw(perf_limited);
992996

993997
static struct freq_attr *cppc_cpufreq_attr[] = {
994998
&freqdomain_cpus,
995999
&auto_select,
9961000
&auto_act_window,
9971001
&energy_performance_preference_val,
1002+
&perf_limited,
9981003
NULL,
9991004
};
10001005

include/acpi/cppc_acpi.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
#define CPPC_EPP_PERFORMANCE_PREF 0x00
4343
#define CPPC_EPP_ENERGY_EFFICIENCY_PREF 0xFF
4444

45+
#define CPPC_PERF_LIMITED_DESIRED_EXCURSION BIT(0)
46+
#define CPPC_PERF_LIMITED_MINIMUM_EXCURSION BIT(1)
47+
#define CPPC_PERF_LIMITED_MASK (CPPC_PERF_LIMITED_DESIRED_EXCURSION | \
48+
CPPC_PERF_LIMITED_MINIMUM_EXCURSION)
49+
4550
/* Each register has the folowing format. */
4651
struct cpc_reg {
4752
u8 descriptor;
@@ -174,6 +179,8 @@ extern int cppc_get_auto_act_window(int cpu, u64 *auto_act_window);
174179
extern int cppc_set_auto_act_window(int cpu, u64 auto_act_window);
175180
extern int cppc_get_auto_sel(int cpu, bool *enable);
176181
extern int cppc_set_auto_sel(int cpu, bool enable);
182+
extern int cppc_get_perf_limited(int cpu, u64 *perf_limited);
183+
extern int cppc_set_perf_limited(int cpu, u64 bits_to_clear);
177184
extern int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf);
178185
extern int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator);
179186
extern int amd_detect_prefcore(bool *detected);
@@ -270,6 +277,14 @@ static inline int cppc_set_auto_sel(int cpu, bool enable)
270277
{
271278
return -EOPNOTSUPP;
272279
}
280+
static inline int cppc_get_perf_limited(int cpu, u64 *perf_limited)
281+
{
282+
return -EOPNOTSUPP;
283+
}
284+
static inline int cppc_set_perf_limited(int cpu, u64 bits_to_clear)
285+
{
286+
return -EOPNOTSUPP;
287+
}
273288
static inline int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf)
274289
{
275290
return -ENODEV;

0 commit comments

Comments
 (0)