Skip to content

Commit c5132c4

Browse files
committed
cpufreq/amd-pstate: Add support for the "Requested CPU Min frequency" BIOS option
JIRA: https://issues.redhat.com/browse/RHEL-106954 commit 608a76b Author: Dhananjay Ugwekar <dhananjay.ugwekar@amd.com> Date: Mon Apr 28 07:16:24 2025 +0000 cpufreq/amd-pstate: Add support for the "Requested CPU Min frequency" BIOS option Initialize lower frequency limit to the "Requested CPU Min frequency" BIOS option (if it is set) value as part of the driver->init() callback. The BIOS specified value is passed by the PMFW as min_perf in CPPC_REQ MSR. To ensure that we don't mistake a stale min_perf value in CPPC_REQ value as the "Requested CPU Min frequency" during a kexec wakeup, reset the CPPC_REQ.min_perf value back to the BIOS specified one in the offline, exit and suspend callbacks. amd_pstate_target() and amd_pstate_epp_update_limit() which are invoked as part of the resume() and online() callbacks will take care of restoring the CPPC_REQ back to the correct values. Signed-off-by: Dhananjay Ugwekar <dhananjay.ugwekar@amd.com> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> Link: https://lore.kernel.org/r/20250428071623.4309-1-dhananjay.ugwekar@amd.com Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Steve Best <sbest@redhat.com>
1 parent e6fcc3e commit c5132c4

File tree

2 files changed

+71
-13
lines changed

2 files changed

+71
-13
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,8 @@ static inline int amd_pstate_cppc_enable(struct cpufreq_policy *policy)
389389
static int msr_init_perf(struct amd_cpudata *cpudata)
390390
{
391391
union perf_cached perf = READ_ONCE(cpudata->perf);
392-
u64 cap1, numerator;
392+
u64 cap1, numerator, cppc_req;
393+
u8 min_perf;
393394

394395
int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1,
395396
&cap1);
@@ -400,6 +401,22 @@ static int msr_init_perf(struct amd_cpudata *cpudata)
400401
if (ret)
401402
return ret;
402403

404+
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &cppc_req);
405+
if (ret)
406+
return ret;
407+
408+
WRITE_ONCE(cpudata->cppc_req_cached, cppc_req);
409+
min_perf = FIELD_GET(AMD_CPPC_MIN_PERF_MASK, cppc_req);
410+
411+
/*
412+
* Clear out the min_perf part to check if the rest of the MSR is 0, if yes, this is an
413+
* indication that the min_perf value is the one specified through the BIOS option
414+
*/
415+
cppc_req &= ~(AMD_CPPC_MIN_PERF_MASK);
416+
417+
if (!cppc_req)
418+
perf.bios_min_perf = min_perf;
419+
403420
perf.highest_perf = numerator;
404421
perf.max_limit_perf = numerator;
405422
perf.min_limit_perf = FIELD_GET(AMD_CPPC_LOWEST_PERF_MASK, cap1);
@@ -580,20 +597,26 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy_data)
580597
{
581598
/*
582599
* Initialize lower frequency limit (i.e.policy->min) with
583-
* lowest_nonlinear_frequency which is the most energy efficient
584-
* frequency. Override the initial value set by cpufreq core and
585-
* amd-pstate qos_requests.
600+
* lowest_nonlinear_frequency or the min frequency (if) specified in BIOS,
601+
* Override the initial value set by cpufreq core and amd-pstate qos_requests.
586602
*/
587603
if (policy_data->min == FREQ_QOS_MIN_DEFAULT_VALUE) {
588604
struct cpufreq_policy *policy __free(put_cpufreq_policy) =
589605
cpufreq_cpu_get(policy_data->cpu);
590606
struct amd_cpudata *cpudata;
607+
union perf_cached perf;
591608

592609
if (!policy)
593610
return -EINVAL;
594611

595612
cpudata = policy->driver_data;
596-
policy_data->min = cpudata->lowest_nonlinear_freq;
613+
perf = READ_ONCE(cpudata->perf);
614+
615+
if (perf.bios_min_perf)
616+
policy_data->min = perf_to_freq(perf, cpudata->nominal_freq,
617+
perf.bios_min_perf);
618+
else
619+
policy_data->min = cpudata->lowest_nonlinear_freq;
597620
}
598621

599622
cpufreq_verify_within_cpu_limits(policy_data);
@@ -1026,6 +1049,10 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
10261049
static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
10271050
{
10281051
struct amd_cpudata *cpudata = policy->driver_data;
1052+
union perf_cached perf = READ_ONCE(cpudata->perf);
1053+
1054+
/* Reset CPPC_REQ MSR to the BIOS value */
1055+
amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
10291056

10301057
freq_qos_remove_request(&cpudata->req[1]);
10311058
freq_qos_remove_request(&cpudata->req[0]);
@@ -1421,7 +1448,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14211448
struct amd_cpudata *cpudata;
14221449
union perf_cached perf;
14231450
struct device *dev;
1424-
u64 value;
14251451
int ret;
14261452

14271453
/*
@@ -1486,12 +1512,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14861512
cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
14871513
}
14881514

1489-
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
1490-
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
1491-
if (ret)
1492-
return ret;
1493-
WRITE_ONCE(cpudata->cppc_req_cached, value);
1494-
}
14951515
ret = amd_pstate_set_epp(policy, cpudata->epp_default);
14961516
if (ret)
14971517
return ret;
@@ -1511,6 +1531,11 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
15111531
struct amd_cpudata *cpudata = policy->driver_data;
15121532

15131533
if (cpudata) {
1534+
union perf_cached perf = READ_ONCE(cpudata->perf);
1535+
1536+
/* Reset CPPC_REQ MSR to the BIOS value */
1537+
amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
1538+
15141539
kfree(cpudata);
15151540
policy->driver_data = NULL;
15161541
}
@@ -1568,12 +1593,31 @@ static int amd_pstate_cpu_online(struct cpufreq_policy *policy)
15681593

15691594
static int amd_pstate_cpu_offline(struct cpufreq_policy *policy)
15701595
{
1571-
return 0;
1596+
struct amd_cpudata *cpudata = policy->driver_data;
1597+
union perf_cached perf = READ_ONCE(cpudata->perf);
1598+
1599+
/*
1600+
* Reset CPPC_REQ MSR to the BIOS value, this will allow us to retain the BIOS specified
1601+
* min_perf value across kexec reboots. If this CPU is just onlined normally after this, the
1602+
* limits, epp and desired perf will get reset to the cached values in cpudata struct
1603+
*/
1604+
return amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
15721605
}
15731606

15741607
static int amd_pstate_suspend(struct cpufreq_policy *policy)
15751608
{
15761609
struct amd_cpudata *cpudata = policy->driver_data;
1610+
union perf_cached perf = READ_ONCE(cpudata->perf);
1611+
int ret;
1612+
1613+
/*
1614+
* Reset CPPC_REQ MSR to the BIOS value, this will allow us to retain the BIOS specified
1615+
* min_perf value across kexec reboots. If this CPU is just resumed back without kexec,
1616+
* the limits, epp and desired perf will get reset to the cached values in cpudata struct
1617+
*/
1618+
ret = amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
1619+
if (ret)
1620+
return ret;
15771621

15781622
/* invalidate to ensure it's rewritten during resume */
15791623
cpudata->cppc_req_cached = 0;
@@ -1584,6 +1628,17 @@ static int amd_pstate_suspend(struct cpufreq_policy *policy)
15841628
return 0;
15851629
}
15861630

1631+
static int amd_pstate_resume(struct cpufreq_policy *policy)
1632+
{
1633+
struct amd_cpudata *cpudata = policy->driver_data;
1634+
union perf_cached perf = READ_ONCE(cpudata->perf);
1635+
int cur_perf = freq_to_perf(perf, cpudata->nominal_freq, policy->cur);
1636+
1637+
/* Set CPPC_REQ to last sane value until the governor updates it */
1638+
return amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf,
1639+
0U, false);
1640+
}
1641+
15871642
static int amd_pstate_epp_resume(struct cpufreq_policy *policy)
15881643
{
15891644
struct amd_cpudata *cpudata = policy->driver_data;
@@ -1612,6 +1667,7 @@ static struct cpufreq_driver amd_pstate_driver = {
16121667
.online = amd_pstate_cpu_online,
16131668
.offline = amd_pstate_cpu_offline,
16141669
.suspend = amd_pstate_suspend,
1670+
.resume = amd_pstate_resume,
16151671
.set_boost = amd_pstate_set_boost,
16161672
.update_limits = amd_pstate_update_limits,
16171673
.name = "amd-pstate",

drivers/cpufreq/amd-pstate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* @lowest_perf: the absolute lowest performance level of the processor
3131
* @min_limit_perf: Cached value of the performance corresponding to policy->min
3232
* @max_limit_perf: Cached value of the performance corresponding to policy->max
33+
* @bios_min_perf: Cached perf value corresponding to the "Requested CPU Min Frequency" BIOS option
3334
*/
3435
union perf_cached {
3536
struct {
@@ -39,6 +40,7 @@ union perf_cached {
3940
u8 lowest_perf;
4041
u8 min_limit_perf;
4142
u8 max_limit_perf;
43+
u8 bios_min_perf;
4244
};
4345
u64 val;
4446
};

0 commit comments

Comments
 (0)