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