Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Merge a driver for ACPI CPUs with basic support for proc...



details:   https://anonhg.NetBSD.org/src/rev/62a1f1ea354e
branches:  trunk
changeset: 756442:62a1f1ea354e
user:      jruoho <jruoho%NetBSD.org@localhost>
date:      Sun Jul 18 09:29:11 2010 +0000

description:
Merge a driver for ACPI CPUs with basic support for processor power states,
also known as C-states. The code is modular and provides an easy way to add
the remaining functionality later (namely throttling and P-states).

Remarks:

  1.    Commented out in the GENERICs; more testing exposure is needed.

  2.    The C3-state is disabled for the time being because it turns off
        timers, among them the local APIC timer. This may not be universally
        true on all x86 processors; define ACPICPU_ENABLE_C3 to test.

  3.    The algorithm used to choose a power state may need tuning. When
        evaluating the appropriate state, the implementation uses the
        previous sleep time as an indicator. Additional hints would include
        for example the system load.

        Also bus master activity is evaluated when choosing a state. The
        usb(4) stack is notorious for such activity even when unused.
        Typically it must be disabled in order to reach the C3-state,
        but it may also prevent the use of C2.

  4.    While no extensive empirical measurements have been carried out, the
        power savings are somewhere between 1-2 W with C1 and C2, depending
        on the processor, firmware, and load. With C3 even up to 4 W can be
        saved.  The less something ticks, the more power is saved.

ok jmcneill@, joerg@, and discussed with various people.

diffstat:

 sys/arch/amd64/conf/GENERIC     |    5 +-
 sys/arch/i386/conf/GENERIC      |    5 +-
 sys/arch/x86/acpi/acpi_cpu_md.c |  187 ++++++++
 sys/arch/x86/conf/files.x86     |    6 +-
 sys/arch/x86/include/machdep.h  |   12 +-
 sys/arch/x86/x86/x86_machdep.c  |   35 +-
 sys/dev/acpi/acpi.c             |    7 +-
 sys/dev/acpi/acpi_cpu.c         |  567 ++++++++++++++++++++++++++
 sys/dev/acpi/acpi_cpu.h         |  140 ++++++
 sys/dev/acpi/acpi_cpu_cstate.c  |  859 ++++++++++++++++++++++++++++++++++++++++
 sys/dev/acpi/files.acpi         |    8 +-
 11 files changed, 1805 insertions(+), 26 deletions(-)

diffs (truncated from 1977 to 300 lines):

diff -r 1bbe89ce2d9a -r 62a1f1ea354e sys/arch/amd64/conf/GENERIC
--- a/sys/arch/amd64/conf/GENERIC       Sun Jul 18 07:07:08 2010 +0000
+++ b/sys/arch/amd64/conf/GENERIC       Sun Jul 18 09:29:11 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.281 2010/06/02 18:05:28 dholland Exp $
+# $NetBSD: GENERIC,v 1.282 2010/07/18 09:29:11 jruoho Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@
 
 options        INCLUDE_CONFIG_FILE     # embed config file in kernel binary
 
-#ident                 "GENERIC-$Revision: 1.281 $"
+#ident                 "GENERIC-$Revision: 1.282 $"
 
 maxusers       64              # estimated number of users
 
@@ -274,6 +274,7 @@
 acpiacad*      at acpi?                # ACPI AC Adapter
 acpibat*       at acpi?                # ACPI Battery
 acpibut*       at acpi?                # ACPI Button
+#acpicpu*      at acpi?                # ACPI CPU
 acpidalb*      at acpi?                # Direct Application Launch Button
 # The ACPI Embedded Controller is generally configured via the special ECDT.
 # This is required as parts of the DSDT can reference the EC before the normal
diff -r 1bbe89ce2d9a -r 62a1f1ea354e sys/arch/i386/conf/GENERIC
--- a/sys/arch/i386/conf/GENERIC        Sun Jul 18 07:07:08 2010 +0000
+++ b/sys/arch/i386/conf/GENERIC        Sun Jul 18 09:29:11 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.986 2010/06/26 15:17:56 kefren Exp $
+# $NetBSD: GENERIC,v 1.987 2010/07/18 09:29:12 jruoho Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@
 
 options        INCLUDE_CONFIG_FILE     # embed config file in kernel binary
 
-#ident                 "GENERIC-$Revision: 1.986 $"
+#ident                 "GENERIC-$Revision: 1.987 $"
 
 maxusers       64              # estimated number of users
 
@@ -353,6 +353,7 @@
 acpiacad*      at acpi?                # ACPI AC Adapter
 acpibat*       at acpi?                # ACPI Battery
 acpibut*       at acpi?                # ACPI Button
+#acpicpu*      at acpi?                # ACPI CPU
 acpidalb*      at acpi?                # ACPI Direct Application Launch Button
 # The ACPI Embedded Controller is generally configured via the special ECDT.
 # This is required as parts of the DSDT can reference the EC before the normal
diff -r 1bbe89ce2d9a -r 62a1f1ea354e sys/arch/x86/acpi/acpi_cpu_md.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/x86/acpi/acpi_cpu_md.c   Sun Jul 18 09:29:11 2010 +0000
@@ -0,0 +1,187 @@
+/* $NetBSD */
+
+/*-
+ * Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.1 2010/07/18 09:29:13 jruoho Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kcore.h>
+
+#include <x86/cpu.h>
+#include <x86/cpuvar.h>
+#include <x86/machdep.h>
+#include <x86/cputypes.h>
+
+#include <dev/acpi/acpica.h>
+#include <dev/acpi/acpi_cpu.h>
+
+static char    native_idle_text[16];
+void         (*native_idle)(void) = NULL;
+
+extern uint32_t        cpus_running;
+
+uint32_t
+acpicpu_md_cap(void)
+{
+       struct cpu_info *ci = curcpu();
+       uint32_t val = 0;
+
+       if (cpu_vendor != CPUVENDOR_INTEL)
+               return val;
+
+       /*
+        * Basic SMP C-states (required for _CST).
+        */
+       val |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3;
+
+        /*
+        * If MONITOR/MWAIT is available, announce
+        * support for native instructions in all C-states.
+        */
+        if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
+               val |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH;
+
+       return val;
+}
+
+uint32_t
+acpicpu_md_quirks(void)
+{
+       struct cpu_info *ci = curcpu();
+       uint32_t val = 0;
+
+       if (acpicpu_md_cpus_running() == 1)
+               val |= ACPICPU_FLAG_C_BM;
+
+       if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
+               val |= ACPICPU_FLAG_C_MWAIT;
+
+       switch (cpu_vendor) {
+
+       case CPUVENDOR_INTEL:
+               val |= ACPICPU_FLAG_C_BM | ACPICPU_FLAG_C_ARB;
+
+               /*
+                * Bus master arbitration is not
+                * needed on some recent Intel CPUs.
+                */
+               if (CPUID2FAMILY(ci->ci_signature) > 15)
+                       val &= ~ACPICPU_FLAG_C_ARB;
+
+               if (CPUID2FAMILY(ci->ci_signature) == 6 &&
+                   CPUID2MODEL(ci->ci_signature) >= 15)
+                       val &= ~ACPICPU_FLAG_C_ARB;
+
+               break;
+
+       case CPUVENDOR_AMD:
+
+               /*
+                * XXX: Deal with the AMD C1E extension here.
+                */
+               break;
+       }
+
+       return val;
+}
+
+uint32_t
+acpicpu_md_cpus_running(void)
+{
+
+       return popcount32(cpus_running);
+}
+
+int
+acpicpu_md_idle_init(void)
+{
+       const size_t size = sizeof(native_idle_text);
+
+       KASSERT(native_idle == NULL);
+
+       x86_disable_intr();
+       x86_cpu_idle_get(&native_idle, native_idle_text, size);
+       x86_enable_intr();
+
+       return 0;
+}
+
+int
+acpicpu_md_idle_start(void)
+{
+
+       KASSERT(native_idle != NULL);
+       KASSERT(native_idle_text[0] != '\0');
+
+       x86_disable_intr();
+       x86_cpu_idle_set(acpicpu_cstate_idle, "acpi");
+       x86_enable_intr();
+
+       DELAY(10000);
+
+       return 0;
+}
+
+int
+acpicpu_md_idle_stop(void)
+{
+
+       KASSERT(native_idle != NULL);
+       KASSERT(native_idle_text[0] != '\0');
+
+       x86_disable_intr();
+       x86_cpu_idle_set(native_idle, native_idle_text);
+       x86_enable_intr();
+
+       DELAY(10000);
+
+       return 0;
+}
+
+void
+acpicpu_md_idle_enter(int method, int state)
+{
+
+       KASSERT(native_idle != NULL);
+
+       switch (method) {
+
+       case ACPICPU_C_STATE_FFH:
+               x86_mwait((state - 1) << 4, 0);
+               break;
+
+       case ACPICPU_C_STATE_HALT:
+               x86_stihlt();
+               break;
+
+       default:
+               (*native_idle)();
+               break;
+       }
+}
diff -r 1bbe89ce2d9a -r 62a1f1ea354e sys/arch/x86/conf/files.x86
--- a/sys/arch/x86/conf/files.x86       Sun Jul 18 07:07:08 2010 +0000
+++ b/sys/arch/x86/conf/files.x86       Sun Jul 18 09:29:11 2010 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.x86,v 1.55 2010/07/08 11:24:59 rmind Exp $
+#      $NetBSD: files.x86,v 1.56 2010/07/18 09:29:12 jruoho Exp $
 
 # options for MP configuration through the MP spec
 defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI
@@ -88,8 +88,10 @@
 # MP configuration using ACPI
 file   arch/x86/x86/mpacpi.c           acpi
 
+file   arch/x86/x86/acpi_machdep.c     acpi
+
 file   arch/x86/acpi/acpi_wakeup.c     acpi
-file   arch/x86/x86/acpi_machdep.c     acpi
+file   arch/x86/acpi/acpi_cpu_md.c     acpi & acpicpu
 
 file   arch/x86/isa/isa_machdep.c      isa
 
diff -r 1bbe89ce2d9a -r 62a1f1ea354e sys/arch/x86/include/machdep.h
--- a/sys/arch/x86/include/machdep.h    Sun Jul 18 07:07:08 2010 +0000
+++ b/sys/arch/x86/include/machdep.h    Sun Jul 18 09:29:11 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.h,v 1.2 2008/12/15 22:20:52 cegger Exp $ */
+/* $NetBSD: machdep.h,v 1.3 2010/07/18 09:29:12 jruoho Exp $ */
 /*
  * Copyright (c) 2000, 2007 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -34,8 +34,12 @@
 struct btinfo_memmap;
 struct extent;
 
-int initx86_parse_memmap(struct btinfo_memmap *, struct extent *);
-int initx86_fake_memmap(struct extent *);
-int initx86_load_memmap(paddr_t first_avail);
+void   x86_cpu_idle_init(void);
+void   x86_cpu_idle_get(void (**)(void), char *, size_t);
+void   x86_cpu_idle_set(void (*)(void), const char *);
+
+int    initx86_parse_memmap(struct btinfo_memmap *, struct extent *);
+int    initx86_fake_memmap(struct extent *);
+int    initx86_load_memmap(paddr_t first_avail);
 
 #endif /* _X86_MACHDEP_H_ */
diff -r 1bbe89ce2d9a -r 62a1f1ea354e sys/arch/x86/x86/x86_machdep.c
--- a/sys/arch/x86/x86/x86_machdep.c    Sun Jul 18 07:07:08 2010 +0000
+++ b/sys/arch/x86/x86/x86_machdep.c    Sun Jul 18 09:29:11 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: x86_machdep.c,v 1.41 2010/06/02 09:43:12 joerg Exp $   */
+/*     $NetBSD: x86_machdep.c,v 1.42 2010/07/18 09:29:12 jruoho Exp $  */
 
 /*-
  * Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi,
@@ -31,7 +31,7 @@
  */



Home | Main Index | Thread Index | Old Index