git: df7b4dcdb8ff - main - hwpstate_amd(4): Sane defaults for min/max perf on insane capabilities

From: Olivier Certner <olce_at_FreeBSD.org>
Date: Wed, 11 Feb 2026 20:44:01 UTC
The branch main has been updated by olce:

URL: https://cgit.FreeBSD.org/src/commit/?id=df7b4dcdb8ff32a735916b50a473424b543c1e5e

commit df7b4dcdb8ff32a735916b50a473424b543c1e5e
Author:     Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2026-01-29 21:14:48 +0000
Commit:     Olivier Certner <olce@FreeBSD.org>
CommitDate: 2026-02-11 20:43:20 +0000

    hwpstate_amd(4): Sane defaults for min/max perf on insane capabilities
    
    If the CPPC_CAPABILITY_1 register stays at its reset value (0) even
    after enabling CPPC, as observed in the field (see the referenced PR
    below), use sane min/max performance limits as hinted by the ACPI spec,
    i.e., all 0s for the minimum value and all 1s for the maximum one.
    
    While here, let's cope upfront with some more insane situations, where
    the minimum value would be greater than the maximum one, but also if
    they would be equal which does not seem to make sense at all in the CPPC
    frame (and, anyway, in this case, the actual minimum and maximum values
    we program should have no effect at all).  That last case actually also
    covers the one exposed in the previous paragraph.
    
    PR:             292615
    Reviewed by:    aokblast
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D55007
---
 sys/x86/cpufreq/hwpstate_amd.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/sys/x86/cpufreq/hwpstate_amd.c b/sys/x86/cpufreq/hwpstate_amd.c
index d1186ae786ce..049699ea02d4 100644
--- a/sys/x86/cpufreq/hwpstate_amd.c
+++ b/sys/x86/cpufreq/hwpstate_amd.c
@@ -661,6 +661,7 @@ amd_set_autonomous_hwp_cb(void *args)
 {
 	struct set_autonomous_hwp_data *const data = args;
 	struct hwpstate_softc *const sc = data->sc;
+	uint64_t lowest_perf, highest_perf;
 	int error;
 
 	/* We proceed sequentially, so we'll clear out errors on progress. */
@@ -690,12 +691,30 @@ amd_set_autonomous_hwp_cb(void *args)
 	 * CPPC driver.
 	 */
 	SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_EPP_BITS, 0x80);
+
+	/* Enable autonomous mode by setting desired performance to 0. */
+	SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_DES_PERF_BITS, 0);
+
+	/*
+	 * When MSR_AMD_CPPC_CAPS_1 stays at its reset value (0) before CPPC
+	 * activation (not supposed to happen, but happens in the field), we use
+	 * reasonable default values that are explicitly described by the ACPI
+	 * spec (all 0s for the minimum value, all 1s for the maximum one).
+	 * Going further, we actually do the same as long as the minimum and
+	 * maximum performance levels are not sorted or are equal (in which case
+	 * CPPC is not supposed to make sense at all), which covers the reset
+	 * value case.
+	 */
+	lowest_perf = BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, data->caps);
+	highest_perf = BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, data->caps);
+	if (lowest_perf >= highest_perf) {
+		lowest_perf = 0;
+		highest_perf = -1;
+	}
 	SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_MIN_PERF_BITS,
-	    BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, data->caps));
+	    lowest_perf);
 	SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_MAX_PERF_BITS,
-	    BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, data->caps));
-	/* enable autonomous mode by setting desired performance to 0 */
-	SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_DES_PERF_BITS, 0);
+	    highest_perf);
 
 	error = wrmsr_safe(MSR_AMD_CPPC_REQUEST, sc->cppc.request);
 	if (error != 0)