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