xref: /illumos-gate/usr/src/uts/i86pc/os/cpupm/cpupm_mach.c (revision d218c8f01e2f96c4d73489408eb378adbfa58bc7)
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 #include <sys/cpu_pm.h>
27 #include <sys/x86_archext.h>
28 #include <sys/sdt.h>
29 #include <sys/spl.h>
30 #include <sys/machsystm.h>
31 #include <sys/hpet.h>
32 #include <sys/cpupm.h>
33 #include <sys/cpu_idle.h>
34 #include <sys/cpu_acpi.h>
35 #include <sys/cpupm_throttle.h>
36 #include <sys/dtrace.h>
37 
38 /*
39  * This callback is used to build the PPM CPU domains once
40  * all the CPU devices have been started. The callback is
41  * initialized by the PPM driver to point to a routine that
42  * will build the domains.
43  */
44 void (*cpupm_rebuild_cpu_domains)(void);
45 
46 /*
47  * This callback is used to reset the topspeed for all the
48  * CPU devices. The callback is initialized by the PPM driver to
49  * point to a routine that will reinitialize all the CPU devices
50  * once all the CPU devices have been started and the CPU domains
51  * built.
52  */
53 void (*cpupm_init_topspeed)(void);
54 
55 /*
56  * This callback is used to redefine the topspeed for a CPU device.
57  * Since all CPUs in a domain should have identical properties, this
58  * callback is initialized by the PPM driver to point to a routine
59  * that will redefine the topspeed for all devices in a CPU domain.
60  * This callback is exercised whenever an ACPI _PPC change notification
61  * is received by the CPU driver.
62  */
63 void (*cpupm_redefine_topspeed)(void *);
64 
65 /*
66  * This callback is used by the PPM driver to call into the CPU driver
67  * to find a CPU's current topspeed (i.e., it's current ACPI _PPC value).
68  */
69 void (*cpupm_set_topspeed_callb)(void *, int);
70 
71 /*
72  * This callback is used by the PPM driver to call into the CPU driver
73  * to set a new topspeed for a CPU.
74  */
75 int (*cpupm_get_topspeed_callb)(void *);
76 
77 static void cpupm_event_notify_handler(ACPI_HANDLE, UINT32, void *);
78 static void cpupm_free_notify_handlers(cpu_t *);
79 
80 /*
81  * Until proven otherwise, all power states are manageable.
82  */
83 static uint32_t cpupm_enabled = CPUPM_ALL_STATES;
84 
85 /*
86  * Until all CPUs have started, we do not allow
87  * power management.
88  */
89 static boolean_t cpupm_ready = B_FALSE;
90 
91 cpupm_state_domains_t *cpupm_pstate_domains = NULL;
92 cpupm_state_domains_t *cpupm_tstate_domains = NULL;
93 cpupm_state_domains_t *cpupm_cstate_domains = NULL;
94 
95 /*
96  * c-state tunables
97  *
98  * cpupm_cs_idle_cost_tunable is the ratio of time CPU spends executing + idle
99  * divided by time spent in the idle state transitions.
100  * A value of 10 means the CPU will not spend more than 1/10 of its time
101  * in idle latency.  The worst case performance will be 90% of non Deep C-state
102  * kernel.
103  *
104  * cpupm_cs_idle_save_tunable is how long we must stay in a deeper C-state
105  * before it is worth going there.  Expressed as a multiple of latency.
106  */
107 uint32_t cpupm_cs_sample_tunable = 5;		/* samples in decision period */
108 uint32_t cpupm_cs_idle_cost_tunable = 10;	/* work time / latency cost */
109 uint32_t cpupm_cs_idle_save_tunable = 2;	/* idle power savings */
110 uint16_t cpupm_C2_idle_pct_tunable = 70;
111 uint16_t cpupm_C3_idle_pct_tunable = 80;
112 
113 #ifndef __xpv
114 extern boolean_t cpupm_intel_init(cpu_t *);
115 extern boolean_t cpupm_amd_init(cpu_t *);
116 
117 typedef struct cpupm_vendor {
118 	boolean_t	(*cpuv_init)(cpu_t *);
119 } cpupm_vendor_t;
120 
121 /*
122  * Table of supported vendors.
123  */
124 static cpupm_vendor_t cpupm_vendors[] = {
125 	cpupm_intel_init,
126 	cpupm_amd_init,
127 	NULL
128 };
129 #endif
130 
131 /*
132  * Initialize the machine.
133  * See if a module exists for managing power for this CPU.
134  */
135 /*ARGSUSED*/
136 void
137 cpupm_init(cpu_t *cp)
138 {
139 #ifndef __xpv
140 	cpupm_vendor_t *vendors;
141 	cpupm_mach_state_t *mach_state;
142 	struct machcpu *mcpu = &(cp->cpu_m);
143 	int *speeds;
144 	uint_t nspeeds;
145 	int ret;
146 
147 	mach_state = cp->cpu_m.mcpu_pm_mach_state =
148 	    kmem_zalloc(sizeof (cpupm_mach_state_t), KM_SLEEP);
149 	mach_state->ms_caps = CPUPM_NO_STATES;
150 	mutex_init(&mach_state->ms_lock, NULL, MUTEX_DRIVER, NULL);
151 
152 	mach_state->ms_acpi_handle = cpu_acpi_init(cp);
153 	if (mach_state->ms_acpi_handle == NULL) {
154 		cpupm_free(cp);
155 		cmn_err(CE_WARN, "!cpupm_init: processor %d: "
156 		    "unable to get ACPI handle", cp->cpu_id);
157 		cmn_err(CE_NOTE, "!CPU power management will not function.");
158 		CPUPM_DISABLE();
159 		return;
160 	}
161 
162 	/*
163 	 * Loop through the CPU management module table and see if
164 	 * any of the modules implement CPU power management
165 	 * for this CPU.
166 	 */
167 	for (vendors = cpupm_vendors; vendors->cpuv_init != NULL; vendors++) {
168 		if (vendors->cpuv_init(cp))
169 			break;
170 	}
171 
172 	/*
173 	 * Nope, we can't power manage this CPU.
174 	 */
175 	if (vendors == NULL) {
176 		cpupm_free(cp);
177 		CPUPM_DISABLE();
178 		return;
179 	}
180 
181 	/*
182 	 * If P-state support exists for this system, then initialize it.
183 	 */
184 	if (mach_state->ms_pstate.cma_ops != NULL) {
185 		ret = mach_state->ms_pstate.cma_ops->cpus_init(cp);
186 		if (ret != 0) {
187 			cmn_err(CE_WARN, "!cpupm_init: processor %d:"
188 			    " unable to initialize P-state support",
189 			    cp->cpu_id);
190 			mach_state->ms_pstate.cma_ops = NULL;
191 			cpupm_disable(CPUPM_P_STATES);
192 		} else {
193 			nspeeds = cpupm_get_speeds(cp, &speeds);
194 			if (nspeeds == 0) {
195 				cmn_err(CE_WARN, "!cpupm_init: processor %d:"
196 				    " no speeds to manage", cp->cpu_id);
197 			} else {
198 				cpupm_set_supp_freqs(cp, speeds, nspeeds);
199 				cpupm_free_speeds(speeds, nspeeds);
200 				mach_state->ms_caps |= CPUPM_P_STATES;
201 			}
202 		}
203 	}
204 
205 	if (mach_state->ms_tstate.cma_ops != NULL) {
206 		ret = mach_state->ms_tstate.cma_ops->cpus_init(cp);
207 		if (ret != 0) {
208 			char err_msg[128];
209 			int p_res;
210 			p_res =	snprintf(err_msg, sizeof (err_msg),
211 			    "!cpupm_init: processor %d: unable to initialize "
212 			    "T-state support", cp->cpu_id);
213 			if (p_res >= 0)
214 				DTRACE_PROBE1(cpu_ts_err_msg, char *, err_msg);
215 			mach_state->ms_tstate.cma_ops = NULL;
216 			cpupm_disable(CPUPM_T_STATES);
217 		} else {
218 			mach_state->ms_caps |= CPUPM_T_STATES;
219 		}
220 	}
221 
222 	/*
223 	 * If C-states support exists for this system, then initialize it.
224 	 */
225 	if (mach_state->ms_cstate.cma_ops != NULL) {
226 		ret = mach_state->ms_cstate.cma_ops->cpus_init(cp);
227 		if (ret != 0) {
228 			cmn_err(CE_WARN, "!cpupm_init: processor %d:"
229 			    " unable to initialize C-state support",
230 			    cp->cpu_id);
231 			mach_state->ms_cstate.cma_ops = NULL;
232 			mcpu->max_cstates = CPU_ACPI_C1;
233 			cpupm_disable(CPUPM_C_STATES);
234 			idle_cpu = non_deep_idle_cpu;
235 			disp_enq_thread = non_deep_idle_disp_enq_thread;
236 		} else if (cpu_deep_cstates_supported()) {
237 			mcpu->max_cstates = cpu_acpi_get_max_cstates(
238 			    mach_state->ms_acpi_handle);
239 			if (mcpu->max_cstates > CPU_ACPI_C1) {
240 				hpet.callback(CST_EVENT_MULTIPLE_CSTATES);
241 				CPU->cpu_m.mcpu_idle_cpu = cpu_acpi_idle;
242 				mcpu->mcpu_idle_type = CPU_ACPI_C1;
243 				disp_enq_thread = cstate_wakeup;
244 			} else {
245 				hpet.callback(CST_EVENT_ONE_CSTATE);
246 			}
247 			mach_state->ms_caps |= CPUPM_C_STATES;
248 		} else {
249 			mcpu->max_cstates = CPU_ACPI_C1;
250 			idle_cpu = non_deep_idle_cpu;
251 			disp_enq_thread = non_deep_idle_disp_enq_thread;
252 		}
253 	}
254 
255 
256 	if (mach_state->ms_caps == CPUPM_NO_STATES) {
257 		cpupm_free(cp);
258 		CPUPM_DISABLE();
259 		return;
260 	}
261 
262 	if ((mach_state->ms_caps & CPUPM_T_STATES) ||
263 	    (mach_state->ms_caps & CPUPM_P_STATES) ||
264 	    (mach_state->ms_caps & CPUPM_C_STATES))
265 		cpupm_add_notify_handler(cp, cpupm_event_notify_handler, cp);
266 #endif
267 }
268 
269 /*
270  * Free any resources allocated by cpupm_init().
271  */
272 /*ARGSUSED*/
273 void
274 cpupm_free(cpu_t *cp)
275 {
276 #ifndef __xpv
277 	cpupm_mach_state_t *mach_state =
278 	    (cpupm_mach_state_t *)cp->cpu_m.mcpu_pm_mach_state;
279 
280 	if (mach_state == NULL)
281 		return;
282 	if (mach_state->ms_pstate.cma_ops != NULL) {
283 		mach_state->ms_pstate.cma_ops->cpus_fini(cp);
284 		mach_state->ms_pstate.cma_ops = NULL;
285 	}
286 
287 	if (mach_state->ms_tstate.cma_ops != NULL) {
288 		mach_state->ms_tstate.cma_ops->cpus_fini(cp);
289 		mach_state->ms_tstate.cma_ops = NULL;
290 	}
291 
292 	if (mach_state->ms_cstate.cma_ops != NULL) {
293 		mach_state->ms_cstate.cma_ops->cpus_fini(cp);
294 		mach_state->ms_cstate.cma_ops = NULL;
295 	}
296 
297 	cpupm_free_notify_handlers(cp);
298 
299 	if (mach_state->ms_acpi_handle != NULL) {
300 		cpu_acpi_fini(mach_state->ms_acpi_handle);
301 		mach_state->ms_acpi_handle = NULL;
302 	}
303 
304 	mutex_destroy(&mach_state->ms_lock);
305 	kmem_free(mach_state, sizeof (cpupm_mach_state_t));
306 	cp->cpu_m.mcpu_pm_mach_state = NULL;
307 #endif
308 }
309 
310 /*
311  * If all CPUs have started and at least one power state is manageable,
312  * then the CPUs are ready for power management.
313  */
314 boolean_t
315 cpupm_is_ready()
316 {
317 #ifndef __xpv
318 	if (cpupm_enabled == CPUPM_NO_STATES)
319 		return (B_FALSE);
320 	return (cpupm_ready);
321 #else
322 	return (B_FALSE);
323 #endif
324 
325 }
326 
327 boolean_t
328 cpupm_is_enabled(uint32_t state)
329 {
330 	return ((cpupm_enabled & state) == state);
331 }
332 
333 /*
334  * By default, all states are enabled.
335  */
336 void
337 cpupm_disable(uint32_t state)
338 {
339 
340 	if (state & CPUPM_P_STATES) {
341 		cpupm_free_domains(&cpupm_pstate_domains);
342 	}
343 	if (state & CPUPM_T_STATES) {
344 		cpupm_free_domains(&cpupm_tstate_domains);
345 	}
346 	if (state & CPUPM_C_STATES) {
347 		cpupm_free_domains(&cpupm_cstate_domains);
348 	}
349 	cpupm_enabled &= ~state;
350 }
351 
352 /*
353  * Once all CPUs have been started, the PPM driver should build CPU
354  * domains and initialize the topspeed for all CPU devices.
355  */
356 void
357 cpupm_post_startup()
358 {
359 #ifndef __xpv
360 	/*
361 	 * The CPU domain built by the PPM during CPUs attaching
362 	 * should be rebuilt with the information retrieved from
363 	 * ACPI.
364 	 */
365 	if (cpupm_rebuild_cpu_domains != NULL)
366 		(*cpupm_rebuild_cpu_domains)();
367 
368 	/*
369 	 * Only initialize the topspeed if P-states are enabled.
370 	 */
371 	if (cpupm_enabled & CPUPM_P_STATES && cpupm_init_topspeed != NULL)
372 		(*cpupm_init_topspeed)();
373 #endif
374 	cpupm_ready = B_TRUE;
375 }
376 
377 /*
378  * Allocate power domains for C,P and T States
379  */
380 void
381 cpupm_alloc_domains(cpu_t *cp, int state)
382 {
383 	cpupm_mach_state_t *mach_state =
384 	    (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
385 	cpu_acpi_handle_t handle = mach_state->ms_acpi_handle;
386 	cpupm_state_domains_t **dom_ptr;
387 	cpupm_state_domains_t *dptr;
388 	cpupm_state_domains_t **mach_dom_state_ptr;
389 	uint32_t domain;
390 	uint32_t type;
391 
392 	switch (state) {
393 	case CPUPM_P_STATES:
394 		if (CPU_ACPI_IS_OBJ_CACHED(handle, CPU_ACPI_PSD_CACHED)) {
395 			domain = CPU_ACPI_PSD(handle).sd_domain;
396 			type = CPU_ACPI_PSD(handle).sd_type;
397 		} else {
398 			mutex_enter(&cpu_lock);
399 			domain = cpuid_get_chipid(cp);
400 			mutex_exit(&cpu_lock);
401 			type = CPU_ACPI_HW_ALL;
402 		}
403 		dom_ptr = &cpupm_pstate_domains;
404 		mach_dom_state_ptr = &mach_state->ms_pstate.cma_domain;
405 		break;
406 	case CPUPM_T_STATES:
407 		if (CPU_ACPI_IS_OBJ_CACHED(handle, CPU_ACPI_TSD_CACHED)) {
408 			domain = CPU_ACPI_TSD(handle).sd_domain;
409 			type = CPU_ACPI_TSD(handle).sd_type;
410 		} else {
411 			mutex_enter(&cpu_lock);
412 			domain = cpuid_get_chipid(cp);
413 			mutex_exit(&cpu_lock);
414 			type = CPU_ACPI_HW_ALL;
415 		}
416 		dom_ptr = &cpupm_tstate_domains;
417 		mach_dom_state_ptr = &mach_state->ms_tstate.cma_domain;
418 		break;
419 	case CPUPM_C_STATES:
420 		if (CPU_ACPI_IS_OBJ_CACHED(handle, CPU_ACPI_CSD_CACHED)) {
421 			domain = CPU_ACPI_CSD(handle).sd_domain;
422 			type = CPU_ACPI_CSD(handle).sd_type;
423 		} else {
424 			mutex_enter(&cpu_lock);
425 			domain = cpuid_get_coreid(cp);
426 			mutex_exit(&cpu_lock);
427 			type = CPU_ACPI_HW_ALL;
428 		}
429 		dom_ptr = &cpupm_cstate_domains;
430 		mach_dom_state_ptr = &mach_state->ms_cstate.cma_domain;
431 		break;
432 	default:
433 		return;
434 	}
435 
436 	for (dptr = *dom_ptr; dptr != NULL; dptr = dptr->pm_next) {
437 		if (dptr->pm_domain == domain)
438 			break;
439 	}
440 
441 	/* new domain is created and linked at the head */
442 	if (dptr == NULL) {
443 		dptr = kmem_zalloc(sizeof (cpupm_state_domains_t), KM_SLEEP);
444 		dptr->pm_domain = domain;
445 		dptr->pm_type = type;
446 		dptr->pm_next = *dom_ptr;
447 		mutex_init(&dptr->pm_lock, NULL, MUTEX_SPIN,
448 		    (void *)ipltospl(DISP_LEVEL));
449 		CPUSET_ZERO(dptr->pm_cpus);
450 		*dom_ptr = dptr;
451 	}
452 	CPUSET_ADD(dptr->pm_cpus, cp->cpu_id);
453 	*mach_dom_state_ptr = dptr;
454 }
455 
456 /*
457  * Free C, P or T state power domains
458  */
459 void
460 cpupm_free_domains(cpupm_state_domains_t **dom_ptr)
461 {
462 	cpupm_state_domains_t *this_domain, *next_domain;
463 
464 	this_domain = *dom_ptr;
465 	while (this_domain != NULL) {
466 		next_domain = this_domain->pm_next;
467 		mutex_destroy(&this_domain->pm_lock);
468 		kmem_free((void *)this_domain,
469 		    sizeof (cpupm_state_domains_t));
470 		this_domain = next_domain;
471 	}
472 	*dom_ptr = NULL;
473 }
474 
475 void
476 cpupm_alloc_ms_cstate(cpu_t *cp)
477 {
478 	cpupm_mach_state_t *mach_state;
479 	cpupm_mach_acpi_state_t *ms_cstate;
480 
481 	mach_state = (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
482 	ms_cstate = &mach_state->ms_cstate;
483 	ASSERT(ms_cstate->cma_state.cstate == NULL);
484 	ms_cstate->cma_state.cstate = kmem_zalloc(sizeof (cma_c_state_t),
485 	    KM_SLEEP);
486 	ms_cstate->cma_state.cstate->cs_next_cstate = CPU_ACPI_C1;
487 }
488 
489 void
490 cpupm_free_ms_cstate(cpu_t *cp)
491 {
492 	cpupm_mach_state_t *mach_state =
493 	    (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
494 	cpupm_mach_acpi_state_t *ms_cstate = &mach_state->ms_cstate;
495 
496 	if (ms_cstate->cma_state.cstate != NULL) {
497 		kmem_free(ms_cstate->cma_state.cstate, sizeof (cma_c_state_t));
498 		ms_cstate->cma_state.cstate = NULL;
499 	}
500 }
501 
502 void
503 cpupm_state_change(cpu_t *cp, int level, int state)
504 {
505 	cpupm_mach_state_t	*mach_state =
506 	    (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
507 	cpupm_state_ops_t	*state_ops;
508 	cpupm_state_domains_t  	*state_domain;
509 	cpuset_t		set;
510 
511 	DTRACE_PROBE2(cpupm__state__change, cpu_t *, cp, int, level);
512 
513 	if (mach_state == NULL) {
514 		return;
515 	}
516 
517 	switch (state) {
518 	case CPUPM_P_STATES:
519 		state_ops = mach_state->ms_pstate.cma_ops;
520 		state_domain = mach_state->ms_pstate.cma_domain;
521 		break;
522 	case CPUPM_T_STATES:
523 		state_ops = mach_state->ms_tstate.cma_ops;
524 		state_domain = mach_state->ms_tstate.cma_domain;
525 		break;
526 	default:
527 		break;
528 	}
529 
530 	switch (state_domain->pm_type) {
531 	case CPU_ACPI_SW_ANY:
532 		/*
533 		 * A request on any CPU in the domain transitions the domain
534 		 */
535 		CPUSET_ONLY(set, cp->cpu_id);
536 		state_ops->cpus_change(set, level);
537 		break;
538 	case CPU_ACPI_SW_ALL:
539 		/*
540 		 * All CPUs in the domain must request the transition
541 		 */
542 	case CPU_ACPI_HW_ALL:
543 		/*
544 		 * P/T-state transitions are coordinated by the hardware
545 		 * For now, request the transition on all CPUs in the domain,
546 		 * but looking ahead we can probably be smarter about this.
547 		 */
548 		mutex_enter(&state_domain->pm_lock);
549 		state_ops->cpus_change(state_domain->pm_cpus, level);
550 		mutex_exit(&state_domain->pm_lock);
551 		break;
552 	default:
553 		cmn_err(CE_WARN, "Unknown domain coordination type: %d",
554 		    state_domain->pm_type);
555 	}
556 }
557 
558 /*
559  * CPU PM interfaces exposed to the CPU power manager
560  */
561 /*ARGSUSED*/
562 id_t
563 cpupm_plat_domain_id(cpu_t *cp, cpupm_dtype_t type)
564 {
565 	cpupm_mach_state_t	*mach_state =
566 	    (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
567 
568 	if ((mach_state == NULL) || (!cpupm_is_enabled(CPUPM_P_STATES) &&
569 	    !cpupm_is_enabled(CPUPM_C_STATES))) {
570 		return (CPUPM_NO_DOMAIN);
571 	}
572 	if (type == CPUPM_DTYPE_ACTIVE) {
573 		/*
574 		 * Return P-State domain for the specified CPU
575 		 */
576 		if (mach_state->ms_pstate.cma_domain) {
577 			return (mach_state->ms_pstate.cma_domain->pm_domain);
578 		}
579 	} else if (type == CPUPM_DTYPE_IDLE) {
580 		/*
581 		 * Return C-State domain for the specified CPU
582 		 */
583 		if (mach_state->ms_cstate.cma_domain) {
584 			return (mach_state->ms_cstate.cma_domain->pm_domain);
585 		}
586 	}
587 	return (CPUPM_NO_DOMAIN);
588 }
589 
590 /*ARGSUSED*/
591 uint_t
592 cpupm_plat_state_enumerate(cpu_t *cp, cpupm_dtype_t type,
593     cpupm_state_t *states)
594 {
595 	int	*speeds;
596 	uint_t	nspeeds, i;
597 
598 	/*
599 	 * Idle domain support unimplemented
600 	 */
601 	if (type != CPUPM_DTYPE_ACTIVE) {
602 		return (0);
603 	}
604 	nspeeds = cpupm_get_speeds(cp, &speeds);
605 
606 	/*
607 	 * If the caller passes NULL for states, just return the
608 	 * number of states.
609 	 */
610 	if (states != NULL) {
611 		for (i = 0; i < nspeeds; i++) {
612 			states[i].cps_speed = speeds[i];
613 			states[i].cps_handle = (cpupm_handle_t)i;
614 		}
615 	}
616 	cpupm_free_speeds(speeds, nspeeds);
617 	return (nspeeds);
618 }
619 
620 /*ARGSUSED*/
621 int
622 cpupm_plat_change_state(cpu_t *cp, cpupm_state_t *state)
623 {
624 	if (!cpupm_is_ready())
625 		return (-1);
626 
627 	cpupm_state_change(cp, (int)state->cps_handle, CPUPM_P_STATES);
628 
629 	return (0);
630 }
631 
632 /*ARGSUSED*/
633 /*
634  * Note: It is the responsibility of the users of
635  * cpupm_get_speeds() to free the memory allocated
636  * for speeds using cpupm_free_speeds()
637  */
638 uint_t
639 cpupm_get_speeds(cpu_t *cp, int **speeds)
640 {
641 #ifndef __xpv
642 	cpupm_mach_state_t *mach_state =
643 	    (cpupm_mach_state_t *)cp->cpu_m.mcpu_pm_mach_state;
644 	return (cpu_acpi_get_speeds(mach_state->ms_acpi_handle, speeds));
645 #else
646 	return (0);
647 #endif
648 }
649 
650 /*ARGSUSED*/
651 void
652 cpupm_free_speeds(int *speeds, uint_t nspeeds)
653 {
654 #ifndef __xpv
655 	cpu_acpi_free_speeds(speeds, nspeeds);
656 #endif
657 }
658 
659 /*
660  * All CPU instances have been initialized successfully.
661  */
662 boolean_t
663 cpupm_power_ready(void)
664 {
665 	return (cpupm_is_enabled(CPUPM_P_STATES) && cpupm_is_ready());
666 }
667 
668 /*
669  * All CPU instances have been initialized successfully.
670  */
671 boolean_t
672 cpupm_throttle_ready(void)
673 {
674 	return (cpupm_is_enabled(CPUPM_T_STATES) && cpupm_is_ready());
675 }
676 
677 /*
678  * All CPU instances have been initialized successfully.
679  */
680 boolean_t
681 cpupm_cstate_ready(void)
682 {
683 	return (cpupm_is_enabled(CPUPM_C_STATES) && cpupm_is_ready());
684 }
685 
686 void
687 cpupm_notify_handler(ACPI_HANDLE obj, UINT32 val, void *ctx)
688 {
689 	cpu_t *cp = ctx;
690 	cpupm_mach_state_t *mach_state =
691 	    (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
692 	cpupm_notification_t *entry;
693 
694 	mutex_enter(&mach_state->ms_lock);
695 	for (entry =  mach_state->ms_handlers; entry != NULL;
696 	    entry = entry->nq_next) {
697 		entry->nq_handler(obj, val, entry->nq_ctx);
698 	}
699 	mutex_exit(&mach_state->ms_lock);
700 }
701 
702 /*ARGSUSED*/
703 void
704 cpupm_add_notify_handler(cpu_t *cp, CPUPM_NOTIFY_HANDLER handler, void *ctx)
705 {
706 #ifndef __xpv
707 	cpupm_mach_state_t *mach_state =
708 	    (cpupm_mach_state_t *)cp->cpu_m.mcpu_pm_mach_state;
709 	cpupm_notification_t *entry;
710 
711 	entry = kmem_zalloc(sizeof (cpupm_notification_t), KM_SLEEP);
712 	entry->nq_handler = handler;
713 	entry->nq_ctx = ctx;
714 	mutex_enter(&mach_state->ms_lock);
715 	if (mach_state->ms_handlers == NULL) {
716 		entry->nq_next = NULL;
717 		mach_state->ms_handlers = entry;
718 		cpu_acpi_install_notify_handler(mach_state->ms_acpi_handle,
719 		    cpupm_notify_handler, cp);
720 
721 	} else {
722 		entry->nq_next = mach_state->ms_handlers;
723 		mach_state->ms_handlers = entry;
724 	}
725 	mutex_exit(&mach_state->ms_lock);
726 #endif
727 }
728 
729 /*ARGSUSED*/
730 static void
731 cpupm_free_notify_handlers(cpu_t *cp)
732 {
733 #ifndef __xpv
734 	cpupm_mach_state_t *mach_state =
735 	    (cpupm_mach_state_t *)cp->cpu_m.mcpu_pm_mach_state;
736 	cpupm_notification_t *entry;
737 	cpupm_notification_t *next;
738 
739 	mutex_enter(&mach_state->ms_lock);
740 	if (mach_state->ms_handlers == NULL) {
741 		mutex_exit(&mach_state->ms_lock);
742 		return;
743 	}
744 	if (mach_state->ms_acpi_handle != NULL) {
745 		cpu_acpi_remove_notify_handler(mach_state->ms_acpi_handle,
746 		    cpupm_notify_handler);
747 	}
748 	entry = mach_state->ms_handlers;
749 	while (entry != NULL) {
750 		next = entry->nq_next;
751 		kmem_free(entry, sizeof (cpupm_notification_t));
752 		entry = next;
753 	}
754 	mach_state->ms_handlers = NULL;
755 	mutex_exit(&mach_state->ms_lock);
756 #endif
757 }
758 
759 /*
760  * Get the current max speed from the ACPI _PPC object
761  */
762 /*ARGSUSED*/
763 int
764 cpupm_get_top_speed(cpu_t *cp)
765 {
766 #ifndef __xpv
767 	cpupm_mach_state_t 	*mach_state;
768 	cpu_acpi_handle_t 	handle;
769 	int 			plat_level;
770 	uint_t			nspeeds;
771 	int			max_level;
772 
773 	mach_state =
774 	    (cpupm_mach_state_t *)cp->cpu_m.mcpu_pm_mach_state;
775 	handle = mach_state->ms_acpi_handle;
776 
777 	cpu_acpi_cache_ppc(handle);
778 	plat_level = CPU_ACPI_PPC(handle);
779 
780 	nspeeds = CPU_ACPI_PSTATES_COUNT(handle);
781 
782 	max_level = nspeeds - 1;
783 	if ((plat_level < 0) || (plat_level > max_level)) {
784 		cmn_err(CE_NOTE, "!cpupm_get_top_speed: CPU %d: "
785 		    "_PPC out of range %d", cp->cpu_id, plat_level);
786 		plat_level = 0;
787 	}
788 
789 	return (plat_level);
790 #else
791 	return (0);
792 #endif
793 }
794 
795 /*
796  * This notification handler is called whenever the ACPI _PPC
797  * object changes. The _PPC is a sort of governor on power levels.
798  * It sets an upper threshold on which, _PSS defined, power levels
799  * are usuable. The _PPC value is dynamic and may change as properties
800  * (i.e., thermal or AC source) of the system change.
801  */
802 
803 static void
804 cpupm_power_manage_notifications(void *ctx)
805 {
806 	cpu_t			*cp = ctx;
807 	int			top_speed;
808 
809 	top_speed = cpupm_get_top_speed(cp);
810 	cpupm_redefine_max_activepwr_state(cp, top_speed);
811 }
812 
813 /* ARGSUSED */
814 static void
815 cpupm_event_notify_handler(ACPI_HANDLE obj, UINT32 val, void *ctx)
816 {
817 #ifndef __xpv
818 
819 	cpu_t *cp = ctx;
820 	cpupm_mach_state_t *mach_state =
821 	    (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state);
822 
823 	if (mach_state == NULL)
824 		return;
825 
826 	/*
827 	 * Currently, we handle _TPC,_CST and _PPC change notifications.
828 	 */
829 	if (val == CPUPM_TPC_CHANGE_NOTIFICATION &&
830 	    mach_state->ms_caps & CPUPM_T_STATES) {
831 		cpupm_throttle_manage_notification(ctx);
832 	} else if (val == CPUPM_CST_CHANGE_NOTIFICATION &&
833 	    mach_state->ms_caps & CPUPM_C_STATES) {
834 		cpuidle_manage_cstates(ctx);
835 	} else if (val == CPUPM_PPC_CHANGE_NOTIFICATION &&
836 	    mach_state->ms_caps & CPUPM_P_STATES) {
837 		cpupm_power_manage_notifications(ctx);
838 	}
839 #endif
840 }
841 
842 /*
843  * Update cpupm cstate data each time CPU exits idle.
844  */
845 void
846 cpupm_wakeup_cstate_data(cma_c_state_t *cs_data, hrtime_t end)
847 {
848 	cs_data->cs_idle_exit = end;
849 }
850 
851 /*
852  * Determine next cstate based on cpupm data.
853  * Update cpupm cstate data each time CPU goes idle.
854  * Do as much as possible in the idle state bookkeeping function because the
855  * performance impact while idle is minimal compared to in the wakeup function
856  * when there is real work to do.
857  */
858 uint32_t
859 cpupm_next_cstate(cma_c_state_t *cs_data, cpu_acpi_cstate_t *cstates,
860     uint32_t cs_count, hrtime_t start)
861 {
862 	hrtime_t duration;
863 	hrtime_t ave_interval;
864 	hrtime_t ave_idle_time;
865 	uint32_t i;
866 
867 	duration = cs_data->cs_idle_exit - cs_data->cs_idle_enter;
868 	scalehrtime(&duration);
869 	cs_data->cs_idle += duration;
870 	cs_data->cs_idle_enter = start;
871 
872 	++cs_data->cs_cnt;
873 	if (cs_data->cs_cnt > cpupm_cs_sample_tunable) {
874 		cs_data->cs_smpl_len = start - cs_data->cs_smpl_start;
875 		scalehrtime(&cs_data->cs_smpl_len);
876 		cs_data->cs_smpl_len |= 1;	/* protect from DIV 0 */
877 		cs_data->cs_smpl_idle = cs_data->cs_idle;
878 		cs_data->cs_idle = 0;
879 		cs_data->cs_smpl_idle_pct = ((100 * cs_data->cs_smpl_idle) /
880 		    cs_data->cs_smpl_len);
881 
882 		cs_data->cs_smpl_start = start;
883 		cs_data->cs_cnt = 0;
884 
885 		/*
886 		 * Strand level C-state policy
887 		 * The cpu_acpi_cstate_t *cstates array is not required to
888 		 * have an entry for both CPU_ACPI_C2 and CPU_ACPI_C3.
889 		 * There are cs_count entries in the cstates array.
890 		 * cs_data->cs_next_cstate contains the index of the next
891 		 * C-state this CPU should enter.
892 		 */
893 		ASSERT(cstates[0].cs_type == CPU_ACPI_C1);
894 
895 		/*
896 		 * Will CPU be idle long enough to save power?
897 		 */
898 		ave_idle_time = (cs_data->cs_smpl_idle /
899 		    cpupm_cs_sample_tunable) / 1000;
900 		for (i = 1; i < cs_count; ++i) {
901 			if (ave_idle_time < (cstates[i].cs_latency *
902 			    cpupm_cs_idle_save_tunable)) {
903 				cs_count = i;
904 				DTRACE_PROBE2(cpupm__next__cstate, cpu_t *,
905 				    CPU, int, i);
906 			}
907 		}
908 
909 		/*
910 		 * Wakeup often (even when non-idle time is very short)?
911 		 * Some producer/consumer type loads fall into this category.
912 		 */
913 		ave_interval = (cs_data->cs_smpl_len / cpupm_cs_sample_tunable)
914 		    / 1000;
915 		for (i = 1; i < cs_count; ++i) {
916 			if (ave_interval <= (cstates[i].cs_latency *
917 			    cpupm_cs_idle_cost_tunable)) {
918 				cs_count = i;
919 				DTRACE_PROBE2(cpupm__next__cstate, cpu_t *,
920 				    CPU, int, (CPU_MAX_CSTATES + i));
921 			}
922 		}
923 
924 		/*
925 		 * Idle percent
926 		 */
927 		for (i = 1; i < cs_count; ++i) {
928 			switch (cstates[i].cs_type) {
929 			case CPU_ACPI_C2:
930 				if (cs_data->cs_smpl_idle_pct <
931 				    cpupm_C2_idle_pct_tunable) {
932 					cs_count = i;
933 					DTRACE_PROBE2(cpupm__next__cstate,
934 					    cpu_t *, CPU, int,
935 					    ((2 * CPU_MAX_CSTATES) + i));
936 				}
937 				break;
938 
939 			case CPU_ACPI_C3:
940 				if (cs_data->cs_smpl_idle_pct <
941 				    cpupm_C3_idle_pct_tunable) {
942 					cs_count = i;
943 					DTRACE_PROBE2(cpupm__next__cstate,
944 					    cpu_t *, CPU, int,
945 					    ((2 * CPU_MAX_CSTATES) + i));
946 				}
947 				break;
948 			}
949 		}
950 
951 		cs_data->cs_next_cstate = cs_count - 1;
952 	}
953 
954 	return (cs_data->cs_next_cstate);
955 }
956