18906SEric.Saxe@Sun.COM /*
28906SEric.Saxe@Sun.COM * CDDL HEADER START
38906SEric.Saxe@Sun.COM *
48906SEric.Saxe@Sun.COM * The contents of this file are subject to the terms of the
58906SEric.Saxe@Sun.COM * Common Development and Distribution License (the "License").
68906SEric.Saxe@Sun.COM * You may not use this file except in compliance with the License.
78906SEric.Saxe@Sun.COM *
88906SEric.Saxe@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98906SEric.Saxe@Sun.COM * or http://www.opensolaris.org/os/licensing.
108906SEric.Saxe@Sun.COM * See the License for the specific language governing permissions
118906SEric.Saxe@Sun.COM * and limitations under the License.
128906SEric.Saxe@Sun.COM *
138906SEric.Saxe@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
148906SEric.Saxe@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158906SEric.Saxe@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
168906SEric.Saxe@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
178906SEric.Saxe@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
188906SEric.Saxe@Sun.COM *
198906SEric.Saxe@Sun.COM * CDDL HEADER END
208906SEric.Saxe@Sun.COM */
218906SEric.Saxe@Sun.COM /*
228906SEric.Saxe@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
238906SEric.Saxe@Sun.COM * Use is subject to license terms.
248906SEric.Saxe@Sun.COM */
258906SEric.Saxe@Sun.COM
268906SEric.Saxe@Sun.COM /*
2710992Saubrey.li@intel.com * Copyright (c) 2009, Intel Corporation.
2810992Saubrey.li@intel.com * All rights reserved.
2910992Saubrey.li@intel.com */
3010992Saubrey.li@intel.com
3110992Saubrey.li@intel.com /*
328906SEric.Saxe@Sun.COM * Intel specific CPU power management support.
338906SEric.Saxe@Sun.COM */
348906SEric.Saxe@Sun.COM
358906SEric.Saxe@Sun.COM #include <sys/x86_archext.h>
368906SEric.Saxe@Sun.COM #include <sys/cpu_acpi.h>
378906SEric.Saxe@Sun.COM #include <sys/speedstep.h>
388906SEric.Saxe@Sun.COM #include <sys/cpupm_throttle.h>
398906SEric.Saxe@Sun.COM #include <sys/cpu_idle.h>
4010992Saubrey.li@intel.com #include <sys/archsystm.h>
418906SEric.Saxe@Sun.COM
428906SEric.Saxe@Sun.COM /*
438906SEric.Saxe@Sun.COM * The Intel Processor Driver Capabilities (_PDC).
448906SEric.Saxe@Sun.COM * See Intel Processor Vendor-Specific ACPI Interface Specification
458906SEric.Saxe@Sun.COM * for details.
468906SEric.Saxe@Sun.COM */
478906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_REVISION 0x1
488906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_PS_MSR 0x0001
498906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_C1_HALT 0x0002
508906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_TS_MSR 0x0004
518906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_MP 0x0008
528906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_C2C3_MP 0x0010
538906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_SW_PSD 0x0020
548906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_TSD 0x0080
558906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_C1_FFH 0x0100
568906SEric.Saxe@Sun.COM #define CPUPM_INTEL_PDC_HW_PSD 0x0800
578906SEric.Saxe@Sun.COM
588906SEric.Saxe@Sun.COM static uint32_t cpupm_intel_pdccap = 0;
598906SEric.Saxe@Sun.COM
6010992Saubrey.li@intel.com /*
6110992Saubrey.li@intel.com * MSR for Intel ENERGY_PERF_BIAS feature.
6210992Saubrey.li@intel.com * The default processor power operation policy is max performance.
6310992Saubrey.li@intel.com * Power control unit drives to max performance at any energy cost.
6410992Saubrey.li@intel.com * This MSR is designed to be a power master control knob,
6510992Saubrey.li@intel.com * it provides 4-bit OS input to the HW for the logical CPU, based on
6610992Saubrey.li@intel.com * user power-policy preference(scale of 0 to 15). 0 is highest
6710992Saubrey.li@intel.com * performance, 15 is minimal energy consumption.
6810992Saubrey.li@intel.com * 7 is a good balance between performance and energy consumption.
6910992Saubrey.li@intel.com */
7010992Saubrey.li@intel.com #define IA32_ENERGY_PERF_BIAS_MSR 0x1B0
7110992Saubrey.li@intel.com #define EPB_MSR_MASK 0xF
7210992Saubrey.li@intel.com #define EPB_MAX_PERF 0
7310992Saubrey.li@intel.com #define EPB_BALANCE 7
7410992Saubrey.li@intel.com #define EPB_MAX_POWER_SAVE 15
7510992Saubrey.li@intel.com
7610992Saubrey.li@intel.com /*
7710992Saubrey.li@intel.com * The value is used to initialize the user power policy preference
7810992Saubrey.li@intel.com * in IA32_ENERGY_PERF_BIAS_MSR. Variable is used here to allow tuning
7910992Saubrey.li@intel.com * from the /etc/system file.
8010992Saubrey.li@intel.com */
8110992Saubrey.li@intel.com uint64_t cpupm_iepb_policy = EPB_MAX_PERF;
8210992Saubrey.li@intel.com
8310992Saubrey.li@intel.com static void cpupm_iepb_set_policy(uint64_t power_policy);
8410992Saubrey.li@intel.com
858906SEric.Saxe@Sun.COM boolean_t
cpupm_intel_init(cpu_t * cp)868906SEric.Saxe@Sun.COM cpupm_intel_init(cpu_t *cp)
878906SEric.Saxe@Sun.COM {
888906SEric.Saxe@Sun.COM cpupm_mach_state_t *mach_state =
898906SEric.Saxe@Sun.COM (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
908906SEric.Saxe@Sun.COM uint_t family;
918906SEric.Saxe@Sun.COM uint_t model;
928906SEric.Saxe@Sun.COM
938906SEric.Saxe@Sun.COM if (x86_vendor != X86_VENDOR_Intel)
948906SEric.Saxe@Sun.COM return (B_FALSE);
958906SEric.Saxe@Sun.COM
96*12004Sjiang.liu@intel.com family = cpuid_getfamily(cp);
97*12004Sjiang.liu@intel.com model = cpuid_getmodel(cp);
988906SEric.Saxe@Sun.COM
998906SEric.Saxe@Sun.COM cpupm_intel_pdccap = CPUPM_INTEL_PDC_MP;
1008906SEric.Saxe@Sun.COM
1018906SEric.Saxe@Sun.COM /*
1028906SEric.Saxe@Sun.COM * If we support SpeedStep on this processor, then set the
1038906SEric.Saxe@Sun.COM * correct cma_ops for the processor and enable appropriate
1048906SEric.Saxe@Sun.COM * _PDC bits.
1058906SEric.Saxe@Sun.COM */
1068906SEric.Saxe@Sun.COM if (speedstep_supported(family, model)) {
1078906SEric.Saxe@Sun.COM mach_state->ms_pstate.cma_ops = &speedstep_ops;
1088906SEric.Saxe@Sun.COM cpupm_intel_pdccap |= CPUPM_INTEL_PDC_PS_MSR |
1098906SEric.Saxe@Sun.COM CPUPM_INTEL_PDC_C1_HALT | CPUPM_INTEL_PDC_SW_PSD |
1108906SEric.Saxe@Sun.COM CPUPM_INTEL_PDC_HW_PSD;
1118906SEric.Saxe@Sun.COM } else {
1128906SEric.Saxe@Sun.COM mach_state->ms_pstate.cma_ops = NULL;
1138906SEric.Saxe@Sun.COM }
1148906SEric.Saxe@Sun.COM
1158906SEric.Saxe@Sun.COM /*
1168906SEric.Saxe@Sun.COM * Set the correct tstate_ops for the processor and
1178906SEric.Saxe@Sun.COM * enable appropriate _PDC bits.
1188906SEric.Saxe@Sun.COM */
1198906SEric.Saxe@Sun.COM mach_state->ms_tstate.cma_ops = &cpupm_throttle_ops;
1208906SEric.Saxe@Sun.COM cpupm_intel_pdccap |= CPUPM_INTEL_PDC_TS_MSR |
1218906SEric.Saxe@Sun.COM CPUPM_INTEL_PDC_TSD;
1228906SEric.Saxe@Sun.COM
1238906SEric.Saxe@Sun.COM /*
1248906SEric.Saxe@Sun.COM * If we support deep cstates on this processor, then set the
1258906SEric.Saxe@Sun.COM * correct cstate_ops for the processor and enable appropriate
1268906SEric.Saxe@Sun.COM * _PDC bits.
1278906SEric.Saxe@Sun.COM */
1288906SEric.Saxe@Sun.COM mach_state->ms_cstate.cma_ops = &cpu_idle_ops;
1298906SEric.Saxe@Sun.COM cpupm_intel_pdccap |= CPUPM_INTEL_PDC_C1_HALT |
1308906SEric.Saxe@Sun.COM CPUPM_INTEL_PDC_C2C3_MP | CPUPM_INTEL_PDC_C1_FFH;
1318906SEric.Saxe@Sun.COM
1328906SEric.Saxe@Sun.COM /*
1338906SEric.Saxe@Sun.COM * _PDC support is optional and the driver should
1348906SEric.Saxe@Sun.COM * function even if the _PDC write fails.
1358906SEric.Saxe@Sun.COM */
1368906SEric.Saxe@Sun.COM (void) cpu_acpi_write_pdc(mach_state->ms_acpi_handle,
1378906SEric.Saxe@Sun.COM CPUPM_INTEL_PDC_REVISION, 1, &cpupm_intel_pdccap);
1388906SEric.Saxe@Sun.COM
13910992Saubrey.li@intel.com /*
14010992Saubrey.li@intel.com * If Intel ENERGY PERFORMANCE BIAS feature is supported,
14110992Saubrey.li@intel.com * provides input to the HW, based on user power-policy.
14210992Saubrey.li@intel.com */
14310992Saubrey.li@intel.com if (cpuid_iepb_supported(cp)) {
14410992Saubrey.li@intel.com cpupm_iepb_set_policy(cpupm_iepb_policy);
14510992Saubrey.li@intel.com }
14610992Saubrey.li@intel.com
1478906SEric.Saxe@Sun.COM return (B_TRUE);
1488906SEric.Saxe@Sun.COM }
14910992Saubrey.li@intel.com
15010992Saubrey.li@intel.com /*
15110992Saubrey.li@intel.com * ENERGY_PERF_BIAS setting,
15210992Saubrey.li@intel.com * A hint to HW, based on user power-policy
15310992Saubrey.li@intel.com */
15410992Saubrey.li@intel.com static void
cpupm_iepb_set_policy(uint64_t iepb_policy)15510992Saubrey.li@intel.com cpupm_iepb_set_policy(uint64_t iepb_policy)
15610992Saubrey.li@intel.com {
15710992Saubrey.li@intel.com ulong_t iflag;
15810992Saubrey.li@intel.com uint64_t epb_value;
15910992Saubrey.li@intel.com
16010992Saubrey.li@intel.com epb_value = iepb_policy & EPB_MSR_MASK;
16110992Saubrey.li@intel.com
16210992Saubrey.li@intel.com iflag = intr_clear();
16310992Saubrey.li@intel.com wrmsr(IA32_ENERGY_PERF_BIAS_MSR, epb_value);
16410992Saubrey.li@intel.com intr_restore(iflag);
16510992Saubrey.li@intel.com }
166