From nobody Wed Apr 08 07:48:47 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4frFYq6B9xz6YdLK for ; Wed, 08 Apr 2026 07:48:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4frFYq5PnTz3qpN for ; Wed, 08 Apr 2026 07:48:47 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775634527; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=dkK/64ebuCNeyYrLtZIPlvb4OYszPanHombdzSTdbAA=; b=UoW1Ur+jHEvg0N2oGTOr+tIbkbMGVE7FDKbn27maMDG2HEvUB6jKyFeX1mfRCOOkEi8Bi9 HqOi4ZgocE6tmQkml56i0/ICyvqJOOdliSAf8xTpFafzCAGyM9e5Bwh+EVs57l4YQIbOZo d7lRA4FfkDaYRpIvjhDyQM+ZnYrPv7P0yNEPT42hFe0Y9eEeVzYEpYpaPVl+cF0rqAc4Dl yCByAh3gLnOUXmhxujkEmwT+T41fsJRHJSrC/c6hu0UfyZVA005eYnu2nwHkrsWg6j+R5W GXnGVKu0BdOvaAE43fjWO7aQOI/+Hzc30fHR+K4MmprhQy80iEdVWxcrtNaxMQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1775634527; a=rsa-sha256; cv=none; b=lIc+pnIwlt5O0rU5hQ3CRrx9PDXYua0UJuJMAnPD2x8WkOGoOsJdO8e3xxuWAYzhDKn0fT fPHCU+CrGkI+Yo2LMDcX0vJi9kwNx7+v4P4DEpfrm9FrwZDB5JgrvvC2p5GXbrOWKUMGZz JQb2OBYrTpXGeIhpjOmiovOUH/YsG1NsPjLRRWa4Yy0BzCJWUXiMEVETW6A/jtSKcWwp4G xAzaCJ6MMFprZGTVJcTDa+0BoMHl/U8+pi6WmbVKBX1D6bHaHCACnxgqDY6cqeXCN2u/rg Mw7PaTuE6oKeDBAVUfVAq0ed/Ygg60pqAYU4TS5vhehvBIlQepQSVze9IH5QsQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775634527; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=dkK/64ebuCNeyYrLtZIPlvb4OYszPanHombdzSTdbAA=; b=TBaZo3wixSpjM5UQsz8TKBrXehpcIYJErENMA2CFv8lHpDZA7yj8GTxMn8pKocYFLD5jOC j5NQkXPxxZy+UNAmu+fpdxDXbwRUphQ41oMW92r1oYBGyVl+VPXIihM7YgwLjZGyt+ytsN OEUOka435We5NHk4HBqy5nRU8d+qz1apMu4uIatRRUBHruxhC/utLlEgfHc/VB35P/NyRU OqmXzhjM+UD9rBpfK/9aBn2OI7AbclwuQRW0/5OFRIgOQKmaG14SfcZDjg0cBYf42tCAFM AycUW/ycdr3RqcptRDRE71dSuiaOdVG3It8Ebr/LlQ7zHDXfHsIK6enXRqKWhA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4frFYq4Tqbz2MD for ; Wed, 08 Apr 2026 07:48:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3a62a by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 08 Apr 2026 07:48:47 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: ShengYi Hung Subject: git: 095cbb1bb7f7 - main - hwpstate_amd: Expose nodes as much as possible in legacy pstate List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: aokblast X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 095cbb1bb7f7b4f742b0a500aa2c61a8c97d4b41 Auto-Submitted: auto-generated Date: Wed, 08 Apr 2026 07:48:47 +0000 Message-Id: <69d6085f.3a62a.67b96686@gitrepo.freebsd.org> The branch main has been updated by aokblast: URL: https://cgit.FreeBSD.org/src/commit/?id=095cbb1bb7f7b4f742b0a500aa2c61a8c97d4b41 commit 095cbb1bb7f7b4f742b0a500aa2c61a8c97d4b41 Author: ShengYi Hung AuthorDate: 2026-04-08 07:45:11 +0000 Commit: ShengYi Hung CommitDate: 2026-04-08 07:48:34 +0000 hwpstate_amd: Expose nodes as much as possible in legacy pstate Reviewed by: olce Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D55606 --- sys/x86/cpufreq/hwpstate_amd.c | 156 ++++++++++++++++++++++++----------------- 1 file changed, 91 insertions(+), 65 deletions(-) diff --git a/sys/x86/cpufreq/hwpstate_amd.c b/sys/x86/cpufreq/hwpstate_amd.c index ccf13f06a6d1..4be295075482 100644 --- a/sys/x86/cpufreq/hwpstate_amd.c +++ b/sys/x86/cpufreq/hwpstate_amd.c @@ -552,6 +552,20 @@ hwpstate_amd_iscale(int val, int div) return (val); } +static void +hwpstate_pstate_read_limit(int cpu, uint64_t *msr) +{ + (void)x86_msr_op(MSR_AMD_10H_11H_LIMIT, + MSR_OP_READ | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpu), 0, msr); +} + +static void +hwpstate_pstate_read_status(int cpu, uint64_t *msr) +{ + (void)x86_msr_op(MSR_AMD_10H_11H_STATUS, + MSR_OP_READ | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpu), 0, msr); +} + /* * Go to Px-state on all cpus, considering the limit register (if so * configured). @@ -561,11 +575,13 @@ hwpstate_goto_pstate(device_t dev, int id) { sbintime_t sbt; uint64_t msr; - int cpu, i, j, limit; + int cpu, j, limit; + + cpu = cpu_get_pcpu(dev)->pc_cpuid; if (hwpstate_pstate_limit) { /* get the current pstate limit */ - msr = rdmsr(MSR_AMD_10H_11H_LIMIT); + hwpstate_pstate_read_limit(cpu, &msr); limit = AMD_10H_11H_GET_PSTATE_LIMIT(msr); if (limit > id) { HWPSTATE_DEBUG(dev, "Restricting requested P%d to P%d " @@ -574,53 +590,31 @@ hwpstate_goto_pstate(device_t dev, int id) } } - cpu = curcpu; HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, cpu); /* Go To Px-state */ - wrmsr(MSR_AMD_10H_11H_CONTROL, id); - - /* - * We are going to the same Px-state on all cpus. - * Probably should take _PSD into account. - */ - CPU_FOREACH(i) { - if (i == cpu) - continue; - - /* Bind to each cpu. */ - thread_lock(curthread); - sched_bind(curthread, i); - thread_unlock(curthread); - HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, i); - /* Go To Px-state */ - wrmsr(MSR_AMD_10H_11H_CONTROL, id); - } + x86_msr_op(MSR_AMD_10H_11H_CONTROL, + MSR_OP_WRITE | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpu), id, NULL); /* * Verify whether each core is in the requested P-state. */ if (hwpstate_verify) { - CPU_FOREACH(i) { - thread_lock(curthread); - sched_bind(curthread, i); - thread_unlock(curthread); - /* wait loop (100*100 usec is enough ?) */ - for (j = 0; j < 100; j++) { - /* get the result. not assure msr=id */ - msr = rdmsr(MSR_AMD_10H_11H_STATUS); - if (msr == id) - break; - sbt = SBT_1MS / 10; - tsleep_sbt(dev, PZERO, "pstate_goto", sbt, - sbt >> tc_precexp, 0); - } - HWPSTATE_DEBUG(dev, "result: P%d-state on cpu%d\n", - (int)msr, i); - if (msr != id) { - HWPSTATE_DEBUG(dev, - "error: loop is not enough.\n"); - return (ENXIO); - } + /* wait loop (100*100 usec is enough ?) */ + for (j = 0; j < 100; j++) { + /* get the result. not assure msr=id */ + + hwpstate_pstate_read_status(cpu, &msr); + if (msr == id) + break; + sbt = SBT_1MS / 10; + tsleep_sbt(dev, PZERO, "pstate_goto", sbt, + sbt >> tc_precexp, 0); + } + HWPSTATE_DEBUG(dev, "result: P%d-state on cpu%d\n", (int)msr, + cpu); + if (msr != id) { + HWPSTATE_DEBUG(dev, "error: loop is not enough.\n"); + return (ENXIO); } } @@ -670,7 +664,6 @@ hwpstate_get_cppc(device_t dev, struct cf_setting *cf) pc = cpu_get_pcpu(dev); if (pc == NULL) return (ENXIO); - memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf)); cf->dev = dev; if ((ret = cpu_est_clockrate(pc->pc_cpuid, &rate))) @@ -685,13 +678,14 @@ hwpstate_get_pstate(device_t dev, struct cf_setting *cf) struct hwpstate_softc *sc; struct hwpstate_setting set; uint64_t msr; + int cpu; sc = device_get_softc(dev); - msr = rdmsr(MSR_AMD_10H_11H_STATUS); + cpu = cpu_get_pcpu(dev)->pc_cpuid; + hwpstate_pstate_read_status(cpu, &msr); if (msr >= sc->cfnum) return (EINVAL); set = sc->hwpstate_settings[msr]; - cf->freq = set.freq; cf->volts = set.volts; cf->power = set.power; @@ -967,8 +961,10 @@ hwpstate_probe_pstate(device_t dev) device_t perf_dev; int error, type; uint64_t msr; + int cpu; sc = device_get_softc(dev); + cpu = cpu_get_pcpu(dev)->pc_cpuid; /* * Check if acpi_perf has INFO only flag. */ @@ -985,15 +981,15 @@ hwpstate_probe_pstate(device_t dev) */ HWPSTATE_DEBUG(dev, "acpi_perf will take care of pstate transitions.\n"); return (ENXIO); - } else { - /* - * If acpi_perf has INFO_ONLY flag, (_PCT has FFixedHW) - * we can get _PSS info from acpi_perf - * without going into ACPI. - */ - HWPSTATE_DEBUG(dev, "going to fetch info from acpi_perf\n"); - error = hwpstate_get_info_from_acpi_perf(dev, perf_dev); } + /* + * If acpi_perf has INFO_ONLY flag, (_PCT has FFixedHW) + * we can get _PSS info from acpi_perf + * without going into ACPI. + */ + HWPSTATE_DEBUG(dev, + "going to fetch info from acpi_perf\n"); + error = hwpstate_get_info_from_acpi_perf(dev, perf_dev); } } @@ -1002,7 +998,7 @@ hwpstate_probe_pstate(device_t dev) * Now we get _PSS info from acpi_perf without error. * Let's check it. */ - msr = rdmsr(MSR_AMD_10H_11H_LIMIT); + hwpstate_pstate_read_limit(cpu, &msr); if (sc->cfnum != 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr)) { HWPSTATE_DEBUG(dev, "MSR (%jd) and ACPI _PSS (%d)" " count mismatch\n", (intmax_t)msr, sc->cfnum); @@ -1042,15 +1038,8 @@ hwpstate_probe(device_t dev) sc->flags |= HWPFL_USE_CPPC; device_set_desc(dev, "AMD Collaborative Processor Performance Control (CPPC)"); - } else { - /* - * No CPPC support. Only keep hwpstate0, it goes well with - * acpi_throttle. - */ - if (device_get_unit(dev) != 0) - return (ENXIO); + } else device_set_desc(dev, "Cool`n'Quiet 2.0"); - } sc->dev = dev; if ((sc->flags & HWPFL_USE_CPPC) != 0) { @@ -1119,22 +1108,59 @@ hwpstate_attach(device_t dev) return (cpufreq_register(dev)); } +struct hwpstate_pstate_read_settings_cb { + struct hwpstate_softc *sc; + uint64_t *vals; + int err; +}; + +static void +hwpstate_pstate_read_settings_cb(void *args) +{ + struct hwpstate_pstate_read_settings_cb *req = args; + int i; + + req->err = 0; + for (i = 0; i < req->sc->cfnum; i++) { + req->err = rdmsr_safe(MSR_AMD_10H_11H_CONFIG + i, + &req->vals[i]); + if (req->err != 0) + return; + } +} + +static int +hwpstate_pstate_read_settings(struct hwpstate_softc *sc, uint64_t vals[]) +{ + struct hwpstate_pstate_read_settings_cb req; + device_t dev; + + req.sc = sc; + req.vals = vals; + dev = sc->dev; + smp_rendezvous_cpu(cpu_get_pcpu(dev)->pc_cpuid, + smp_no_rendezvous_barrier, hwpstate_pstate_read_settings_cb, + smp_no_rendezvous_barrier, &req); + return (req.err); +} + static int hwpstate_get_info_from_msr(device_t dev) { struct hwpstate_softc *sc; struct hwpstate_setting *hwpstate_set; - uint64_t msr; + uint64_t state_settings[AMD_10H_11H_MAX_STATES], msr; int family, i, fid, did; family = CPUID_TO_FAMILY(cpu_id); sc = device_get_softc(dev); /* Get pstate count */ - msr = rdmsr(MSR_AMD_10H_11H_LIMIT); + hwpstate_pstate_read_limit(cpu_get_pcpu(dev)->pc_cpuid, &msr); sc->cfnum = 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr); hwpstate_set = sc->hwpstate_settings; + hwpstate_pstate_read_settings(sc, state_settings); for (i = 0; i < sc->cfnum; i++) { - msr = rdmsr(MSR_AMD_10H_11H_CONFIG + i); + msr = state_settings[i]; if ((msr & ((uint64_t)1 << 63)) == 0) { HWPSTATE_DEBUG(dev, "msr is not valid.\n"); return (ENXIO);