Skip to content

Commit 7485e22

Browse files
committed
Merge: Update amd-pstate driver
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6394 JIRA: https://issues.redhat.com/browse/RHEL-75923 Omitted-fix: e120829 (can be backported via perf) The following upstream commit was excluded from the backport as it is not currently compatible with RHEL: b4b1ddc cpufreq: Make cpufreq_driver->exit() return void Signed-off-by: David Arcari <[email protected]> Approved-by: Mark Langsdorf <[email protected]> Approved-by: Steve Best <[email protected]> Approved-by: CKI KWF Bot <[email protected]> Merged-by: Augusto Caringi <[email protected]>
2 parents d172c7f + 1075d43 commit 7485e22

File tree

20 files changed

+1028
-581
lines changed

20 files changed

+1028
-581
lines changed

Documentation/admin-guide/acpi/cppc_sysfs.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,4 @@ taking two different snapshots of feedback counters at time T1 and T2.
7575
delivered_counter_delta = fbc_t2[del] - fbc_t1[del]
7676
reference_counter_delta = fbc_t2[ref] - fbc_t1[ref]
7777

78-
delivered_perf = (refernce_perf x delivered_counter_delta) / reference_counter_delta
78+
delivered_perf = (reference_perf x delivered_counter_delta) / reference_counter_delta

Documentation/admin-guide/pm/amd-pstate.rst

Lines changed: 347 additions & 24 deletions
Large diffs are not rendered by default.

arch/arm64/include/asm/topology.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ void update_freq_counters_refs(void);
2525
#define arch_scale_freq_invariant topology_scale_freq_invariant
2626
#define arch_scale_freq_ref topology_get_freq_ref
2727

28-
#ifdef CONFIG_ACPI_CPPC_LIB
29-
#define arch_init_invariance_cppc topology_init_cpu_capacity_cppc
30-
#endif
31-
3228
/* Replace task scheduler's default cpu-invariant accounting */
3329
#define arch_scale_cpu_capacity topology_get_cpu_scale
3430

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@
479479
#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */
480480
#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */
481481
#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */
482-
#define X86_FEATURE_FAST_CPPC (21*32 + 5) /* "" AMD Fast CPPC */
482+
#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* Fast CPPC */
483483

484484
/*
485485
* BUG word(s)

arch/x86/include/asm/processor.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,11 +727,9 @@ static inline u32 per_cpu_l2c_id(unsigned int cpu)
727727
}
728728

729729
#ifdef CONFIG_CPU_SUP_AMD
730-
extern u32 amd_get_highest_perf(void);
731730
extern void amd_clear_divider(void);
732731
extern void amd_check_microcode(void);
733732
#else
734-
static inline u32 amd_get_highest_perf(void) { return 0; }
735733
static inline void amd_clear_divider(void) { }
736734
static inline void amd_check_microcode(void) { }
737735
#endif

arch/x86/include/asm/topology.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,4 @@ static inline void freq_invariance_set_perf_ratio(u64 ratio, bool turbo_disabled
305305
extern void arch_scale_freq_tick(void);
306306
#define arch_scale_freq_tick arch_scale_freq_tick
307307

308-
#ifdef CONFIG_ACPI_CPPC_LIB
309-
void init_freq_invariance_cppc(void);
310-
#define arch_init_invariance_cppc init_freq_invariance_cppc
311-
#endif
312-
313308
#endif /* _ASM_X86_TOPOLOGY_H */

arch/x86/kernel/acpi/cppc.c

Lines changed: 166 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@
99
#include <asm/processor.h>
1010
#include <asm/topology.h>
1111

12+
#define CPPC_HIGHEST_PERF_PERFORMANCE 196
13+
#define CPPC_HIGHEST_PERF_PREFCORE 166
14+
15+
enum amd_pref_core {
16+
AMD_PREF_CORE_UNKNOWN = 0,
17+
AMD_PREF_CORE_SUPPORTED,
18+
AMD_PREF_CORE_UNSUPPORTED,
19+
};
20+
static enum amd_pref_core amd_pref_core_detected;
21+
static u64 boost_numerator;
22+
1223
/* Refer to drivers/acpi/cppc_acpi.c for the description of functions */
1324

1425
bool cpc_supported_by_cpu(void)
@@ -69,7 +80,7 @@ int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val)
6980
static void amd_set_max_freq_ratio(void)
7081
{
7182
struct cppc_perf_caps perf_caps;
72-
u64 highest_perf, nominal_perf;
83+
u64 numerator, nominal_perf;
7384
u64 perf_ratio;
7485
int rc;
7586

@@ -79,15 +90,19 @@ static void amd_set_max_freq_ratio(void)
7990
return;
8091
}
8192

82-
highest_perf = amd_get_highest_perf();
93+
rc = amd_get_boost_ratio_numerator(0, &numerator);
94+
if (rc) {
95+
pr_debug("Could not retrieve highest performance (%d)\n", rc);
96+
return;
97+
}
8398
nominal_perf = perf_caps.nominal_perf;
8499

85-
if (!highest_perf || !nominal_perf) {
86-
pr_debug("Could not retrieve highest or nominal performance\n");
100+
if (!nominal_perf) {
101+
pr_debug("Could not retrieve nominal performance\n");
87102
return;
88103
}
89104

90-
perf_ratio = div_u64(highest_perf * SCHED_CAPACITY_SCALE, nominal_perf);
105+
perf_ratio = div_u64(numerator * SCHED_CAPACITY_SCALE, nominal_perf);
91106
/* midpoint between max_boost and max_P */
92107
perf_ratio = (perf_ratio + SCHED_CAPACITY_SCALE) >> 1;
93108
if (!perf_ratio) {
@@ -100,7 +115,7 @@ static void amd_set_max_freq_ratio(void)
100115

101116
static DEFINE_MUTEX(freq_invariance_lock);
102117

103-
void init_freq_invariance_cppc(void)
118+
static inline void init_freq_invariance_cppc(void)
104119
{
105120
static bool init_done;
106121

@@ -116,3 +131,148 @@ void init_freq_invariance_cppc(void)
116131
init_done = true;
117132
mutex_unlock(&freq_invariance_lock);
118133
}
134+
135+
void acpi_processor_init_invariance_cppc(void)
136+
{
137+
init_freq_invariance_cppc();
138+
}
139+
140+
/*
141+
* Get the highest performance register value.
142+
* @cpu: CPU from which to get highest performance.
143+
* @highest_perf: Return address for highest performance value.
144+
*
145+
* Return: 0 for success, negative error code otherwise.
146+
*/
147+
int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf)
148+
{
149+
u64 val;
150+
int ret;
151+
152+
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
153+
ret = rdmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_CAP1, &val);
154+
if (ret)
155+
goto out;
156+
157+
val = AMD_CPPC_HIGHEST_PERF(val);
158+
} else {
159+
ret = cppc_get_highest_perf(cpu, &val);
160+
if (ret)
161+
goto out;
162+
}
163+
164+
WRITE_ONCE(*highest_perf, (u32)val);
165+
out:
166+
return ret;
167+
}
168+
EXPORT_SYMBOL_GPL(amd_get_highest_perf);
169+
170+
/**
171+
* amd_detect_prefcore: Detect if CPUs in the system support preferred cores
172+
* @detected: Output variable for the result of the detection.
173+
*
174+
* Determine whether CPUs in the system support preferred cores. On systems
175+
* that support preferred cores, different highest perf values will be found
176+
* on different cores. On other systems, the highest perf value will be the
177+
* same on all cores.
178+
*
179+
* The result of the detection will be stored in the 'detected' parameter.
180+
*
181+
* Return: 0 for success, negative error code otherwise
182+
*/
183+
int amd_detect_prefcore(bool *detected)
184+
{
185+
int cpu, count = 0;
186+
u64 highest_perf[2] = {0};
187+
188+
if (WARN_ON(!detected))
189+
return -EINVAL;
190+
191+
switch (amd_pref_core_detected) {
192+
case AMD_PREF_CORE_SUPPORTED:
193+
*detected = true;
194+
return 0;
195+
case AMD_PREF_CORE_UNSUPPORTED:
196+
*detected = false;
197+
return 0;
198+
default:
199+
break;
200+
}
201+
202+
for_each_present_cpu(cpu) {
203+
u32 tmp;
204+
int ret;
205+
206+
ret = amd_get_highest_perf(cpu, &tmp);
207+
if (ret)
208+
return ret;
209+
210+
if (!count || (count == 1 && tmp != highest_perf[0]))
211+
highest_perf[count++] = tmp;
212+
213+
if (count == 2)
214+
break;
215+
}
216+
217+
*detected = (count == 2);
218+
boost_numerator = highest_perf[0];
219+
220+
amd_pref_core_detected = *detected ? AMD_PREF_CORE_SUPPORTED :
221+
AMD_PREF_CORE_UNSUPPORTED;
222+
223+
pr_debug("AMD CPPC preferred core is %ssupported (highest perf: 0x%llx)\n",
224+
*detected ? "" : "un", highest_perf[0]);
225+
226+
return 0;
227+
}
228+
EXPORT_SYMBOL_GPL(amd_detect_prefcore);
229+
230+
/**
231+
* amd_get_boost_ratio_numerator: Get the numerator to use for boost ratio calculation
232+
* @cpu: CPU to get numerator for.
233+
* @numerator: Output variable for numerator.
234+
*
235+
* Determine the numerator to use for calculating the boost ratio on
236+
* a CPU. On systems that support preferred cores, this will be a hardcoded
237+
* value. On other systems this will the highest performance register value.
238+
*
239+
* If booting the system with amd-pstate enabled but preferred cores disabled then
240+
* the correct boost numerator will be returned to match hardware capabilities
241+
* even if the preferred cores scheduling hints are not enabled.
242+
*
243+
* Return: 0 for success, negative error code otherwise.
244+
*/
245+
int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
246+
{
247+
bool prefcore;
248+
int ret;
249+
250+
ret = amd_detect_prefcore(&prefcore);
251+
if (ret)
252+
return ret;
253+
254+
/* without preferred cores, return the highest perf register value */
255+
if (!prefcore) {
256+
*numerator = boost_numerator;
257+
return 0;
258+
}
259+
260+
/*
261+
* For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f,
262+
* the highest performance level is set to 196.
263+
* https://bugzilla.kernel.org/show_bug.cgi?id=218759
264+
*/
265+
if (cpu_feature_enabled(X86_FEATURE_ZEN4)) {
266+
switch (boot_cpu_data.x86_model) {
267+
case 0x70 ... 0x7f:
268+
*numerator = CPPC_HIGHEST_PERF_PERFORMANCE;
269+
return 0;
270+
default:
271+
break;
272+
}
273+
}
274+
*numerator = CPPC_HIGHEST_PERF_PREFCORE;
275+
276+
return 0;
277+
}
278+
EXPORT_SYMBOL_GPL(amd_get_boost_ratio_numerator);

arch/x86/kernel/cpu/amd.c

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,22 +1189,6 @@ unsigned long amd_get_dr_addr_mask(unsigned int dr)
11891189
}
11901190
EXPORT_SYMBOL_GPL(amd_get_dr_addr_mask);
11911191

1192-
u32 amd_get_highest_perf(void)
1193-
{
1194-
struct cpuinfo_x86 *c = &boot_cpu_data;
1195-
1196-
if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) ||
1197-
(c->x86_model >= 0x70 && c->x86_model < 0x80)))
1198-
return 166;
1199-
1200-
if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) ||
1201-
(c->x86_model >= 0x40 && c->x86_model < 0x70)))
1202-
return 166;
1203-
1204-
return 255;
1205-
}
1206-
EXPORT_SYMBOL_GPL(amd_get_highest_perf);
1207-
12081192
static void zenbleed_check_cpu(void *unused)
12091193
{
12101194
struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());

arch/x86/kernel/cpu/scattered.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static const struct cpuid_bit cpuid_bits[] = {
4545
{ X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 },
4646
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
4747
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },
48-
{ X86_FEATURE_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 },
48+
{ X86_FEATURE_AMD_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 },
4949
{ X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 },
5050
{ X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 },
5151
{ X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 },

drivers/acpi/cppc_acpi.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -661,10 +661,6 @@ static int pcc_data_alloc(int pcc_ss_id)
661661
* )
662662
*/
663663

664-
#ifndef arch_init_invariance_cppc
665-
static inline void arch_init_invariance_cppc(void) { }
666-
#endif
667-
668664
/**
669665
* acpi_cppc_processor_probe - Search for per CPU _CPC objects.
670666
* @pr: Ptr to acpi_processor containing this CPU's logical ID.
@@ -891,8 +887,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
891887
goto out_free;
892888
}
893889

894-
arch_init_invariance_cppc();
895-
896890
kfree(output.pointer);
897891
return 0;
898892

0 commit comments

Comments
 (0)