Date: Wed, 11 Feb 2026 20:44:02 +0000 From: Olivier Certner <olce@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 6db204dc2de0 - main - hwpstate_amd(4): Factor out setting the CPPC_REQUEST register Message-ID: <698cea12.46042.6e964248@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=6db204dc2de0f52e9a6842af29f026a8a2951e3c commit 6db204dc2de0f52e9a6842af29f026a8a2951e3c Author: Olivier Certner <olce@FreeBSD.org> AuthorDate: 2026-01-27 11:30:48 +0000 Commit: Olivier Certner <olce@FreeBSD.org> CommitDate: 2026-02-11 20:43:20 +0000 hwpstate_amd(4): Factor out setting the CPPC_REQUEST register In preparation for creating other knobs to tweak values in this register beyond just the EPP (Efficiency/Performance Preference). While here, add a herald comment before the softc structure indicating how we achieve atomicity when modifying the softc. Reviewed by: aokblast Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D55008 --- sys/x86/cpufreq/hwpstate_amd.c | 94 +++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 25 deletions(-) diff --git a/sys/x86/cpufreq/hwpstate_amd.c b/sys/x86/cpufreq/hwpstate_amd.c index 049699ea02d4..18d420dc7747 100644 --- a/sys/x86/cpufreq/hwpstate_amd.c +++ b/sys/x86/cpufreq/hwpstate_amd.c @@ -147,6 +147,12 @@ enum hwpstate_flags { PSTATE_CPPC = 1, }; +/* + * Atomicity is achieved by only modifying a given softc on its associated CPU + * and with interrupts disabled. + * + * XXX - Only the CPPC support complies at the moment. + */ struct hwpstate_softc { device_t dev; u_int flags; @@ -354,35 +360,78 @@ sysctl_cppc_dump_handler(SYSCTL_HANDLER_ARGS) return (error); } + +struct set_cppc_request_cb { + struct hwpstate_softc *sc; + uint64_t request; + uint64_t mask; + int res; /* 0 or HWP_ERROR_CPPC_REQUEST_WRITE */ +}; + static void -set_epp(device_t hwp_device, u_int val) +set_cppc_request_cb(void *args) { - struct hwpstate_softc *sc; + struct set_cppc_request_cb *const data = args; + uint64_t *const req = &data->sc->cppc.request; + int error; - sc = device_get_softc(hwp_device); - if (BITS_VALUE(AMD_CPPC_REQUEST_EPP_BITS, sc->cppc.request) == val) - return; - SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_EPP_BITS, val); - x86_msr_op(MSR_AMD_CPPC_REQUEST, - MSR_OP_RENDEZVOUS_ONE | MSR_OP_WRITE | - MSR_OP_CPUID(cpu_get_pcpu(hwp_device)->pc_cpuid), - sc->cppc.request, NULL); + *req &= ~data->mask; + *req |= data->request & data->mask; + + error = wrmsr_safe(MSR_AMD_CPPC_REQUEST, *req); + data->res = error == 0 ? 0 : HWP_ERROR_CPPC_REQUEST_WRITE; +} + +static inline void +set_cppc_request_send_one(struct set_cppc_request_cb *const data, device_t dev) +{ + const u_int cpuid = cpu_get_pcpu(dev)->pc_cpuid; + + data->sc = device_get_softc(dev); + smp_rendezvous_cpu(cpuid, smp_no_rendezvous_barrier, + set_cppc_request_cb, smp_no_rendezvous_barrier, data); +} + +static int +set_cppc_request(device_t hwp_dev, uint64_t request, uint64_t mask) +{ + struct set_cppc_request_cb data = { + .request = request, + .mask = mask, + /* 'sc' filled by set_cppc_request_send_one(). */ + }; + int error; + + if (hwpstate_pkg_ctrl_enable) { + const devclass_t dc = devclass_find(HWP_AMD_CLASSNAME); + const int units = devclass_get_maxunit(dc); + + error = 0; + for (int i = 0; i < units; ++i) { + const device_t dev = devclass_get_device(dc, i); + + set_cppc_request_send_one(&data, dev); + if (data.res != 0) + /* Note the error, but continue. */ + error = EFAULT; + } + } else { + set_cppc_request_send_one(&data, hwp_dev); + error = data.res != 0 ? EFAULT : 0; + } + + return (error); } static int sysctl_epp_handler(SYSCTL_HANDLER_ARGS) { - device_t dev, hwp_dev; - devclass_t dc; - struct hwpstate_softc *sc; const u_int max_epp = BITS_VALUE(AMD_CPPC_REQUEST_EPP_BITS, (uint64_t)-1); + const device_t dev = oidp->oid_arg1; + struct hwpstate_softc *const sc = device_get_softc(dev); u_int val; int error = 0; - int cpu; - - dev = oidp->oid_arg1; - sc = device_get_softc(dev); /* Sysctl knob does not exist if PSTATE_CPPC is not set. */ check_cppc_enabled(sc, __func__); @@ -398,14 +447,9 @@ sysctl_epp_handler(SYSCTL_HANDLER_ARGS) } val = (val * max_epp) / 100; - if (hwpstate_pkg_ctrl_enable) { - dc = devclass_find(HWP_AMD_CLASSNAME); - CPU_FOREACH(cpu) { - hwp_dev = devclass_get_device(dc, cpu); - set_epp(hwp_dev, val); - } - } else - set_epp(dev, val); + error = set_cppc_request(dev, + BITS_WITH_VALUE(AMD_CPPC_REQUEST_EPP_BITS, val), + BITS_WITH_VALUE(AMD_CPPC_REQUEST_EPP_BITS, -1)); end: return (error);home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?698cea12.46042.6e964248>
