<I should post the draft one week ago.
I fighted with my box these days, and finally it refused to work for me.
What a pity, currently it's the only machine supporting deeper C-state,
;( > 

The proposed driver was roughly tested on both machines supporting and
not supporting deeper c-state.
Before I checked into repo, I'd like to see your comments and
suggestions. No wonder you see something ugly,
It's really a draft for now.
See below and attached.

Thanks,
-Aubrey

=========================
diff -r 779c86b8bbe0 usr/src/uts/common/os/cpu.c
--- a/usr/src/uts/common/os/cpu.c       Fri Dec 07 23:46:46 2007 -0500
+++ b/usr/src/uts/common/os/cpu.c       Thu Dec 13 15:17:35 2007 +0800
@@ -2110,6 +2110,7 @@ static struct {
        kstat_named_t ci_clogid;
        kstat_named_t ci_ncpuperchip;
        kstat_named_t ci_ncoreperchip;
+       kstat_named_t ci_max_cstates;
 #endif
 } cpu_info_template = {
        { "state",                      KSTAT_DATA_CHAR },
@@ -2135,6 +2136,7 @@ static struct {
        { "clog_id",                    KSTAT_DATA_INT32 },
        { "ncpu_per_chip",              KSTAT_DATA_INT32 },
        { "ncore_per_chip",             KSTAT_DATA_INT32 },
+       { "supported_max_cstates",      KSTAT_DATA_INT32 },
 #endif
 };
 
@@ -2203,6 +2205,7 @@ cpu_info_kstat_update(kstat_t *ksp, int 
        cpu_info_template.ci_ncpuperchip.value.l =
cpuid_get_ncpu_per_chip(cp);
        cpu_info_template.ci_ncoreperchip.value.l =
            cpuid_get_ncore_per_chip(cp);
+       cpu_info_template.ci_ncoreperchip.value.l = cp->cpu_max_cstates;
 #endif
 
        return (0);
diff -r 779c86b8bbe0 usr/src/uts/common/sys/cpudrv.h
--- a/usr/src/uts/common/sys/cpudrv.h   Fri Dec 07 23:46:46 2007 -0500
+++ b/usr/src/uts/common/sys/cpudrv.h   Thu Dec 13 15:17:35 2007 +0800
@@ -89,9 +89,15 @@ typedef struct cpudrv_pm {
        kcondvar_t      timeout_cv;     /* wait on timeout_count change
*/
 #if defined(__x86)
        kthread_t       *pm_throttle_thread; /* throttling thread */
+       uint_t          max_cstates;    /* supported max_cstates */
 #endif
        boolean_t       pm_started;     /* PM really started */
+       uint_t          pm_cap;         /* PM capabilities */
 } cpudrv_pm_t;
+
+#define        OSPM_C_STATES   0x01
+#define        OSPM_P_STATES   0x02
+#define        OSPM_T_STATES   0x04
 
 /*
  * Idle & user threads water marks in percentage
diff -r 779c86b8bbe0 usr/src/uts/common/sys/cpuvar.h
--- a/usr/src/uts/common/sys/cpuvar.h   Fri Dec 07 23:46:46 2007 -0500
+++ b/usr/src/uts/common/sys/cpuvar.h   Thu Dec 13 15:17:35 2007 +0800
@@ -212,6 +212,7 @@ typedef struct cpu {
 
        uint64_t        cpu_curr_clock;         /* current clock freq in
Hz */
        char            *cpu_supp_freqs;        /* supported freqs in Hz
*/
+       int32_t         cpu_max_cstates;        /* supported max cstates
*/
 
        /*
         * Interrupt load factor used by dispatcher & softcall
diff -r 779c86b8bbe0 usr/src/uts/i86pc/Makefile.files
--- a/usr/src/uts/i86pc/Makefile.files  Fri Dec 07 23:46:46 2007 -0500
+++ b/usr/src/uts/i86pc/Makefile.files  Thu Dec 13 15:17:35 2007 +0800
@@ -177,7 +177,7 @@ MCAMD_OBJS  += \
        mcamd_subr.o \
        mcamd_pcicfg.o
 
-CPUDRV_OBJS    += cpudrv.o cpudrv_plat.o cpu_acpi.o speedstep.o
cpudrv_intel.o
+CPUDRV_OBJS    += cpudrv.o cpudrv_plat.o cpu_acpi.o cpu_idle.o
speedstep.o cpudrv_intel.o
 PPM_OBJS       += ppm_subr.o ppm.o ppm_plat.o
 
 ACPIPPM_OBJS   += acpippm.o acpisleep.o
diff -r 779c86b8bbe0 usr/src/uts/i86pc/io/cpu_acpi.c
--- a/usr/src/uts/i86pc/io/cpu_acpi.c   Fri Dec 07 23:46:46 2007 -0500
+++ b/usr/src/uts/i86pc/io/cpu_acpi.c   Thu Dec 13 15:17:35 2007 +0800
@@ -368,6 +368,63 @@ cpu_acpi_cache_ppc(cpu_acpi_handle_t han
        AcpiOsFree(abuf.Pointer);
 }
 
+int
+cpu_acpi_cache_cst(cpu_acpi_handle_t handle)
+{
+       ACPI_BUFFER abuf;
+       ACPI_OBJECT *obj;
+       ACPI_INTEGER count;
+       cpu_acpi_cstate_t *cstate;
+       int i;
+
+       abuf.Length = ACPI_ALLOCATE_BUFFER;
+       abuf.Pointer = NULL;
+
+       if (ACPI_FAILURE(AcpiEvaluateObject(handle->cs_handle, "_CST",
+               NULL, &abuf))) {
+                       cmn_err(CE_NOTE, "!cpu_acpi: _CST evaluate
failure");
+               return (-1);
+       }
+       obj = (ACPI_OBJECT *)abuf.Pointer;
+       if (obj->Package.Count < 2) {
+               cmn_err(CE_NOTE, "!cpu_acpi: _CST package bad count
%d.",
+                       obj->Package.Count);
+               goto out;
+       }
+
+       count = obj->Package.Elements[0].Integer.Value;
+       if (count < 1 || count != obj->Package.Count - 1) {
+               cmn_err(CE_NOTE, "!cpu_acpi: _CST is not valid\n");
+               goto out;
+       }
+       handle->cs_cstates = kmem_zalloc(sizeof (cpu_acpi_cstates_t),
KM_SLEEP);
+       handle->cs_cstates->cst_count = count;
+       handle->cs_cstates->cst_cstates = kmem_zalloc(sizeof
(cpu_acpi_cstate_t)
+               * count, KM_SLEEP);
+       cstate = handle->cs_cstates->cst_cstates;
+       for (i = 1; i <=count; i++) {
+               ACPI_OBJECT *pkg;
+               AML_RESOURCE_GENERIC_REGISTER *reg;
+               ACPI_OBJECT *element;
+               pkg = &(obj->Package.Elements[i]);
+               reg = (AML_RESOURCE_GENERIC_REGISTER *)
+                       pkg->Package.Elements[0].Buffer.Pointer;
+               cstate->cs_addrspace_id = reg->AddressSpaceId;
+               cstate->cs_address = reg->Address;
+               element = &(pkg->Package.Elements[1]);
+               cstate->cs_type = element->Integer.Value;
+               element = &(pkg->Package.Elements[2]);
+               cstate->cs_latency = element->Integer.Value;
+               element = &(pkg->Package.Elements[3]);
+               cstate->cs_power = element->Integer.Value;
+               cstate++;
+       }
+
+out:
+       AcpiOsFree(abuf.Pointer);
+       return (0);
+}
+
 /*
  * Cache the _PCT, _PSS, _PSD and _PPC data.
  */
@@ -508,3 +565,13 @@ cpu_acpi_free_speeds(int *speeds, uint_t
 {
        kmem_free(speeds, nspeeds * sizeof (int));
 }
+
+uint_t
+cpu_acpi_get_max_cstates(cpu_acpi_handle_t handle)
+{
+       cpu_acpi_cstates_t *cstates = handle->cs_cstates;
+       if (cstates)
+               return (cstates->cst_count);
+       else
+               return (1);
+}
diff -r 779c86b8bbe0 usr/src/uts/i86pc/io/cpu_idle.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/io/cpu_idle.c   Thu Dec 13 15:18:16 2007 +0800
@@ -0,0 +1,68 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident  "%Z%%M% %I%     %E% SMI"
+
+#include <sys/x86_archext.h>
+#include <sys/machsystm.h>
+#include <sys/x_call.h>
+#include <sys/acpi/acpi.h>
+#include <sys/acpica.h>
+#include <sys/cpudrv.h>
+#include <sys/cpu_idle.h>
+#include <sys/cpu_acpi.h>
+#include <sys/cpupm.h>
+#include <sys/dtrace.h>
+#include <sys/sdt.h>
+
+static int cpu_idle_init(cpudrv_devstate_t *);
+
+/*
+ * Interfaces for modules implementing Intel's Enhanced SpeedStep.
+ */
+struct cpudrv_cstate_ops cpu_idle_ops = {
+       cpu_idle_init,
+};
+
+/*
+ * Validate that this processor supports Speedstep and if so,
+ * get the P-state data from ACPI and cache it.
+ */
+static int
+cpu_idle_init(cpudrv_devstate_t *cpudsp)
+{
+       cpu_acpi_handle_t handle = cpudsp->acpi_handle;
+
+       /*
+        * Cache the C-state specific ACPI data.
+        */
+       if (cpu_acpi_cache_cst(handle) != 0) {
+               cmn_err(CE_WARN, "Failed to cache ACPI data\n");
+               cpu_acpi_fini(handle);
+               return (-1);
+       }
+
+       return (0);
+}
diff -r 779c86b8bbe0 usr/src/uts/i86pc/io/cpudrv_intel.c
--- a/usr/src/uts/i86pc/io/cpudrv_intel.c       Fri Dec 07 23:46:46 2007
-0500
+++ b/usr/src/uts/i86pc/io/cpudrv_intel.c       Thu Dec 13 15:17:35 2007
+0800
@@ -33,6 +33,7 @@
 #include <sys/cpudrv_vendor.h>
 #include <sys/cpu_acpi.h>
 #include <sys/speedstep.h>
+#include <sys/cpu_idle.h>
 
 /*
  * The Intel Processor Driver Capabilities (_PDC).
@@ -42,8 +43,16 @@
  */
 #define        CPUDRV_INTEL_PDC_REVISION       0x1
 #define        CPUDRV_INTEL_PDC_PS_MSR         (1<<0)
+#define        CPUDRV_INTEL_PDC_C1_HALT        (1<<1)
+#define        CPUDRV_INTEL_PDC_TS_MSR         (1<<2)
 #define        CPUDRV_INTEL_PDC_MP             (1<<3)
+#define        CPUDRV_INTEL_PDC_C2C3           (1<<4)
 #define        CPUDRV_INTEL_PDC_PSD            (1<<5)
+#define        CPUDRV_INTEL_PDC_CSD            (1<<6)
+#define        CPUDRV_INTEL_PDC_TSD            (1<<7)
+#define        CPUDRV_INTEL_PDC_NATIVE_C1      (1<<8)
+#define        CPUDRV_INTEL_PDC_NATIVE_C2C3    (1<<9)
+#define        CPUDRV_INTEL_PDC_HW_PS          (1<<11)
 
 static uint32_t cpudrv_intel_pdccap = 0;
 
@@ -84,8 +93,9 @@ intel_cpupm_init(cpudrv_devstate_t *cpud
         * Set the correct cstate_ops for the processor and
         * enable appropriate _PDC bits.
         */
-       cpuvops->cpupm_cstate_ops = NULL;       /* XXX until we support
*/
-       cpudrv_intel_pdccap |= 0;               /* XXX until we support
*/
+       cpuvops->cpupm_cstate_ops = &cpu_idle_ops;
+       cpudrv_intel_pdccap |= CPUDRV_INTEL_PDC_C1_HALT |
+                   CPUDRV_INTEL_PDC_C2C3;
 
        handle = cpudsp->acpi_handle = cpu_acpi_init(cpudsp->dip);
        if (handle == NULL) {
diff -r 779c86b8bbe0 usr/src/uts/i86pc/io/cpudrv_plat.c
--- a/usr/src/uts/i86pc/io/cpudrv_plat.c        Fri Dec 07 23:46:46 2007
-0500
+++ b/usr/src/uts/i86pc/io/cpudrv_plat.c        Thu Dec 13 15:17:35 2007
+0800
@@ -35,6 +35,7 @@
 #include <sys/cpudrv_plat.h>
 #include <sys/cpudrv.h>
 #include <sys/speedstep.h>
+#include <sys/cpu_idle.h>
 #include <sys/machsystm.h>
 
 /*
@@ -118,6 +119,9 @@ cpudrv_pm_init_module(cpudrv_devstate_t 
 cpudrv_pm_init_module(cpudrv_devstate_t *cpudsp)
 {
        cpudrv_vendor_t *vendor;
+       cpudrv_pm_t *cpupm = &(cpudsp->cpudrv_pm);
+       uint_t cpu_max_cstates;
+       cpu_t *cp;
        int ret;
 
        /*
@@ -148,15 +152,33 @@ cpudrv_pm_init_module(cpudrv_devstate_t 
                            " unable to initialize P-state support",
                            ddi_get_instance(cpudsp->dip));
                        cpuvops->cpupm_pstate_ops = NULL;
-                       return (B_FALSE);
                }
+               cpupm->pm_cap |= OSPM_P_STATES;
+       }
+
+       /*
+        * Until C-state and T-state are added, we'll return false here.
+        */
+       if (cpuvops->cpupm_cstate_ops != NULL) {
+               ret = cpuvops->cpupm_cstate_ops->cpucs_init(cpudsp);
+               if (ret !=0) {
+                       cmn_err(CE_WARN, "!cpudrv_pm_init_module:
instance %d:"
+                           " unable to initialize C-state support",
+                           ddi_get_instance(cpudsp->dip));
+                       cpuvops->cpupm_cstate_ops = NULL;
+               }
+               cpupm->pm_cap |= OSPM_C_STATES;
+       }
+
+       CPUDRV_PM_GET_MAX_CSTATES(cpudsp, cpu_max_cstates);
+       cpupm->max_cstates = cpu_max_cstates;
+
+       if (cpupm->pm_cap & (OSPM_P_STATES | OSPM_C_STATES)) {
                return (B_TRUE);
-       }
-
-       /*
-        * Until C-state and T-state are added, we'll return false here.
-        */
-       return (B_FALSE);
+       } else {
+               cpu_acpi_fini(cpudsp->acpi_handle);
+               return (B_FALSE);
+       }
 }
 
 /*
diff -r 779c86b8bbe0 usr/src/uts/i86pc/sys/cpu_acpi.h
--- a/usr/src/uts/i86pc/sys/cpu_acpi.h  Fri Dec 07 23:46:46 2007 -0500
+++ b/usr/src/uts/i86pc/sys/cpu_acpi.h  Thu Dec 13 15:17:35 2007 +0800
@@ -105,6 +105,23 @@ typedef int cpu_acpi_ppc_t;
 typedef int cpu_acpi_ppc_t;
 
 /*
+ * Container for _CST information
+ */
+typedef struct cpu_acpi_cstate
+{
+       uint32_t cs_addrspace_id;
+       uint32_t cs_address;
+       uint32_t cs_type;
+       uint32_t cs_latency;
+       uint32_t cs_power;
+} cpu_acpi_cstate_t;
+
+typedef struct cpu_acpi_cstates {
+       cpu_acpi_cstate_t *cst_cstates;
+       uint32_t cst_count;
+} cpu_acpi_cstates_t;
+
+/*
  * Container for cached ACPI data.
  */
 typedef struct cpu_acpi_state {
@@ -112,6 +129,7 @@ typedef struct cpu_acpi_state {
        dev_info_t *cs_dip;
        uint_t cpu_acpi_cached;
        cpu_acpi_pstates_t *cs_pstates;
+       cpu_acpi_cstates_t *cs_cstates;
        cpu_acpi_pct_t cs_pct[2];
        cpu_acpi_psd_t cs_psd;
        cpu_acpi_ppc_t cs_ppc;
@@ -125,6 +143,7 @@ extern int cpu_acpi_cache_pct(cpu_acpi_h
 extern int cpu_acpi_cache_pct(cpu_acpi_handle_t);
 extern int cpu_acpi_cache_psd(cpu_acpi_handle_t);
 extern void cpu_acpi_cache_ppc(cpu_acpi_handle_t);
+extern int cpu_acpi_cache_cst(cpu_acpi_handle_t);
 extern int cpu_acpi_cache_data(cpu_acpi_handle_t);
 extern void cpu_acpi_install_ppc_handler(cpu_acpi_handle_t,
     ACPI_NOTIFY_HANDLER, dev_info_t *);
@@ -133,6 +152,7 @@ extern int cpu_acpi_write_port(ACPI_IO_A
 extern int cpu_acpi_write_port(ACPI_IO_ADDRESS, uint32_t, uint32_t);
 extern int cpu_acpi_read_port(ACPI_IO_ADDRESS, uint32_t *, uint32_t);
 extern uint_t cpu_acpi_get_speeds(cpu_acpi_handle_t, int **);
+extern uint_t cpu_acpi_get_max_cstates(cpu_acpi_handle_t);
 extern void cpu_acpi_free_speeds(int *, uint_t);
 
 #ifdef __cplusplus
diff -r 779c86b8bbe0 usr/src/uts/i86pc/sys/cpu_idle.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/sys/cpu_idle.h  Thu Dec 13 15:18:00 2007 +0800
@@ -0,0 +1,43 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef        _CPUIDLE_H
+#define        _CPUIDLE_H
+
+#pragma ident  "%Z%%M% %I%     %E% SMI"
+
+#include <sys/cpudrv_vendor.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct cpudrv_cstate_ops cpu_idle_ops;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CPUIDLE_H */
diff -r 779c86b8bbe0 usr/src/uts/i86pc/sys/cpudrv_plat.h
--- a/usr/src/uts/i86pc/sys/cpudrv_plat.h       Fri Dec 07 23:46:46 2007
-0500
+++ b/usr/src/uts/i86pc/sys/cpudrv_plat.h       Thu Dec 13 15:17:35 2007
+0800
@@ -86,6 +86,12 @@ extern ulong_t cpu_ready_set;
        cpu_acpi_free_speeds(speeds, nspeeds);
 
 /*
+ * ACPI provides the supported C-states.
+ */
+#define        CPUDRV_PM_GET_MAX_CSTATES(cpudsp, cpu_max_cstates) \
+       cpu_max_cstates = cpu_acpi_get_max_cstates(cpudsp->acpi_handle);
+
+/*
  * Convert speed to Hz.
  */
 #define        CPUDRV_PM_SPEED_HZ(unused, mhz) ((uint64_t)mhz *
1000000)
============================================================



-------------- next part --------------
A non-text attachment was scrubbed...
Name: cstate.diff
Type: application/octet-stream
Size: 13806 bytes
Desc: cstate.diff
URL: 
<http://mail.opensolaris.org/pipermail/tesla-dev/attachments/20071213/2275416f/attachment.obj>

Reply via email to