Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Merge T-state a.k.a. throttling support for acpicpu(4).
details: https://anonhg.NetBSD.org/src/rev/a90e56626bd9
branches: trunk
changeset: 757071:a90e56626bd9
user: jruoho <jruoho%NetBSD.org@localhost>
date: Fri Aug 13 16:21:50 2010 +0000
description:
Merge T-state a.k.a. throttling support for acpicpu(4).
Remarks:
1. Native instructions are supported only on Intel. Native support for
other x86 vendors will be investigated. By assumption, AMD and others
use the I/O based approach.
2. The existing code, INTEL_ONDEMAND_CLOCKMOD, must be disabled in
order to use acpicpu(4). Otherwise fatal MSR races may occur.
Unlike with P-states, no attempt is done to disable the existing
implementation.
3. There is no rationale to export controls to user land.
4. Throttling is an artefact from the past. T-states will not be used for
power management per se. For CPU frequency management, P-states are
preferred in all circumstances. No noticeable additional power savings
were observed in various experiments. When the system has been scaled
to the highest (i.e. lowest power) P-state, it is preferable to move
from C0 to deeper C-states than it is to actively throttle the CPU.
5. But T-states need to be implemented for passive cooling via acpitz(4).
As specified by ACPI and Intel documents, these can be used as the
last line of defence against critical thermal conditions. Support
for this will be added later.
diffstat:
sys/arch/x86/acpi/acpi_cpu_md.c | 112 ++++-
sys/dev/acpi/acpi_cpu.c | 20 +-
sys/dev/acpi/acpi_cpu.h | 58 ++-
sys/dev/acpi/acpi_cpu_cstate.c | 25 +-
sys/dev/acpi/acpi_cpu_pstate.c | 54 +-
sys/dev/acpi/acpi_cpu_tstate.c | 836 ++++++++++++++++++++++++++++++++++++++++
sys/dev/acpi/files.acpi | 3 +-
sys/modules/acpicpu/Makefile | 8 +-
8 files changed, 1048 insertions(+), 68 deletions(-)
diffs (truncated from 1453 to 300 lines):
diff -r b8bcfeddf6b8 -r a90e56626bd9 sys/arch/x86/acpi/acpi_cpu_md.c
--- a/sys/arch/x86/acpi/acpi_cpu_md.c Fri Aug 13 11:45:47 2010 +0000
+++ b/sys/arch/x86/acpi/acpi_cpu_md.c Fri Aug 13 16:21:50 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu_md.c,v 1.9 2010/08/09 15:46:17 jruoho Exp $ */
+/* $NetBSD: acpi_cpu_md.c,v 1.10 2010/08/13 16:21:50 jruoho Exp $ */
/*-
* Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.9 2010/08/09 15:46:17 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.10 2010/08/13 16:21:50 jruoho Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -52,6 +52,7 @@
static int acpicpu_md_pstate_sysctl_get(SYSCTLFN_PROTO);
static int acpicpu_md_pstate_sysctl_set(SYSCTLFN_PROTO);
static int acpicpu_md_pstate_sysctl_all(SYSCTLFN_PROTO);
+static int acpicpu_md_tstate_get_status(uint64_t *);
extern uint32_t cpus_running;
extern struct acpicpu_softc **acpicpu_sc;
@@ -78,11 +79,14 @@
val |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH;
/*
- * Set native P-states if EST is available.
+ * Set native P- and T-states, if available.
*/
if ((ci->ci_feat_val[1] & CPUID2_EST) != 0)
val |= ACPICPU_PDC_P_FFH;
+ if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0)
+ val |= ACPICPU_PDC_T_FFH;
+
return val;
}
@@ -107,6 +111,9 @@
if ((ci->ci_feat_val[1] & CPUID2_EST) != 0)
val |= ACPICPU_FLAG_P_FFH;
+ if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0)
+ val |= ACPICPU_FLAG_T_FFH;
+
/*
* Bus master arbitration is not
* needed on some recent Intel CPUs.
@@ -123,7 +130,7 @@
case CPUVENDOR_AMD:
/*
- * XXX: Deal with the AMD C1E extension here.
+ * XXX: Deal with PowerNow! and C1E here.
*/
break;
}
@@ -310,13 +317,6 @@
uint32_t freq;
int err;
- /*
- * We can use any ACPI CPU to manipulate the
- * frequencies. In MP environments all CPUs
- * are mandated to support the same number of
- * P-states and each state must have identical
- * parameters across processors.
- */
sc = acpicpu_sc[ci->ci_acpiid];
if (sc == NULL)
@@ -493,3 +493,93 @@
return EAGAIN;
}
+
+int
+acpicpu_md_tstate_get(struct acpicpu_softc *sc, uint32_t *percent)
+{
+ struct acpicpu_tstate *ts;
+ uint64_t val;
+ uint32_t i;
+ int rv;
+
+ rv = acpicpu_md_tstate_get_status(&val);
+
+ if (rv != 0)
+ return rv;
+
+ mutex_enter(&sc->sc_mtx);
+
+ for (i = 0; i < sc->sc_tstate_count; i++) {
+
+ ts = &sc->sc_tstate[i];
+
+ if (ts->ts_percent == 0)
+ continue;
+
+ if (val == ts->ts_control || val == ts->ts_status) {
+ mutex_exit(&sc->sc_mtx);
+ *percent = ts->ts_percent;
+ return 0;
+ }
+ }
+
+ mutex_exit(&sc->sc_mtx);
+
+ return EIO;
+}
+
+static int
+acpicpu_md_tstate_get_status(uint64_t *val)
+{
+
+ switch (cpu_vendor) {
+
+ case CPUVENDOR_INTEL:
+ *val = rdmsr(MSR_THERM_CONTROL);
+ break;
+
+ default:
+ return ENODEV;
+ }
+
+ return 0;
+}
+
+int
+acpicpu_md_tstate_set(struct acpicpu_tstate *ts)
+{
+ struct msr_rw_info msr;
+ uint64_t xc, val;
+ int i;
+
+ switch (cpu_vendor) {
+
+ case CPUVENDOR_INTEL:
+ msr.msr_read = true;
+ msr.msr_type = MSR_THERM_CONTROL;
+ msr.msr_value = ts->ts_control;
+ msr.msr_mask = __BITS(1, 4);
+ break;
+
+ default:
+ return ENODEV;
+ }
+
+ xc = xc_broadcast(0, (xcfunc_t)x86_msr_xcall, &msr, NULL);
+ xc_wait(xc);
+
+ if (ts->ts_status == 0)
+ return 0;
+
+ for (i = val = 0; i < ACPICPU_T_STATE_RETRY; i++) {
+
+ (void)acpicpu_md_tstate_get_status(&val);
+
+ if (val == ts->ts_status)
+ return 0;
+
+ DELAY(ts->ts_latency);
+ }
+
+ return EAGAIN;
+}
diff -r b8bcfeddf6b8 -r a90e56626bd9 sys/dev/acpi/acpi_cpu.c
--- a/sys/dev/acpi/acpi_cpu.c Fri Aug 13 11:45:47 2010 +0000
+++ b/sys/dev/acpi/acpi_cpu.c Fri Aug 13 16:21:50 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu.c,v 1.14 2010/08/11 16:22:18 jruoho Exp $ */
+/* $NetBSD: acpi_cpu.c,v 1.15 2010/08/13 16:21:50 jruoho Exp $ */
/*-
* Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.14 2010/08/11 16:22:18 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.15 2010/08/13 16:21:50 jruoho Exp $");
#include <sys/param.h>
#include <sys/cpu.h>
@@ -157,9 +157,11 @@
acpicpu_cstate_attach(self);
acpicpu_pstate_attach(self);
+ acpicpu_tstate_attach(self);
(void)config_finalize_register(self, acpicpu_cstate_start);
(void)config_finalize_register(self, acpicpu_pstate_start);
+ (void)config_finalize_register(self, acpicpu_tstate_start);
(void)acpi_register_notify(sc->sc_node, acpicpu_notify);
(void)pmf_device_register(self, acpicpu_suspend, acpicpu_resume);
@@ -191,6 +193,12 @@
if (rv != 0)
return rv;
+ if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
+ rv = acpicpu_tstate_detach(self);
+
+ if (rv != 0)
+ return rv;
+
rv = RUN_ONCE(&once_detach, acpicpu_once_detach);
if (rv != 0)
@@ -469,7 +477,7 @@
if ((sc->sc_flags & ACPICPU_FLAG_T) == 0)
return;
- func = NULL;
+ func = acpicpu_tstate_callback;
break;
default:
@@ -493,6 +501,9 @@
if ((sc->sc_flags & ACPICPU_FLAG_P) != 0)
(void)acpicpu_pstate_suspend(self);
+ if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
+ (void)acpicpu_tstate_suspend(self);
+
return true;
}
@@ -507,6 +518,9 @@
if ((sc->sc_flags & ACPICPU_FLAG_P) != 0)
(void)acpicpu_pstate_resume(self);
+ if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
+ (void)acpicpu_tstate_resume(self);
+
sc->sc_cold = false;
return true;
diff -r b8bcfeddf6b8 -r a90e56626bd9 sys/dev/acpi/acpi_cpu.h
--- a/sys/dev/acpi/acpi_cpu.h Fri Aug 13 11:45:47 2010 +0000
+++ b/sys/dev/acpi/acpi_cpu.h Fri Aug 13 16:21:50 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu.h,v 1.13 2010/08/11 11:48:21 jruoho Exp $ */
+/* $NetBSD: acpi_cpu.h,v 1.14 2010/08/13 16:21:50 jruoho Exp $ */
/*-
* Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -35,15 +35,6 @@
*
* Intel Corporation: Intel Processor-Specific ACPI
* Interface Specification, September 2006, Revision 005.
- *
- * http://download.intel.com/technology/IAPC/acpi/downloads/30222305.pdf
- *
- * For other relevant reading, see for instance:
- *
- * Advanced Micro Devices: Using ACPI to Report APML P-State
- * Limit Changes to Operating Systems and VMM's. August 7, 2009.
- *
- * http://developer.amd.com/Assets/ACPI-APML-PState-rev12.pdf
*/
#define ACPICPU_PDC_REVID 0x1
#define ACPICPU_PDC_SMP 0xA
@@ -89,23 +80,31 @@
#define ACPICPU_P_STATE_UNKNOWN 0x0
/*
+ * T-states.
+ */
+#define ACPICPU_T_STATE_MAX 0x8
+#define ACPICPU_T_STATE_RETRY 0xA
+#define ACPICPU_T_STATE_UNKNOWN 255
+
+/*
* Flags.
*/
#define ACPICPU_FLAG_C __BIT(0) /* C-states supported */
#define ACPICPU_FLAG_P __BIT(1) /* P-states supported */
#define ACPICPU_FLAG_T __BIT(2) /* T-states supported */
-#define ACPICPU_FLAG_C_CST __BIT(3) /* C-states with _CST */
+#define ACPICPU_FLAG_C_FFH __BIT(3) /* Native C-states */
#define ACPICPU_FLAG_C_FADT __BIT(4) /* C-states with FADT */
#define ACPICPU_FLAG_C_BM __BIT(5) /* Bus master control */
#define ACPICPU_FLAG_C_BM_STS __BIT(6) /* Bus master check required */
#define ACPICPU_FLAG_C_ARB __BIT(7) /* Bus master arbitration */
#define ACPICPU_FLAG_C_NOC3 __BIT(8) /* C3 disabled (quirk) */
-#define ACPICPU_FLAG_C_FFH __BIT(9) /* MONITOR/MWAIT supported */
-#define ACPICPU_FLAG_C_C1E __BIT(10) /* AMD C1E detected */
+#define ACPICPU_FLAG_C_C1E __BIT(9) /* AMD C1E detected */
-#define ACPICPU_FLAG_P_PPC __BIT(11) /* Dynamic freq. with _PPC */
-#define ACPICPU_FLAG_P_FFH __BIT(12) /* EST etc. supported */
+#define ACPICPU_FLAG_P_FFH __BIT(10) /* Native P-states */
+
+#define ACPICPU_FLAG_T_FFH __BIT(11) /* Native throttling */
+#define ACPICPU_FLAG_T_FADT __BIT(12) /* Throttling with FADT */
Home |
Main Index |
Thread Index |
Old Index