xref: /illumos-gate/usr/src/uts/i86pc/os/cpupm/cpu_acpi.c (revision 19193bb63b10fe65b6e01f1ce7232407a18a917a)
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_acpi.h>
27 
28 /*
29  * List of the processor ACPI object types that are being used.
30  */
31 typedef enum cpu_acpi_obj {
32 	PDC_OBJ = 0,
33 	PCT_OBJ,
34 	PSS_OBJ,
35 	PSD_OBJ,
36 	PPC_OBJ,
37 	PTC_OBJ,
38 	TSS_OBJ,
39 	TSD_OBJ,
40 	TPC_OBJ,
41 	CSD_OBJ,
42 } cpu_acpi_obj_t;
43 
44 /*
45  * Container to store object name.
46  * Other attributes can be added in the future as necessary.
47  */
48 typedef struct cpu_acpi_obj_attr {
49 	char *name;
50 } cpu_acpi_obj_attr_t;
51 
52 /*
53  * List of object attributes.
54  * NOTE: Please keep the ordering of the list as same as cpu_acpi_obj_t.
55  */
56 static cpu_acpi_obj_attr_t cpu_acpi_obj_attrs[] = {
57 	{"_PDC"},
58 	{"_PCT"},
59 	{"_PSS"},
60 	{"_PSD"},
61 	{"_PPC"},
62 	{"_PTC"},
63 	{"_TSS"},
64 	{"_TSD"},
65 	{"_TPC"},
66 	{"_CSD"}
67 };
68 
69 /*
70  * Cache the ACPI CPU control data objects.
71  */
72 static int
73 cpu_acpi_cache_ctrl_regs(cpu_acpi_handle_t handle, cpu_acpi_obj_t objtype,
74     cpu_acpi_ctrl_regs_t *regs)
75 {
76 	ACPI_BUFFER abuf;
77 	ACPI_OBJECT *obj;
78 	AML_RESOURCE_GENERIC_REGISTER *greg;
79 	int ret = -1;
80 	int i;
81 
82 	/*
83 	 * Fetch the control registers (if present) for the CPU node.
84 	 * Since they are optional, non-existence is not a failure
85 	 * (we just consider it a fixed hardware case).
86 	 */
87 	abuf.Length = ACPI_ALLOCATE_BUFFER;
88 	abuf.Pointer = NULL;
89 	if (ACPI_FAILURE(AcpiEvaluateObjectTyped(handle->cs_handle,
90 	    cpu_acpi_obj_attrs[objtype].name, NULL, &abuf,
91 	    ACPI_TYPE_PACKAGE))) {
92 		regs[0].cr_addrspace_id = ACPI_ADR_SPACE_FIXED_HARDWARE;
93 		regs[1].cr_addrspace_id = ACPI_ADR_SPACE_FIXED_HARDWARE;
94 		return (1);
95 	}
96 
97 	obj = abuf.Pointer;
98 	if (obj->Package.Count != 2) {
99 		cmn_err(CE_NOTE, "!cpu_acpi: %s package bad count %d.",
100 		    cpu_acpi_obj_attrs[objtype].name, obj->Package.Count);
101 		goto out;
102 	}
103 
104 	/*
105 	 * Does the package look coherent?
106 	 */
107 	for (i = 0; i < obj->Package.Count; i++) {
108 		if (obj->Package.Elements[i].Type != ACPI_TYPE_BUFFER) {
109 			cmn_err(CE_NOTE, "!cpu_acpi: "
110 			    "Unexpected data in %s package.",
111 			    cpu_acpi_obj_attrs[objtype].name);
112 			goto out;
113 		}
114 
115 		greg = (AML_RESOURCE_GENERIC_REGISTER *)
116 		    obj->Package.Elements[i].Buffer.Pointer;
117 		if (greg->DescriptorType !=
118 		    ACPI_RESOURCE_NAME_GENERIC_REGISTER) {
119 			cmn_err(CE_NOTE, "!cpu_acpi: "
120 			    "%s package has format error.",
121 			    cpu_acpi_obj_attrs[objtype].name);
122 			goto out;
123 		}
124 		if (greg->ResourceLength !=
125 		    ACPI_AML_SIZE_LARGE(AML_RESOURCE_GENERIC_REGISTER)) {
126 			cmn_err(CE_NOTE, "!cpu_acpi: "
127 			    "%s package not right size.",
128 			    cpu_acpi_obj_attrs[objtype].name);
129 			goto out;
130 		}
131 		if (greg->AddressSpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE &&
132 		    greg->AddressSpaceId != ACPI_ADR_SPACE_SYSTEM_IO) {
133 			cmn_err(CE_NOTE, "!cpu_apci: %s contains unsupported "
134 			    "address space type %x",
135 			    cpu_acpi_obj_attrs[objtype].name,
136 			    greg->AddressSpaceId);
137 			goto out;
138 		}
139 	}
140 
141 	/*
142 	 * Looks good!
143 	 */
144 	for (i = 0; i < obj->Package.Count; i++) {
145 		greg = (AML_RESOURCE_GENERIC_REGISTER *)
146 		    obj->Package.Elements[i].Buffer.Pointer;
147 		regs[i].cr_addrspace_id = greg->AddressSpaceId;
148 		regs[i].cr_width = greg->BitWidth;
149 		regs[i].cr_offset = greg->BitOffset;
150 		regs[i].cr_asize = greg->AccessSize;
151 		regs[i].cr_address = greg->Address;
152 	}
153 	ret = 0;
154 out:
155 	AcpiOsFree(abuf.Pointer);
156 	return (ret);
157 }
158 
159 /*
160  * Cache the ACPI _PCT data. The _PCT data defines the interface to use
161  * when making power level transitions (i.e., system IO ports, fixed
162  * hardware port, etc).
163  */
164 static int
165 cpu_acpi_cache_pct(cpu_acpi_handle_t handle)
166 {
167 	cpu_acpi_pct_t *pct;
168 	int ret;
169 
170 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PCT_CACHED);
171 	pct = &CPU_ACPI_PCT(handle)[0];
172 	if ((ret = cpu_acpi_cache_ctrl_regs(handle, PCT_OBJ, pct)) == 0)
173 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PCT_CACHED);
174 	return (ret);
175 }
176 
177 /*
178  * Cache the ACPI _PTC data. The _PTC data defines the interface to use
179  * when making T-state transitions (i.e., system IO ports, fixed
180  * hardware port, etc).
181  */
182 static int
183 cpu_acpi_cache_ptc(cpu_acpi_handle_t handle)
184 {
185 	cpu_acpi_ptc_t *ptc;
186 	int ret;
187 
188 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PTC_CACHED);
189 	ptc = &CPU_ACPI_PTC(handle)[0];
190 	if ((ret = cpu_acpi_cache_ctrl_regs(handle, PTC_OBJ, ptc)) == 0)
191 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PTC_CACHED);
192 	return (ret);
193 }
194 
195 /*
196  * Cache the ACPI CPU state dependency data objects.
197  */
198 static int
199 cpu_acpi_cache_state_dependencies(cpu_acpi_handle_t handle,
200     cpu_acpi_obj_t objtype, cpu_acpi_state_dependency_t *sd)
201 {
202 	ACPI_BUFFER abuf;
203 	ACPI_OBJECT *pkg, *elements;
204 	int number;
205 	int ret = -1;
206 
207 	if (objtype == CSD_OBJ) {
208 		number = 6;
209 	} else {
210 		number = 5;
211 	}
212 	/*
213 	 * Fetch the dependencies (if present) for the CPU node.
214 	 * Since they are optional, non-existence is not a failure
215 	 * (it's up to the caller to determine how to handle non-existence).
216 	 */
217 	abuf.Length = ACPI_ALLOCATE_BUFFER;
218 	abuf.Pointer = NULL;
219 	if (ACPI_FAILURE(AcpiEvaluateObjectTyped(handle->cs_handle,
220 	    cpu_acpi_obj_attrs[objtype].name, NULL, &abuf,
221 	    ACPI_TYPE_PACKAGE))) {
222 		return (1);
223 	}
224 
225 	pkg = abuf.Pointer;
226 
227 	if (((objtype != CSD_OBJ) && (pkg->Package.Count != 1)) ||
228 	    ((objtype == CSD_OBJ) && (pkg->Package.Count != 1) &&
229 	    (pkg->Package.Count != 2))) {
230 		cmn_err(CE_NOTE, "!cpu_acpi: %s unsupported package "
231 		    "count %d.", cpu_acpi_obj_attrs[objtype].name,
232 		    pkg->Package.Count);
233 		goto out;
234 	}
235 
236 	/*
237 	 * For C-state domain, we assume C2 and C3 have the same
238 	 * domain information
239 	 */
240 	if (pkg->Package.Elements[0].Type != ACPI_TYPE_PACKAGE ||
241 	    pkg->Package.Elements[0].Package.Count != number) {
242 		cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in %s package.",
243 		    cpu_acpi_obj_attrs[objtype].name);
244 		goto out;
245 	}
246 	elements = pkg->Package.Elements[0].Package.Elements;
247 	if (elements[0].Integer.Value != number ||
248 	    elements[1].Integer.Value != 0) {
249 		cmn_err(CE_NOTE, "!cpu_acpi: Unexpected %s revision.",
250 		    cpu_acpi_obj_attrs[objtype].name);
251 		goto out;
252 	}
253 
254 	sd->sd_entries = elements[0].Integer.Value;
255 	sd->sd_revision = elements[1].Integer.Value;
256 	sd->sd_domain = elements[2].Integer.Value;
257 	sd->sd_type = elements[3].Integer.Value;
258 	sd->sd_num = elements[4].Integer.Value;
259 	if (objtype == CSD_OBJ) {
260 		sd->sd_index = elements[5].Integer.Value;
261 	}
262 
263 	ret = 0;
264 out:
265 	AcpiOsFree(abuf.Pointer);
266 	return (ret);
267 }
268 
269 /*
270  * Cache the ACPI _PSD data. The _PSD data defines P-state CPU dependencies
271  * (think CPU domains).
272  */
273 static int
274 cpu_acpi_cache_psd(cpu_acpi_handle_t handle)
275 {
276 	cpu_acpi_psd_t *psd;
277 	int ret;
278 
279 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PSD_CACHED);
280 	psd = &CPU_ACPI_PSD(handle);
281 	ret = cpu_acpi_cache_state_dependencies(handle, PSD_OBJ, psd);
282 	if (ret == 0)
283 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PSD_CACHED);
284 	return (ret);
285 
286 }
287 
288 /*
289  * Cache the ACPI _TSD data. The _TSD data defines T-state CPU dependencies
290  * (think CPU domains).
291  */
292 static int
293 cpu_acpi_cache_tsd(cpu_acpi_handle_t handle)
294 {
295 	cpu_acpi_tsd_t *tsd;
296 	int ret;
297 
298 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_TSD_CACHED);
299 	tsd = &CPU_ACPI_TSD(handle);
300 	ret = cpu_acpi_cache_state_dependencies(handle, TSD_OBJ, tsd);
301 	if (ret == 0)
302 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_TSD_CACHED);
303 	return (ret);
304 
305 }
306 
307 /*
308  * Cache the ACPI _CSD data. The _CSD data defines C-state CPU dependencies
309  * (think CPU domains).
310  */
311 static int
312 cpu_acpi_cache_csd(cpu_acpi_handle_t handle)
313 {
314 	cpu_acpi_csd_t *csd;
315 	int ret;
316 
317 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_CSD_CACHED);
318 	csd = &CPU_ACPI_CSD(handle);
319 	ret = cpu_acpi_cache_state_dependencies(handle, CSD_OBJ, csd);
320 	if (ret == 0)
321 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_CSD_CACHED);
322 	return (ret);
323 
324 }
325 
326 static void
327 cpu_acpi_cache_pstate(cpu_acpi_handle_t handle, ACPI_OBJECT *obj, int cnt)
328 {
329 	cpu_acpi_pstate_t *pstate;
330 	ACPI_OBJECT *q, *l;
331 	int i, j;
332 
333 	CPU_ACPI_PSTATES_COUNT(handle) = cnt;
334 	CPU_ACPI_PSTATES(handle) = kmem_zalloc(CPU_ACPI_PSTATES_SIZE(cnt),
335 	    KM_SLEEP);
336 	pstate = (cpu_acpi_pstate_t *)CPU_ACPI_PSTATES(handle);
337 	for (i = 0, l = NULL; i < obj->Package.Count && cnt > 0; i++, l = q) {
338 		uint32_t *up;
339 
340 		q = obj->Package.Elements[i].Package.Elements;
341 
342 		/*
343 		 * Skip duplicate entries.
344 		 */
345 		if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
346 			continue;
347 
348 		up = (uint32_t *)pstate;
349 		for (j = 0; j < CPU_ACPI_PSS_CNT; j++)
350 			up[j] = q[j].Integer.Value;
351 		pstate++;
352 		cnt--;
353 	}
354 }
355 
356 static void
357 cpu_acpi_cache_tstate(cpu_acpi_handle_t handle, ACPI_OBJECT *obj, int cnt)
358 {
359 	cpu_acpi_tstate_t *tstate;
360 	ACPI_OBJECT *q, *l;
361 	int i, j;
362 
363 	CPU_ACPI_TSTATES_COUNT(handle) = cnt;
364 	CPU_ACPI_TSTATES(handle) = kmem_zalloc(CPU_ACPI_TSTATES_SIZE(cnt),
365 	    KM_SLEEP);
366 	tstate = (cpu_acpi_tstate_t *)CPU_ACPI_TSTATES(handle);
367 	for (i = 0, l = NULL; i < obj->Package.Count && cnt > 0; i++, l = q) {
368 		uint32_t *up;
369 
370 		q = obj->Package.Elements[i].Package.Elements;
371 
372 		/*
373 		 * Skip duplicate entries.
374 		 */
375 		if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
376 			continue;
377 
378 		up = (uint32_t *)tstate;
379 		for (j = 0; j < CPU_ACPI_TSS_CNT; j++)
380 			up[j] = q[j].Integer.Value;
381 		tstate++;
382 		cnt--;
383 	}
384 }
385 
386 /*
387  * Cache the _PSS or _TSS data.
388  */
389 static int
390 cpu_acpi_cache_supported_states(cpu_acpi_handle_t handle,
391     cpu_acpi_obj_t objtype, int fcnt)
392 {
393 	ACPI_BUFFER abuf;
394 	ACPI_OBJECT *obj, *q, *l;
395 	boolean_t eot = B_FALSE;
396 	int ret = -1;
397 	int cnt;
398 	int i, j;
399 
400 	/*
401 	 * Fetch the data (if present) for the CPU node.
402 	 */
403 	abuf.Length = ACPI_ALLOCATE_BUFFER;
404 	abuf.Pointer = NULL;
405 	if (ACPI_FAILURE(AcpiEvaluateObjectTyped(handle->cs_handle,
406 	    cpu_acpi_obj_attrs[objtype].name, NULL, &abuf,
407 	    ACPI_TYPE_PACKAGE))) {
408 		cmn_err(CE_NOTE, "!cpu_acpi: %s package not found.",
409 		    cpu_acpi_obj_attrs[objtype].name);
410 		return (1);
411 	}
412 	obj = abuf.Pointer;
413 	if (obj->Package.Count < 2) {
414 		cmn_err(CE_NOTE, "!cpu_acpi: %s package bad count %d.",
415 		    cpu_acpi_obj_attrs[objtype].name, obj->Package.Count);
416 		goto out;
417 	}
418 
419 	/*
420 	 * Does the package look coherent?
421 	 */
422 	cnt = 0;
423 	for (i = 0, l = NULL; i < obj->Package.Count; i++, l = q) {
424 		if (obj->Package.Elements[i].Type != ACPI_TYPE_PACKAGE ||
425 		    obj->Package.Elements[i].Package.Count != fcnt) {
426 			cmn_err(CE_NOTE, "!cpu_acpi: "
427 			    "Unexpected data in %s package.",
428 			    cpu_acpi_obj_attrs[objtype].name);
429 			goto out;
430 		}
431 
432 		q = obj->Package.Elements[i].Package.Elements;
433 		for (j = 0; j < fcnt; j++) {
434 			if (q[j].Type != ACPI_TYPE_INTEGER) {
435 				cmn_err(CE_NOTE, "!cpu_acpi: "
436 				    "%s element invalid (type)",
437 				    cpu_acpi_obj_attrs[objtype].name);
438 				goto out;
439 			}
440 		}
441 
442 		/*
443 		 * Ignore duplicate entries.
444 		 */
445 		if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
446 			continue;
447 
448 		/*
449 		 * Some supported state tables are larger than required
450 		 * and unused elements are filled with patterns
451 		 * of 0xff.  Simply check here for frequency = 0xffff
452 		 * and stop counting if found.
453 		 */
454 		if (q[0].Integer.Value == 0xffff) {
455 			eot = B_TRUE;
456 			continue;
457 		}
458 
459 		/*
460 		 * We should never find a valid entry after we've hit
461 		 * an the end-of-table entry.
462 		 */
463 		if (eot) {
464 			cmn_err(CE_NOTE, "!cpu_acpi: "
465 			    "Unexpected data in %s package after eot.",
466 			    cpu_acpi_obj_attrs[objtype].name);
467 			goto out;
468 		}
469 
470 		/*
471 		 * states must be defined in order from highest to lowest.
472 		 */
473 		if (l != NULL && l[0].Integer.Value < q[0].Integer.Value) {
474 			cmn_err(CE_NOTE, "!cpu_acpi: "
475 			    "%s package state definitions out of order.",
476 			    cpu_acpi_obj_attrs[objtype].name);
477 			goto out;
478 		}
479 
480 		/*
481 		 * This entry passes.
482 		 */
483 		cnt++;
484 	}
485 	if (cnt == 0)
486 		goto out;
487 
488 	/*
489 	 * Yes, fill in the structure.
490 	 */
491 	ASSERT(objtype == PSS_OBJ || objtype == TSS_OBJ);
492 	(objtype == PSS_OBJ) ? cpu_acpi_cache_pstate(handle, obj, cnt) :
493 	    cpu_acpi_cache_tstate(handle, obj, cnt);
494 
495 	ret = 0;
496 out:
497 	AcpiOsFree(abuf.Pointer);
498 	return (ret);
499 }
500 
501 /*
502  * Cache the _PSS data. The _PSS data defines the different power levels
503  * supported by the CPU and the attributes associated with each power level
504  * (i.e., frequency, voltage, etc.). The power levels are number from
505  * highest to lowest. That is, the highest power level is _PSS entry 0
506  * and the lowest power level is the last _PSS entry.
507  */
508 static int
509 cpu_acpi_cache_pstates(cpu_acpi_handle_t handle)
510 {
511 	int ret;
512 
513 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PSS_CACHED);
514 	ret = cpu_acpi_cache_supported_states(handle, PSS_OBJ,
515 	    CPU_ACPI_PSS_CNT);
516 	if (ret == 0)
517 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PSS_CACHED);
518 	return (ret);
519 }
520 
521 /*
522  * Cache the _TSS data. The _TSS data defines the different freq throttle
523  * levels supported by the CPU and the attributes associated with each
524  * throttle level (i.e., frequency throttle percentage, voltage, etc.).
525  * The throttle levels are number from highest to lowest.
526  */
527 static int
528 cpu_acpi_cache_tstates(cpu_acpi_handle_t handle)
529 {
530 	int ret;
531 
532 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_TSS_CACHED);
533 	ret = cpu_acpi_cache_supported_states(handle, TSS_OBJ,
534 	    CPU_ACPI_TSS_CNT);
535 	if (ret == 0)
536 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_TSS_CACHED);
537 	return (ret);
538 }
539 
540 /*
541  * Cache the ACPI CPU present capabilities data objects.
542  */
543 static int
544 cpu_acpi_cache_present_capabilities(cpu_acpi_handle_t handle,
545     cpu_acpi_obj_t objtype, cpu_acpi_present_capabilities_t *pc)
546 
547 {
548 	ACPI_BUFFER abuf;
549 	ACPI_OBJECT *obj;
550 
551 	/*
552 	 * Fetch the present capabilites object (if present) for the CPU node.
553 	 * Since they are optional, non-existence is not a failure.
554 	 */
555 	abuf.Length = ACPI_ALLOCATE_BUFFER;
556 	abuf.Pointer = NULL;
557 	if (ACPI_FAILURE(AcpiEvaluateObject(handle->cs_handle,
558 	    cpu_acpi_obj_attrs[objtype].name, NULL, &abuf)) ||
559 	    abuf.Length == 0) {
560 		*pc = 0;
561 		return (1);
562 	}
563 
564 	obj = (ACPI_OBJECT *)abuf.Pointer;
565 	*pc = obj->Integer.Value;
566 	AcpiOsFree(abuf.Pointer);
567 	return (0);
568 }
569 
570 /*
571  * Cache the _PPC data. The _PPC simply contains an integer value which
572  * represents the highest power level that a CPU should transition to.
573  * That is, it's an index into the array of _PSS entries and will be
574  * greater than or equal to zero.
575  */
576 void
577 cpu_acpi_cache_ppc(cpu_acpi_handle_t handle)
578 {
579 	cpu_acpi_ppc_t *ppc;
580 	int ret;
581 
582 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PPC_CACHED);
583 	ppc = &CPU_ACPI_PPC(handle);
584 	ret = cpu_acpi_cache_present_capabilities(handle, PPC_OBJ, ppc);
585 	if (ret == 0)
586 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PPC_CACHED);
587 }
588 
589 /*
590  * Cache the _TPC data. The _TPC simply contains an integer value which
591  * represents the throttle level that a CPU should transition to.
592  * That is, it's an index into the array of _TSS entries and will be
593  * greater than or equal to zero.
594  */
595 void
596 cpu_acpi_cache_tpc(cpu_acpi_handle_t handle)
597 {
598 	cpu_acpi_tpc_t *tpc;
599 	int ret;
600 
601 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_TPC_CACHED);
602 	tpc = &CPU_ACPI_TPC(handle);
603 	ret = cpu_acpi_cache_present_capabilities(handle, TPC_OBJ, tpc);
604 	if (ret == 0)
605 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_TPC_CACHED);
606 }
607 
608 int
609 cpu_acpi_verify_cstate(cpu_acpi_cstate_t *cstate)
610 {
611 	uint32_t addrspaceid = cstate->cs_addrspace_id;
612 
613 	if ((addrspaceid != ACPI_ADR_SPACE_FIXED_HARDWARE) &&
614 	    (addrspaceid != ACPI_ADR_SPACE_SYSTEM_IO)) {
615 		cmn_err(CE_WARN, "!_CST: unsupported address space id"
616 		    ":C%d, type: %d\n", cstate->cs_type, addrspaceid);
617 		return (1);
618 	}
619 	return (0);
620 }
621 
622 int
623 cpu_acpi_cache_cst(cpu_acpi_handle_t handle)
624 {
625 	ACPI_BUFFER abuf;
626 	ACPI_OBJECT *obj;
627 	ACPI_INTEGER cnt;
628 	cpu_acpi_cstate_t *cstate, *p;
629 	int i, count;
630 
631 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_CST_CACHED);
632 
633 	abuf.Length = ACPI_ALLOCATE_BUFFER;
634 	abuf.Pointer = NULL;
635 
636 	if (ACPI_FAILURE(AcpiEvaluateObject(handle->cs_handle, "_CST",
637 	    NULL, &abuf))) {
638 		cmn_err(CE_NOTE, "!cpu_acpi: _CST evaluate failure");
639 		return (-1);
640 	}
641 	obj = (ACPI_OBJECT *)abuf.Pointer;
642 	if (obj->Package.Count < 2) {
643 		cmn_err(CE_NOTE, "!cpu_acpi: _CST package bad count %d.",
644 		    obj->Package.Count);
645 		AcpiOsFree(abuf.Pointer);
646 		return (-1);
647 	}
648 
649 	/*
650 	 * Does the package look coherent?
651 	 */
652 	cnt = obj->Package.Elements[0].Integer.Value;
653 	if (cnt < 1 || cnt != obj->Package.Count - 1) {
654 		cmn_err(CE_NOTE, "!cpu_acpi: _CST invalid element count %d != "
655 		    "Package count %d\n",
656 		    (int)cnt, (int)obj->Package.Count - 1);
657 		AcpiOsFree(abuf.Pointer);
658 		return (-1);
659 	}
660 
661 	CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)cnt;
662 	CPU_ACPI_CSTATES(handle) = kmem_zalloc(CPU_ACPI_CSTATES_SIZE(cnt),
663 	    KM_SLEEP);
664 	CPU_ACPI_BM_INFO(handle) = 0;
665 	cstate = (cpu_acpi_cstate_t *)CPU_ACPI_CSTATES(handle);
666 	p = cstate;
667 
668 	for (i = 1, count = 1; i <= cnt; i++) {
669 		ACPI_OBJECT *pkg;
670 		AML_RESOURCE_GENERIC_REGISTER *reg;
671 		ACPI_OBJECT *element;
672 
673 		pkg = &(obj->Package.Elements[i]);
674 		reg = (AML_RESOURCE_GENERIC_REGISTER *)
675 		    pkg->Package.Elements[0].Buffer.Pointer;
676 		cstate->cs_addrspace_id = reg->AddressSpaceId;
677 		cstate->cs_address = reg->Address;
678 		element = &(pkg->Package.Elements[1]);
679 		cstate->cs_type = element->Integer.Value;
680 		element = &(pkg->Package.Elements[2]);
681 		cstate->cs_latency = element->Integer.Value;
682 		element = &(pkg->Package.Elements[3]);
683 		cstate->cs_power = element->Integer.Value;
684 
685 		if (cpu_acpi_verify_cstate(cstate)) {
686 			/*
687 			 * ignore this entry if it's not valid
688 			 */
689 			continue;
690 		}
691 		if (cstate == p) {
692 			cstate++;
693 		} else if (p->cs_type == cstate->cs_type) {
694 			/*
695 			 * if there are duplicate entries, we keep the
696 			 * last one. This fixes:
697 			 * 1) some buggy BIOS have total duplicate entries.
698 			 * 2) ACPI Spec allows the same cstate entry with
699 			 *    different power and latency, we use the one
700 			 *    with more power saving.
701 			 */
702 			(void) memcpy(p, cstate, sizeof (cpu_acpi_cstate_t));
703 		} else {
704 			/*
705 			 * we got a valid entry, cache it to the
706 			 * cstate structure
707 			 */
708 			p = cstate++;
709 			count++;
710 		}
711 	}
712 
713 	if (count < 2) {
714 		cmn_err(CE_NOTE, "!cpu_acpi: _CST invalid count %d < 2\n",
715 		    count);
716 		AcpiOsFree(abuf.Pointer);
717 		return (-1);
718 	}
719 
720 	if (count != cnt)
721 		CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)count;
722 
723 	AcpiOsFree(abuf.Pointer);
724 	CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_CST_CACHED);
725 	return (0);
726 }
727 
728 /*
729  * Cache the _PCT, _PSS, _PSD and _PPC data.
730  */
731 int
732 cpu_acpi_cache_pstate_data(cpu_acpi_handle_t handle)
733 {
734 	if (cpu_acpi_cache_pct(handle) < 0) {
735 		cmn_err(CE_WARN, "!cpu_acpi: error parsing _PCT for "
736 		    "CPU %d", handle->cs_id);
737 		return (-1);
738 	}
739 
740 	if (cpu_acpi_cache_pstates(handle) != 0) {
741 		cmn_err(CE_WARN, "!cpu_acpi: error parsing _PSS for "
742 		    "CPU %d", handle->cs_id);
743 		return (-1);
744 	}
745 
746 	if (cpu_acpi_cache_psd(handle) < 0) {
747 		cmn_err(CE_WARN, "!cpu_acpi: error parsing _PSD for "
748 		    "CPU %d", handle->cs_id);
749 		return (-1);
750 	}
751 
752 	cpu_acpi_cache_ppc(handle);
753 
754 	return (0);
755 }
756 
757 void
758 cpu_acpi_free_pstate_data(cpu_acpi_handle_t handle)
759 {
760 	if (handle != NULL) {
761 		if (CPU_ACPI_PSTATES(handle)) {
762 			kmem_free(CPU_ACPI_PSTATES(handle),
763 			    CPU_ACPI_PSTATES_SIZE(
764 			    CPU_ACPI_PSTATES_COUNT(handle)));
765 			CPU_ACPI_PSTATES(handle) = NULL;
766 		}
767 	}
768 }
769 
770 /*
771  * Cache the _PTC, _TSS, _TSD and _TPC data.
772  */
773 int
774 cpu_acpi_cache_tstate_data(cpu_acpi_handle_t handle)
775 {
776 	if (cpu_acpi_cache_ptc(handle) < 0) {
777 		cmn_err(CE_WARN, "!cpu_acpi: error parsing _PTC for "
778 		    "CPU %d", handle->cs_id);
779 		return (-1);
780 	}
781 
782 	if (cpu_acpi_cache_tstates(handle) != 0) {
783 		cmn_err(CE_WARN, "!cpu_acpi: error parsing _TSS for "
784 		    "CPU %d", handle->cs_id);
785 		return (-1);
786 	}
787 
788 	if (cpu_acpi_cache_tsd(handle) < 0) {
789 		cmn_err(CE_WARN, "!cpu_acpi: error parsing _TSD for "
790 		    "CPU %d", handle->cs_id);
791 		return (-1);
792 	}
793 
794 	cpu_acpi_cache_tpc(handle);
795 
796 	return (0);
797 }
798 
799 void
800 cpu_acpi_free_tstate_data(cpu_acpi_handle_t handle)
801 {
802 	if (handle != NULL) {
803 		if (CPU_ACPI_TSTATES(handle)) {
804 			kmem_free(CPU_ACPI_TSTATES(handle),
805 			    CPU_ACPI_TSTATES_SIZE(
806 			    CPU_ACPI_TSTATES_COUNT(handle)));
807 			CPU_ACPI_TSTATES(handle) = NULL;
808 		}
809 	}
810 }
811 
812 /*
813  * Cache the _CST data.
814  */
815 int
816 cpu_acpi_cache_cstate_data(cpu_acpi_handle_t handle)
817 {
818 	if (cpu_acpi_cache_cst(handle) < 0) {
819 		cmn_err(CE_WARN, "!cpu_acpi: error parsing _CST for "
820 		    "CPU %d", handle->cs_id);
821 		return (-1);
822 	}
823 
824 	if (cpu_acpi_cache_csd(handle) < 0) {
825 		cmn_err(CE_WARN, "!cpu_acpi: error parsing _CSD for "
826 		    "CPU %d", handle->cs_id);
827 		return (-1);
828 	}
829 
830 	return (0);
831 }
832 
833 void
834 cpu_acpi_free_cstate_data(cpu_acpi_handle_t handle)
835 {
836 	if (handle != NULL) {
837 		if (CPU_ACPI_CSTATES(handle)) {
838 			kmem_free(CPU_ACPI_CSTATES(handle),
839 			    CPU_ACPI_CSTATES_SIZE(
840 			    CPU_ACPI_CSTATES_COUNT(handle)));
841 			CPU_ACPI_CSTATES(handle) = NULL;
842 		}
843 	}
844 }
845 
846 /*
847  * Register a handler for processor change notifications.
848  */
849 void
850 cpu_acpi_install_notify_handler(cpu_acpi_handle_t handle,
851     ACPI_NOTIFY_HANDLER handler, void *ctx)
852 {
853 	if (ACPI_FAILURE(AcpiInstallNotifyHandler(handle->cs_handle,
854 	    ACPI_DEVICE_NOTIFY, handler, ctx)))
855 		cmn_err(CE_NOTE, "!cpu_acpi: Unable to register "
856 		    "notify handler for CPU");
857 }
858 
859 /*
860  * Remove a handler for processor change notifications.
861  */
862 void
863 cpu_acpi_remove_notify_handler(cpu_acpi_handle_t handle,
864     ACPI_NOTIFY_HANDLER handler)
865 {
866 	if (ACPI_FAILURE(AcpiRemoveNotifyHandler(handle->cs_handle,
867 	    ACPI_DEVICE_NOTIFY, handler)))
868 		cmn_err(CE_NOTE, "!cpu_acpi: Unable to remove "
869 		    "notify handler for CPU");
870 }
871 
872 /*
873  * Write _PDC.
874  */
875 int
876 cpu_acpi_write_pdc(cpu_acpi_handle_t handle, uint32_t revision, uint32_t count,
877     uint32_t *capabilities)
878 {
879 	ACPI_OBJECT obj;
880 	ACPI_OBJECT_LIST list = { 1, &obj};
881 	uint32_t *buffer;
882 	uint32_t *bufptr;
883 	uint32_t bufsize;
884 	int i;
885 
886 	bufsize = (count + 2) * sizeof (uint32_t);
887 	buffer = kmem_zalloc(bufsize, KM_SLEEP);
888 	buffer[0] = revision;
889 	buffer[1] = count;
890 	bufptr = &buffer[2];
891 	for (i = 0; i < count; i++)
892 		*bufptr++ = *capabilities++;
893 
894 	obj.Type = ACPI_TYPE_BUFFER;
895 	obj.Buffer.Length = bufsize;
896 	obj.Buffer.Pointer = (void *)buffer;
897 
898 	/*
899 	 * _PDC is optional, so don't log failure.
900 	 */
901 	if (ACPI_FAILURE(AcpiEvaluateObject(handle->cs_handle, "_PDC",
902 	    &list, NULL))) {
903 		kmem_free(buffer, bufsize);
904 		return (-1);
905 	}
906 
907 	kmem_free(buffer, bufsize);
908 	return (0);
909 }
910 
911 /*
912  * Write to system IO port.
913  */
914 int
915 cpu_acpi_write_port(ACPI_IO_ADDRESS address, uint32_t value, uint32_t width)
916 {
917 	if (ACPI_FAILURE(AcpiOsWritePort(address, value, width))) {
918 		cmn_err(CE_NOTE, "cpu_acpi: error writing system IO port "
919 		    "%lx.", (long)address);
920 		return (-1);
921 	}
922 	return (0);
923 }
924 
925 /*
926  * Read from a system IO port.
927  */
928 int
929 cpu_acpi_read_port(ACPI_IO_ADDRESS address, uint32_t *value, uint32_t width)
930 {
931 	if (ACPI_FAILURE(AcpiOsReadPort(address, value, width))) {
932 		cmn_err(CE_NOTE, "cpu_acpi: error reading system IO port "
933 		    "%lx.", (long)address);
934 		return (-1);
935 	}
936 	return (0);
937 }
938 
939 /*
940  * Return supported frequencies.
941  */
942 uint_t
943 cpu_acpi_get_speeds(cpu_acpi_handle_t handle, int **speeds)
944 {
945 	cpu_acpi_pstate_t *pstate;
946 	int *hspeeds;
947 	uint_t nspeeds;
948 	int i;
949 
950 	nspeeds = CPU_ACPI_PSTATES_COUNT(handle);
951 	pstate = (cpu_acpi_pstate_t *)CPU_ACPI_PSTATES(handle);
952 	hspeeds = kmem_zalloc(nspeeds * sizeof (int), KM_SLEEP);
953 	for (i = 0; i < nspeeds; i++) {
954 		hspeeds[i] = CPU_ACPI_FREQ(pstate);
955 		pstate++;
956 	}
957 	*speeds = hspeeds;
958 	return (nspeeds);
959 }
960 
961 /*
962  * Free resources allocated by cpu_acpi_get_speeds().
963  */
964 void
965 cpu_acpi_free_speeds(int *speeds, uint_t nspeeds)
966 {
967 	kmem_free(speeds, nspeeds * sizeof (int));
968 }
969 
970 uint_t
971 cpu_acpi_get_max_cstates(cpu_acpi_handle_t handle)
972 {
973 	if (CPU_ACPI_CSTATES(handle))
974 		return (CPU_ACPI_CSTATES_COUNT(handle));
975 	else
976 		return (1);
977 }
978 
979 void
980 cpu_acpi_set_register(uint32_t bitreg, uint32_t value)
981 {
982 	AcpiSetRegister(bitreg, value);
983 }
984 
985 void
986 cpu_acpi_get_register(uint32_t bitreg, uint32_t *value)
987 {
988 	AcpiGetRegister(bitreg, value);
989 }
990 
991 /*
992  * Map the dip to an ACPI handle for the device.
993  */
994 cpu_acpi_handle_t
995 cpu_acpi_init(cpu_t *cp)
996 {
997 	cpu_acpi_handle_t handle;
998 
999 	handle = kmem_zalloc(sizeof (cpu_acpi_state_t), KM_SLEEP);
1000 
1001 	if (ACPI_FAILURE(acpica_get_handle_cpu(cp->cpu_id,
1002 	    &handle->cs_handle))) {
1003 		kmem_free(handle, sizeof (cpu_acpi_state_t));
1004 		return (NULL);
1005 	}
1006 	handle->cs_id = cp->cpu_id;
1007 	return (handle);
1008 }
1009 
1010 /*
1011  * Free any resources.
1012  */
1013 void
1014 cpu_acpi_fini(cpu_acpi_handle_t handle)
1015 {
1016 	if (handle)
1017 		kmem_free(handle, sizeof (cpu_acpi_state_t));
1018 }
1019