svn commit: r357378 - in head/sys/x86: cpufreq include
Conrad Meyer
cem at FreeBSD.org
Sat Feb 1 19:49:14 UTC 2020
Author: cem
Date: Sat Feb 1 19:49:13 2020
New Revision: 357378
URL: https://svnweb.freebsd.org/changeset/base/357378
Log:
hwpstate_intel(4): Add fallback EPP using PERF_BIAS MSR
Per Intel SDM (Vol 3b Part 2), if HWP indicates EPP (energy-performance
preference) is not supported, the hardware instead uses the ENERGY_PERF_BIAS
MSR. In the epp sysctl handler, fall back to that MSR if HWP does not
support EPP and CPUID indicates the ENERGY_PERF_BIAS MSR is supported.
Modified:
head/sys/x86/cpufreq/hwpstate_intel.c
head/sys/x86/include/specialreg.h
Modified: head/sys/x86/cpufreq/hwpstate_intel.c
==============================================================================
--- head/sys/x86/cpufreq/hwpstate_intel.c Sat Feb 1 19:46:02 2020 (r357377)
+++ head/sys/x86/cpufreq/hwpstate_intel.c Sat Feb 1 19:49:13 2020 (r357378)
@@ -88,6 +88,7 @@ struct hwp_softc {
bool hwp_activity_window;
bool hwp_pref_ctrl;
bool hwp_pkg_ctrl;
+ bool hwp_perf_bias;
uint64_t req; /* Cached copy of last request */
@@ -215,6 +216,26 @@ raw_to_percent(int x)
return (round10(x * 1000 / 0xff));
}
+/* Range of MSR_IA32_ENERGY_PERF_BIAS is more limited: 0-0xf. */
+static inline int
+percent_to_raw_perf_bias(int x)
+{
+ /*
+ * Round up so that raw values present as nice round human numbers and
+ * also round-trip to the same raw value.
+ */
+ MPASS(x <= 100 && x >= 0);
+ return (((0xf * x) + 50) / 100);
+}
+
+static inline int
+raw_to_percent_perf_bias(int x)
+{
+ /* Rounding to nice human numbers despite a step interval of 6.67%. */
+ MPASS(x <= 0xf && x >= 0);
+ return (((x * 20) / 0xf) * 5);
+}
+
static int
sysctl_epp_select(SYSCTL_HANDLER_ARGS)
{
@@ -227,7 +248,7 @@ sysctl_epp_select(SYSCTL_HANDLER_ARGS)
dev = oidp->oid_arg1;
sc = device_get_softc(dev);
- if (!sc->hwp_pref_ctrl)
+ if (!sc->hwp_pref_ctrl && !sc->hwp_perf_bias)
return (ENODEV);
pc = cpu_get_pcpu(dev);
@@ -238,11 +259,24 @@ sysctl_epp_select(SYSCTL_HANDLER_ARGS)
sched_bind(curthread, pc->pc_cpuid);
thread_unlock(curthread);
- ret = rdmsr_safe(MSR_IA32_HWP_REQUEST, &requested);
- if (ret)
- goto out;
- val = (requested & IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE) >> 24;
- val = raw_to_percent(val);
+ if (sc->hwp_pref_ctrl) {
+ ret = rdmsr_safe(MSR_IA32_HWP_REQUEST, &requested);
+ if (ret)
+ goto out;
+ val = (requested & IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE) >> 24;
+ val = raw_to_percent(val);
+ } else {
+ /*
+ * If cpuid indicates EPP is not supported, the HWP controller
+ * uses MSR_IA32_ENERGY_PERF_BIAS instead (Intel SDM §14.4.4).
+ * This register is per-core (but not HT).
+ */
+ ret = rdmsr_safe(MSR_IA32_ENERGY_PERF_BIAS, &requested);
+ if (ret)
+ goto out;
+ val = requested & IA32_ENERGY_PERF_BIAS_POLICY_HINT_MASK;
+ val = raw_to_percent_perf_bias(val);
+ }
MPASS(val >= 0 && val <= 100);
@@ -255,12 +289,18 @@ sysctl_epp_select(SYSCTL_HANDLER_ARGS)
goto out;
}
- val = percent_to_raw(val);
+ if (sc->hwp_pref_ctrl) {
+ val = percent_to_raw(val);
- requested &= ~IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE;
- requested |= val << 24;
+ requested &= ~IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE;
+ requested |= val << 24;
- ret = wrmsr_safe(MSR_IA32_HWP_REQUEST, requested);
+ ret = wrmsr_safe(MSR_IA32_HWP_REQUEST, requested);
+ } else {
+ requested = percent_to_raw_perf_bias(val);
+ MPASS((requested & ~IA32_ENERGY_PERF_BIAS_POLICY_HINT_MASK) == 0);
+ ret = wrmsr_safe(MSR_IA32_ENERGY_PERF_BIAS, requested);
+ }
out:
thread_lock(curthread);
@@ -405,6 +445,7 @@ intel_hwpstate_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
+ /* eax */
if (cpu_power_eax & CPUTPM1_HWP_NOTIFICATION)
sc->hwp_notifications = true;
if (cpu_power_eax & CPUTPM1_HWP_ACTIVITY_WINDOW)
@@ -413,6 +454,10 @@ intel_hwpstate_attach(device_t dev)
sc->hwp_pref_ctrl = true;
if (cpu_power_eax & CPUTPM1_HWP_PKG)
sc->hwp_pkg_ctrl = true;
+
+ /* ecx */
+ if (cpu_power_ecx & CPUID_PERF_BIAS)
+ sc->hwp_perf_bias = true;
ret = set_autonomous_hwp(sc);
if (ret)
Modified: head/sys/x86/include/specialreg.h
==============================================================================
--- head/sys/x86/include/specialreg.h Sat Feb 1 19:46:02 2020 (r357377)
+++ head/sys/x86/include/specialreg.h Sat Feb 1 19:49:13 2020 (r357378)
@@ -812,6 +812,9 @@
#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE (0xffULL << 8)
#define IA32_HWP_MINIMUM_PERFORMANCE (0xffULL << 0)
+/* MSR IA32_ENERGY_PERF_BIAS */
+#define IA32_ENERGY_PERF_BIAS_POLICY_HINT_MASK (0xfULL << 0)
+
/*
* PAT modes.
*/
More information about the svn-src-head
mailing list