xref: /illumos-gate/usr/src/uts/i86pc/os/cpupm/cpupm_intel.c (revision 42ed7838f131b8f58d6c95db1c7e3a6a3e6ea7e4)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * Copyright (c) 2009, Intel Corporation.
28  * All rights reserved.
29  */
30 
31 /*
32  * Intel specific CPU power management support.
33  */
34 
35 #include <sys/x86_archext.h>
36 #include <sys/cpu_acpi.h>
37 #include <sys/speedstep.h>
38 #include <sys/cpupm_throttle.h>
39 #include <sys/cpu_idle.h>
40 #include <sys/archsystm.h>
41 
42 /*
43  * The Intel Processor Driver Capabilities (_PDC).
44  * See Intel Processor Vendor-Specific ACPI Interface Specification
45  * for details.
46  */
47 #define	CPUPM_INTEL_PDC_REVISION	0x1
48 #define	CPUPM_INTEL_PDC_PS_MSR		0x0001
49 #define	CPUPM_INTEL_PDC_C1_HALT		0x0002
50 #define	CPUPM_INTEL_PDC_TS_MSR		0x0004
51 #define	CPUPM_INTEL_PDC_MP		0x0008
52 #define	CPUPM_INTEL_PDC_C2C3_MP		0x0010
53 #define	CPUPM_INTEL_PDC_SW_PSD		0x0020
54 #define	CPUPM_INTEL_PDC_TSD		0x0080
55 #define	CPUPM_INTEL_PDC_C1_FFH		0x0100
56 #define	CPUPM_INTEL_PDC_HW_PSD		0x0800
57 
58 static uint32_t cpupm_intel_pdccap = 0;
59 
60 /*
61  * MSR for Intel ENERGY_PERF_BIAS feature.
62  * The default processor power operation policy is max performance.
63  * Power control unit drives to max performance at any energy cost.
64  * This MSR is designed to be a power master control knob,
65  * it provides 4-bit OS input to the HW for the logical CPU, based on
66  * user power-policy preference(scale of 0 to 15). 0 is highest
67  * performance, 15 is minimal energy consumption.
68  * 7 is a good balance between performance and energy consumption.
69  */
70 #define	IA32_ENERGY_PERF_BIAS_MSR	0x1B0
71 #define	EPB_MSR_MASK			0xF
72 #define	EPB_MAX_PERF			0
73 #define	EPB_BALANCE			7
74 #define	EPB_MAX_POWER_SAVE		15
75 
76 /*
77  * The value is used to initialize the user power policy preference
78  * in IA32_ENERGY_PERF_BIAS_MSR. Variable is used here to allow tuning
79  * from the /etc/system file.
80  */
81 uint64_t cpupm_iepb_policy = EPB_MAX_PERF;
82 
83 static void cpupm_iepb_set_policy(uint64_t power_policy);
84 
85 boolean_t
86 cpupm_intel_init(cpu_t *cp)
87 {
88 	cpupm_mach_state_t *mach_state =
89 	    (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
90 	uint_t family;
91 	uint_t model;
92 
93 	if (x86_vendor != X86_VENDOR_Intel)
94 		return (B_FALSE);
95 
96 	family = cpuid_getfamily(CPU);
97 	model = cpuid_getmodel(CPU);
98 
99 	cpupm_intel_pdccap = CPUPM_INTEL_PDC_MP;
100 
101 	/*
102 	 * If we support SpeedStep on this processor, then set the
103 	 * correct cma_ops for the processor and enable appropriate
104 	 * _PDC bits.
105 	 */
106 	if (speedstep_supported(family, model)) {
107 		mach_state->ms_pstate.cma_ops = &speedstep_ops;
108 		cpupm_intel_pdccap |= CPUPM_INTEL_PDC_PS_MSR |
109 		    CPUPM_INTEL_PDC_C1_HALT | CPUPM_INTEL_PDC_SW_PSD |
110 		    CPUPM_INTEL_PDC_HW_PSD;
111 	} else {
112 		mach_state->ms_pstate.cma_ops = NULL;
113 	}
114 
115 	/*
116 	 * Set the correct tstate_ops for the processor and
117 	 * enable appropriate _PDC bits.
118 	 */
119 	mach_state->ms_tstate.cma_ops = &cpupm_throttle_ops;
120 	cpupm_intel_pdccap |= CPUPM_INTEL_PDC_TS_MSR |
121 	    CPUPM_INTEL_PDC_TSD;
122 
123 	/*
124 	 * If we support deep cstates on this processor, then set the
125 	 * correct cstate_ops for the processor and enable appropriate
126 	 * _PDC bits.
127 	 */
128 	mach_state->ms_cstate.cma_ops = &cpu_idle_ops;
129 	cpupm_intel_pdccap |= CPUPM_INTEL_PDC_C1_HALT |
130 	    CPUPM_INTEL_PDC_C2C3_MP | CPUPM_INTEL_PDC_C1_FFH;
131 
132 	/*
133 	 * _PDC support is optional and the driver should
134 	 * function even if the _PDC write fails.
135 	 */
136 	(void) cpu_acpi_write_pdc(mach_state->ms_acpi_handle,
137 	    CPUPM_INTEL_PDC_REVISION, 1, &cpupm_intel_pdccap);
138 
139 	/*
140 	 * If Intel ENERGY PERFORMANCE BIAS feature is supported,
141 	 * provides input to the HW, based on user power-policy.
142 	 */
143 	if (cpuid_iepb_supported(cp)) {
144 		cpupm_iepb_set_policy(cpupm_iepb_policy);
145 	}
146 
147 	return (B_TRUE);
148 }
149 
150 /*
151  * ENERGY_PERF_BIAS setting,
152  * A hint to HW, based on user power-policy
153  */
154 static void
155 cpupm_iepb_set_policy(uint64_t iepb_policy)
156 {
157 	ulong_t		iflag;
158 	uint64_t	epb_value;
159 
160 	epb_value = iepb_policy & EPB_MSR_MASK;
161 
162 	iflag = intr_clear();
163 	wrmsr(IA32_ENERGY_PERF_BIAS_MSR, epb_value);
164 	intr_restore(iflag);
165 }
166