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
58static 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 */
81uint64_t cpupm_iepb_policy = EPB_MAX_PERF;
82
83static void cpupm_iepb_set_policy(uint64_t power_policy);
84
85boolean_t
86cpupm_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(cp);
97	model = cpuid_getmodel(cp);
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 */
154static void
155cpupm_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