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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/x86_archext.h> 29 #include <sys/machsystm.h> 30 #include <sys/x_call.h> 31 #include <sys/acpi/acpi.h> 32 #include <sys/acpica.h> 33 #include <sys/speedstep.h> 34 #include <sys/cpu_acpi.h> 35 #include <sys/cpupm.h> 36 #include <sys/dtrace.h> 37 #include <sys/sdt.h> 38 39 /* 40 * Error returns 41 */ 42 #define ESS_RET_SUCCESS 0x00 43 #define ESS_RET_NO_PM 0x01 44 #define ESS_RET_UNSUP_STATE 0x02 45 46 /* 47 * Intel docs indicate that maximum latency of P-state changes should 48 * be on the order of 10mS. When waiting, wait in 100uS increments. 49 */ 50 #define ESS_MAX_LATENCY_MICROSECS 10000 51 #define ESS_LATENCY_WAIT 100 52 53 /* 54 * The SpeedStep related Processor Driver Capabilities (_PDC). 55 * See Intel Processor Vendor-Specific ACPI Interface Specification 56 * for details. 57 */ 58 #define ESS_PDC_REVISION 0x1 59 #define ESS_PDC_PS_MSR (1<<0) 60 #define ESS_PDC_MP (1<<3) 61 #define ESS_PDC_PSD (1<<5) 62 63 /* 64 * MSR registers for changing and reading processor power state. 65 */ 66 #define IA32_PERF_STAT_MSR 0x198 67 #define IA32_PERF_CTL_MSR 0x199 68 69 #define IA32_CPUID_TSC_CONSTANT 0xF30 70 #define IA32_MISC_ENABLE_MSR 0x1A0 71 #define IA32_MISC_ENABLE_EST (1<<16) 72 #define IA32_MISC_ENABLE_CXE (1<<25) 73 /* 74 * Debugging support 75 */ 76 #ifdef DEBUG 77 volatile int ess_debug = 0; 78 #define ESSDEBUG(arglist) if (ess_debug) printf arglist; 79 #else 80 #define ESSDEBUG(arglist) 81 #endif 82 83 typedef struct speedstep_state { 84 uint32_t ss_state; 85 } speedstep_state_t; 86 87 uint32_t ess_pdccap = ESS_PDC_PS_MSR | ESS_PDC_MP | ESS_PDC_PSD; 88 89 /* 90 * Read the status register. How it is read, depends upon the _PCT 91 * APCI object value. 92 */ 93 static int 94 read_status(cpu_acpi_handle_t handle, uint32_t *stat) 95 { 96 cpu_acpi_pct_t *pct_stat; 97 uint64_t reg; 98 int ret = 0; 99 100 pct_stat = CPU_ACPI_PCT_STATUS(handle); 101 102 switch (pct_stat->pc_addrspace_id) { 103 case ACPI_ADR_SPACE_FIXED_HARDWARE: 104 reg = rdmsr(IA32_PERF_STAT_MSR); 105 *stat = reg & 0xFFFF; 106 ret = 0; 107 break; 108 109 case ACPI_ADR_SPACE_SYSTEM_IO: 110 ret = cpu_acpi_read_port(pct_stat->pc_address, stat, 111 pct_stat->pc_width); 112 break; 113 114 default: 115 DTRACE_PROBE1(ess_status_unsupported_type, uint8_t, 116 pct_stat->pc_addrspace_id); 117 return (-1); 118 } 119 120 DTRACE_PROBE1(ess_status_read, uint32_t, *stat); 121 DTRACE_PROBE1(ess_status_read_err, int, ret); 122 123 return (ret); 124 } 125 126 /* 127 * Write the ctrl register. How it is written, depends upon the _PCT 128 * APCI object value. 129 */ 130 static int 131 write_ctrl(cpu_acpi_handle_t handle, uint32_t ctrl) 132 { 133 cpu_acpi_pct_t *pct_ctrl; 134 uint64_t reg; 135 int ret = 0; 136 137 pct_ctrl = CPU_ACPI_PCT_CTRL(handle); 138 139 switch (pct_ctrl->pc_addrspace_id) { 140 case ACPI_ADR_SPACE_FIXED_HARDWARE: 141 /* 142 * Read current power state because reserved bits must be 143 * preserved, compose new value, and write it. 144 */ 145 reg = rdmsr(IA32_PERF_CTL_MSR); 146 reg &= ~((uint64_t)0xFFFF); 147 reg |= ctrl; 148 wrmsr(IA32_PERF_CTL_MSR, reg); 149 ret = 0; 150 break; 151 152 case ACPI_ADR_SPACE_SYSTEM_IO: 153 ret = cpu_acpi_write_port(pct_ctrl->pc_address, ctrl, 154 pct_ctrl->pc_width); 155 break; 156 157 default: 158 DTRACE_PROBE1(ess_ctrl_unsupported_type, uint8_t, 159 pct_ctrl->pc_addrspace_id); 160 return (-1); 161 } 162 163 DTRACE_PROBE1(ess_ctrl_write, uint32_t, ctrl); 164 DTRACE_PROBE1(ess_ctrl_write_err, int, ret); 165 166 return (ret); 167 } 168 169 /* 170 * Transition the current processor to the requested state. 171 */ 172 void 173 speedstep_pstate_transition(int *ret, cpudrv_devstate_t *cpudsp, 174 uint32_t req_state) 175 { 176 speedstep_state_t *speedstep_state = cpudsp->module_state; 177 cpu_acpi_handle_t handle = cpudsp->acpi_handle; 178 cpu_acpi_pstate_t *req_pstate; 179 uint32_t ctrl; 180 uint32_t stat; 181 int i; 182 183 req_pstate = CPU_ACPI_PSTATE(handle, req_state); 184 DTRACE_PROBE1(ess_transition, uint32_t, CPU_ACPI_FREQ(req_pstate)); 185 186 /* 187 * Initiate the processor p-state change. 188 */ 189 ctrl = CPU_ACPI_CTRL(req_pstate); 190 if (write_ctrl(handle, ctrl) != 0) { 191 *ret = ESS_RET_UNSUP_STATE; 192 return; 193 } 194 195 /* Wait until switch is complete, but bound the loop just in case. */ 196 for (i = 0; i < ESS_MAX_LATENCY_MICROSECS; i += ESS_LATENCY_WAIT) { 197 if (read_status(handle, &stat) == 0 && 198 CPU_ACPI_STAT(req_pstate) == stat) 199 break; 200 drv_usecwait(ESS_LATENCY_WAIT); 201 } 202 if (i >= ESS_MAX_LATENCY_MICROSECS) { 203 DTRACE_PROBE(ess_transition_incomplete); 204 } 205 206 speedstep_state->ss_state = req_state; 207 CPU->cpu_curr_clock = 208 (((uint64_t)CPU_ACPI_FREQ(req_pstate) * 1000000)); 209 *ret = ESS_RET_SUCCESS; 210 } 211 212 int 213 speedstep_power(cpudrv_devstate_t *cpudsp, uint32_t req_state) 214 { 215 cpuset_t cpus; 216 int ret; 217 218 CPUSET_ONLY(cpus, cpudsp->cpu_id); 219 220 kpreempt_disable(); 221 xc_call((xc_arg_t)&ret, (xc_arg_t)cpudsp, (xc_arg_t)req_state, 222 X_CALL_HIPRI, cpus, (xc_func_t)speedstep_pstate_transition); 223 kpreempt_enable(); 224 225 return (ret); 226 } 227 228 /* 229 * Validate that this processor supports Speedstep and if so, 230 * get the P-state data from ACPI and cache it. 231 */ 232 int 233 speedstep_init(cpudrv_devstate_t *cpudsp) 234 { 235 speedstep_state_t *speedstep_state; 236 cpu_acpi_handle_t handle; 237 cpu_acpi_pct_t *pct_stat; 238 uint64_t reg; 239 uint_t family; 240 uint_t model; 241 struct cpuid_regs cpu_regs; 242 cpu_t *cp; 243 int dependency; 244 245 ESSDEBUG(("speedstep_init: instance %d\n", 246 ddi_get_instance(cpudsp->dip))); 247 248 /* Intel w/ CPUID support and rdmsr/wrmsr? */ 249 if (x86_vendor != X86_VENDOR_Intel || 250 !(x86_feature & X86_CPUID) || 251 !(x86_feature & X86_MSR)) { 252 ESSDEBUG(("Either not Intel or feature not supported.\n")); 253 return (ESS_RET_NO_PM); 254 } 255 256 /* 257 * Enhanced Speedstep supported? 258 */ 259 cpu_regs.cp_eax = 0x1; 260 (void) __cpuid_insn(&cpu_regs); 261 if (!(cpu_regs.cp_ecx & CPUID_INTC_ECX_EST)) { 262 ESSDEBUG(("Enhanced Speedstep not supported.\n")); 263 return (ESS_RET_NO_PM); 264 } 265 266 family = cpuid_getfamily(CPU); 267 model = cpuid_getmodel(CPU); 268 if (!((family == 0xf && model >= 0x3) || 269 (family == 0x6 && model >= 0xe))) { 270 ESSDEBUG(("Variant TSC not supported.\n")); 271 return (ESS_RET_NO_PM); 272 } 273 274 /* 275 * If Enhanced Speedstep has not been enabled on the system, 276 * then we probably should not override the BIOS setting. 277 */ 278 reg = rdmsr(IA32_MISC_ENABLE_MSR); 279 if (! (reg & IA32_MISC_ENABLE_EST)) { 280 cmn_err(CE_NOTE, "!Enhanced Intel SpeedStep not enabled."); 281 cmn_err(CE_NOTE, "!CPU power management will not function."); 282 return (ESS_RET_NO_PM); 283 } 284 285 /* 286 * Enhanced Speedstep requires ACPI support. Get a handle 287 * to the correct processor object for this dip. 288 */ 289 handle = cpudsp->acpi_handle = cpu_acpi_init(cpudsp->dip); 290 if (handle == NULL) { 291 cmn_err(CE_WARN, "!speedstep_init: instance %d: " 292 "unable to get ACPI handle", 293 ddi_get_instance(cpudsp->dip)); 294 295 cmn_err(CE_NOTE, "!CPU power management will not function."); 296 return (ESS_RET_NO_PM); 297 } 298 299 /* 300 * _PDC support is optional and the driver should 301 * function even if the _PDC write fails. 302 */ 303 if (cpu_acpi_write_pdc(handle, ESS_PDC_REVISION, 1, 304 &ess_pdccap) != 0) 305 ESSDEBUG(("Failed to write PDC\n")); 306 307 if (cpu_acpi_cache_data(handle) != 0) { 308 ESSDEBUG(("Failed to cache ACPI data\n")); 309 cpu_acpi_fini(handle); 310 return (ESS_RET_NO_PM); 311 } 312 313 pct_stat = CPU_ACPI_PCT_STATUS(handle); 314 switch (pct_stat->pc_addrspace_id) { 315 case ACPI_ADR_SPACE_FIXED_HARDWARE: 316 ESSDEBUG(("Transitions will use fixed hardware\n")); 317 break; 318 case ACPI_ADR_SPACE_SYSTEM_IO: 319 ESSDEBUG(("Transitions will use system IO\n")); 320 break; 321 default: 322 cmn_err(CE_WARN, "!_PCT conifgured for unsupported " 323 "addrspace = %d.", pct_stat->pc_addrspace_id); 324 cmn_err(CE_NOTE, "!CPU power management will not function."); 325 cpu_acpi_fini(handle); 326 return (ESS_RET_NO_PM); 327 } 328 329 if (CPU_ACPI_IS_OBJ_CACHED(handle, CPU_ACPI_PSD_CACHED)) 330 dependency = CPU_ACPI_PSD(handle).pd_domain; 331 else { 332 mutex_enter(&cpu_lock); 333 cp = cpu[CPU->cpu_id]; 334 dependency = cpuid_get_chipid(cp); 335 mutex_exit(&cpu_lock); 336 } 337 cpupm_add_cpu2dependency(cpudsp->dip, dependency); 338 339 speedstep_state = kmem_zalloc(sizeof (speedstep_state_t), KM_SLEEP); 340 speedstep_state->ss_state = NULL; 341 cpudsp->module_state = speedstep_state; 342 343 ESSDEBUG(("Instance %d succeeded.\n", ddi_get_instance(cpudsp->dip))); 344 return (ESS_RET_SUCCESS); 345 } 346 347 /* 348 * Free resources allocated by speedstep_init(). 349 */ 350 void 351 speedstep_fini(cpudrv_devstate_t *cpudsp) 352 { 353 cpu_acpi_fini(cpudsp->acpi_handle); 354 kmem_free(cpudsp->module_state, sizeof (speedstep_state_t)); 355 } 356