17f606aceSMark Haywood /*
27f606aceSMark Haywood  * CDDL HEADER START
37f606aceSMark Haywood  *
47f606aceSMark Haywood  * The contents of this file are subject to the terms of the
57f606aceSMark Haywood  * Common Development and Distribution License (the "License").
67f606aceSMark Haywood  * You may not use this file except in compliance with the License.
77f606aceSMark Haywood  *
87f606aceSMark Haywood  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97f606aceSMark Haywood  * or http://www.opensolaris.org/os/licensing.
107f606aceSMark Haywood  * See the License for the specific language governing permissions
117f606aceSMark Haywood  * and limitations under the License.
127f606aceSMark Haywood  *
137f606aceSMark Haywood  * When distributing Covered Code, include this CDDL HEADER in each
147f606aceSMark Haywood  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157f606aceSMark Haywood  * If applicable, add the following below this CDDL HEADER, with the
167f606aceSMark Haywood  * fields enclosed by brackets "[]" replaced with your own identifying
177f606aceSMark Haywood  * information: Portions Copyright [yyyy] [name of copyright owner]
187f606aceSMark Haywood  *
197f606aceSMark Haywood  * CDDL HEADER END
207f606aceSMark Haywood  */
217f606aceSMark Haywood /*
2284e1ed42SMark Haywood  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237f606aceSMark Haywood  * Use is subject to license terms.
247f606aceSMark Haywood  */
257f606aceSMark Haywood 
26f21ed392Saubrey.li@intel.com /*
27f21ed392Saubrey.li@intel.com  * Copyright (c) 2009, Intel Corporation.
28f21ed392Saubrey.li@intel.com  * All rights reserved.
29f21ed392Saubrey.li@intel.com  */
30f21ed392Saubrey.li@intel.com 
317f606aceSMark Haywood /*
327f606aceSMark Haywood  * Intel specific CPU power management support.
337f606aceSMark Haywood  */
347f606aceSMark Haywood 
357f606aceSMark Haywood #include <sys/x86_archext.h>
367f606aceSMark Haywood #include <sys/cpu_acpi.h>
377f606aceSMark Haywood #include <sys/speedstep.h>
380e751525SEric Saxe #include <sys/cpupm_throttle.h>
390e751525SEric Saxe #include <sys/cpu_idle.h>
40f21ed392Saubrey.li@intel.com #include <sys/archsystm.h>
417f606aceSMark Haywood 
427f606aceSMark Haywood /*
437f606aceSMark Haywood  * The Intel Processor Driver Capabilities (_PDC).
447f606aceSMark Haywood  * See Intel Processor Vendor-Specific ACPI Interface Specification
457f606aceSMark Haywood  * for details.
467f606aceSMark Haywood  */
470e751525SEric Saxe #define	CPUPM_INTEL_PDC_REVISION	0x1
480e751525SEric Saxe #define	CPUPM_INTEL_PDC_PS_MSR		0x0001
490e751525SEric Saxe #define	CPUPM_INTEL_PDC_C1_HALT		0x0002
500e751525SEric Saxe #define	CPUPM_INTEL_PDC_TS_MSR		0x0004
510e751525SEric Saxe #define	CPUPM_INTEL_PDC_MP		0x0008
520e751525SEric Saxe #define	CPUPM_INTEL_PDC_C2C3_MP		0x0010
530e751525SEric Saxe #define	CPUPM_INTEL_PDC_SW_PSD		0x0020
540e751525SEric Saxe #define	CPUPM_INTEL_PDC_TSD		0x0080
550e751525SEric Saxe #define	CPUPM_INTEL_PDC_C1_FFH		0x0100
560e751525SEric Saxe #define	CPUPM_INTEL_PDC_HW_PSD		0x0800
577f606aceSMark Haywood 
580e751525SEric Saxe static uint32_t cpupm_intel_pdccap = 0;
597f606aceSMark Haywood 
60f21ed392Saubrey.li@intel.com /*
61f21ed392Saubrey.li@intel.com  * MSR for Intel ENERGY_PERF_BIAS feature.
62f21ed392Saubrey.li@intel.com  * The default processor power operation policy is max performance.
63f21ed392Saubrey.li@intel.com  * Power control unit drives to max performance at any energy cost.
64f21ed392Saubrey.li@intel.com  * This MSR is designed to be a power master control knob,
65f21ed392Saubrey.li@intel.com  * it provides 4-bit OS input to the HW for the logical CPU, based on
66f21ed392Saubrey.li@intel.com  * user power-policy preference(scale of 0 to 15). 0 is highest
67f21ed392Saubrey.li@intel.com  * performance, 15 is minimal energy consumption.
68f21ed392Saubrey.li@intel.com  * 7 is a good balance between performance and energy consumption.
69f21ed392Saubrey.li@intel.com  */
70f21ed392Saubrey.li@intel.com #define	IA32_ENERGY_PERF_BIAS_MSR	0x1B0
71f21ed392Saubrey.li@intel.com #define	EPB_MSR_MASK			0xF
72f21ed392Saubrey.li@intel.com #define	EPB_MAX_PERF			0
73f21ed392Saubrey.li@intel.com #define	EPB_BALANCE			7
74f21ed392Saubrey.li@intel.com #define	EPB_MAX_POWER_SAVE		15
75f21ed392Saubrey.li@intel.com 
76f21ed392Saubrey.li@intel.com /*
77f21ed392Saubrey.li@intel.com  * The value is used to initialize the user power policy preference
78f21ed392Saubrey.li@intel.com  * in IA32_ENERGY_PERF_BIAS_MSR. Variable is used here to allow tuning
79f21ed392Saubrey.li@intel.com  * from the /etc/system file.
80f21ed392Saubrey.li@intel.com  */
81f21ed392Saubrey.li@intel.com uint64_t cpupm_iepb_policy = EPB_MAX_PERF;
82f21ed392Saubrey.li@intel.com 
83f21ed392Saubrey.li@intel.com static void cpupm_iepb_set_policy(uint64_t power_policy);
84f21ed392Saubrey.li@intel.com 
857f606aceSMark Haywood boolean_t
cpupm_intel_init(cpu_t * cp)860e751525SEric Saxe cpupm_intel_init(cpu_t *cp)
877f606aceSMark Haywood {
880e751525SEric Saxe 	cpupm_mach_state_t *mach_state =
890e751525SEric Saxe 	    (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
907f606aceSMark Haywood 	uint_t family;
917f606aceSMark Haywood 	uint_t model;
927f606aceSMark Haywood 
937f606aceSMark Haywood 	if (x86_vendor != X86_VENDOR_Intel)
947f606aceSMark Haywood 		return (B_FALSE);
957f606aceSMark Haywood 
96*a3114836SGerry Liu 	family = cpuid_getfamily(cp);
97*a3114836SGerry Liu 	model = cpuid_getmodel(cp);
987f606aceSMark Haywood 
990e751525SEric Saxe 	cpupm_intel_pdccap = CPUPM_INTEL_PDC_MP;
1000e751525SEric Saxe 
1017f606aceSMark Haywood 	/*
1027f606aceSMark Haywood 	 * If we support SpeedStep on this processor, then set the
1030e751525SEric Saxe 	 * correct cma_ops for the processor and enable appropriate
1047f606aceSMark Haywood 	 * _PDC bits.
1057f606aceSMark Haywood 	 */
1067f606aceSMark Haywood 	if (speedstep_supported(family, model)) {
1070e751525SEric Saxe 		mach_state->ms_pstate.cma_ops = &speedstep_ops;
1080e751525SEric Saxe 		cpupm_intel_pdccap |= CPUPM_INTEL_PDC_PS_MSR |
1090e751525SEric Saxe 		    CPUPM_INTEL_PDC_C1_HALT | CPUPM_INTEL_PDC_SW_PSD |
1100e751525SEric Saxe 		    CPUPM_INTEL_PDC_HW_PSD;
1117f606aceSMark Haywood 	} else {
1120e751525SEric Saxe 		mach_state->ms_pstate.cma_ops = NULL;
1137f606aceSMark Haywood 	}
1147f606aceSMark Haywood 
1157f606aceSMark Haywood 	/*
1167f606aceSMark Haywood 	 * Set the correct tstate_ops for the processor and
1177f606aceSMark Haywood 	 * enable appropriate _PDC bits.
1187f606aceSMark Haywood 	 */
1190e751525SEric Saxe 	mach_state->ms_tstate.cma_ops = &cpupm_throttle_ops;
1200e751525SEric Saxe 	cpupm_intel_pdccap |= CPUPM_INTEL_PDC_TS_MSR |
1210e751525SEric Saxe 	    CPUPM_INTEL_PDC_TSD;
1220e751525SEric Saxe 
1230e751525SEric Saxe 	/*
1240e751525SEric Saxe 	 * If we support deep cstates on this processor, then set the
1250e751525SEric Saxe 	 * correct cstate_ops for the processor and enable appropriate
1260e751525SEric Saxe 	 * _PDC bits.
1270e751525SEric Saxe 	 */
1280e751525SEric Saxe 	mach_state->ms_cstate.cma_ops = &cpu_idle_ops;
1290e751525SEric Saxe 	cpupm_intel_pdccap |= CPUPM_INTEL_PDC_C1_HALT |
1300e751525SEric Saxe 	    CPUPM_INTEL_PDC_C2C3_MP | CPUPM_INTEL_PDC_C1_FFH;
1317f606aceSMark Haywood 
1327f606aceSMark Haywood 	/*
1337f606aceSMark Haywood 	 * _PDC support is optional and the driver should
1347f606aceSMark Haywood 	 * function even if the _PDC write fails.
1357f606aceSMark Haywood 	 */
1360e751525SEric Saxe 	(void) cpu_acpi_write_pdc(mach_state->ms_acpi_handle,
1370e751525SEric Saxe 	    CPUPM_INTEL_PDC_REVISION, 1, &cpupm_intel_pdccap);
1387f606aceSMark Haywood 
139f21ed392Saubrey.li@intel.com 	/*
140f21ed392Saubrey.li@intel.com 	 * If Intel ENERGY PERFORMANCE BIAS feature is supported,
141f21ed392Saubrey.li@intel.com 	 * provides input to the HW, based on user power-policy.
142f21ed392Saubrey.li@intel.com 	 */
143f21ed392Saubrey.li@intel.com 	if (cpuid_iepb_supported(cp)) {
144f21ed392Saubrey.li@intel.com 		cpupm_iepb_set_policy(cpupm_iepb_policy);
145f21ed392Saubrey.li@intel.com 	}
146f21ed392Saubrey.li@intel.com 
1477f606aceSMark Haywood 	return (B_TRUE);
1487f606aceSMark Haywood }
149f21ed392Saubrey.li@intel.com 
150f21ed392Saubrey.li@intel.com /*
151f21ed392Saubrey.li@intel.com  * ENERGY_PERF_BIAS setting,
152f21ed392Saubrey.li@intel.com  * A hint to HW, based on user power-policy
153f21ed392Saubrey.li@intel.com  */
154f21ed392Saubrey.li@intel.com static void
cpupm_iepb_set_policy(uint64_t iepb_policy)155f21ed392Saubrey.li@intel.com cpupm_iepb_set_policy(uint64_t iepb_policy)
156f21ed392Saubrey.li@intel.com {
157f21ed392Saubrey.li@intel.com 	ulong_t		iflag;
158f21ed392Saubrey.li@intel.com 	uint64_t	epb_value;
159f21ed392Saubrey.li@intel.com 
160f21ed392Saubrey.li@intel.com 	epb_value = iepb_policy & EPB_MSR_MASK;
161f21ed392Saubrey.li@intel.com 
162f21ed392Saubrey.li@intel.com 	iflag = intr_clear();
163f21ed392Saubrey.li@intel.com 	wrmsr(IA32_ENERGY_PERF_BIAS_MSR, epb_value);
164f21ed392Saubrey.li@intel.com 	intr_restore(iflag);
165f21ed392Saubrey.li@intel.com }
166