xref: /illumos-gate/usr/src/uts/i86pc/os/cpupm/cpu_acpi.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 	CPU_ACPI_BM_INFO(handle) = 0;
738 	cstate = (cpu_acpi_cstate_t *)CPU_ACPI_CSTATES(handle);
739 	p = cstate;
740 
741 	for (i = 1, count = 1; i <= cnt; i++) {
742 		ACPI_OBJECT *pkg;
743 		AML_RESOURCE_GENERIC_REGISTER *reg;
744 		ACPI_OBJECT *element;
745 
746 		pkg = &(obj->Package.Elements[i]);
747 		reg = (AML_RESOURCE_GENERIC_REGISTER *)
748 		    pkg->Package.Elements[0].Buffer.Pointer;
749 		cstate->cs_addrspace_id = reg->AddressSpaceId;
750 		cstate->cs_address = reg->Address;
751 		element = &(pkg->Package.Elements[1]);
752 		cstate->cs_type = element->Integer.Value;
753 		element = &(pkg->Package.Elements[2]);
754 		cstate->cs_latency = element->Integer.Value;
755 		element = &(pkg->Package.Elements[3]);
756 		cstate->cs_power = element->Integer.Value;
757 
758 		if (cpu_acpi_verify_cstate(cstate)) {
759 			/*
760 			 * ignore this entry if it's not valid
761 			 */
762 			continue;
763 		}
764 		if (cstate == p) {
765 			cstate++;
766 		} else if (p->cs_type == cstate->cs_type) {
767 			/*
768 			 * if there are duplicate entries, we keep the
769 			 * last one. This fixes:
770 			 * 1) some buggy BIOS have total duplicate entries.
771 			 * 2) ACPI Spec allows the same cstate entry with
772 			 *    different power and latency, we use the one
773 			 *    with more power saving.
774 			 */
775 			(void) memcpy(p, cstate, sizeof (cpu_acpi_cstate_t));
776 		} else {
777 			/*
778 			 * we got a valid entry, cache it to the
779 			 * cstate structure
780 			 */
781 			p = cstate++;
782 			count++;
783 		}
784 	}
785 
786 	if (count < 2) {
787 		cmn_err(CE_NOTE, "!cpu_acpi: _CST invalid count %d < 2 for "
788 		    "CPU %d", count, handle->cs_id);
789 		kmem_free(CPU_ACPI_CSTATES(handle), alloc_size);
790 		CPU_ACPI_CSTATES(handle) = NULL;
791 		CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)0;
792 		goto out;
793 	}
794 	cstate = (cpu_acpi_cstate_t *)CPU_ACPI_CSTATES(handle);
795 	if (cstate[0].cs_type != CPU_ACPI_C1) {
796 		cmn_err(CE_NOTE, "!cpu_acpi: _CST first element type not "
797 		    "C1: %d for CPU %d", (int)cstate->cs_type, handle->cs_id);
798 		kmem_free(CPU_ACPI_CSTATES(handle), alloc_size);
799 		CPU_ACPI_CSTATES(handle) = NULL;
800 		CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)0;
801 		goto out;
802 	}
803 
804 	if (count != cnt) {
805 		void	*orig = CPU_ACPI_CSTATES(handle);
806 
807 		CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)count;
808 		CPU_ACPI_CSTATES(handle) = kmem_zalloc(
809 		    CPU_ACPI_CSTATES_SIZE(count), KM_SLEEP);
810 		(void) memcpy(CPU_ACPI_CSTATES(handle), orig,
811 		    CPU_ACPI_CSTATES_SIZE(count));
812 		kmem_free(orig, alloc_size);
813 	}
814 
815 	CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_CST_CACHED);
816 
817 	ret = 0;
818 
819 out:
820 	if (abuf.Pointer != NULL)
821 		AcpiOsFree(abuf.Pointer);
822 	return (ret);
823 }
824 
825 /*
826  * Cache the _PCT, _PSS, _PSD and _PPC data.
827  */
828 int
829 cpu_acpi_cache_pstate_data(cpu_acpi_handle_t handle)
830 {
831 	if (cpu_acpi_cache_pct(handle) < 0) {
832 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
833 		    int, PCT_OBJ);
834 		cmn_err(CE_NOTE, "!cpu_acpi: error parsing _PCT for "
835 		    "CPU %d", handle->cs_id);
836 		return (-1);
837 	}
838 
839 	if (cpu_acpi_cache_pstates(handle) != 0) {
840 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
841 		    int, PSS_OBJ);
842 		cmn_err(CE_NOTE, "!cpu_acpi: error parsing _PSS for "
843 		    "CPU %d", handle->cs_id);
844 		return (-1);
845 	}
846 
847 	if (cpu_acpi_cache_psd(handle) < 0) {
848 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
849 		    int, PSD_OBJ);
850 		cmn_err(CE_NOTE, "!cpu_acpi: error parsing _PSD for "
851 		    "CPU %d", handle->cs_id);
852 		return (-1);
853 	}
854 
855 	cpu_acpi_cache_ppc(handle);
856 
857 	return (0);
858 }
859 
860 void
861 cpu_acpi_free_pstate_data(cpu_acpi_handle_t handle)
862 {
863 	if (handle != NULL) {
864 		if (CPU_ACPI_PSTATES(handle)) {
865 			kmem_free(CPU_ACPI_PSTATES(handle),
866 			    CPU_ACPI_PSTATES_SIZE(
867 			    CPU_ACPI_PSTATES_COUNT(handle)));
868 			CPU_ACPI_PSTATES(handle) = NULL;
869 		}
870 	}
871 }
872 
873 /*
874  * Cache the _PTC, _TSS, _TSD and _TPC data.
875  */
876 int
877 cpu_acpi_cache_tstate_data(cpu_acpi_handle_t handle)
878 {
879 	int ret;
880 
881 	if (cpu_acpi_cache_ptc(handle) < 0) {
882 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
883 		    int, PTC_OBJ);
884 		return (-1);
885 	}
886 
887 	if ((ret = cpu_acpi_cache_tstates(handle)) != 0) {
888 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
889 		    int, TSS_OBJ);
890 		return (ret);
891 	}
892 
893 	if (cpu_acpi_cache_tsd(handle) < 0) {
894 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
895 		    int, TSD_OBJ);
896 		return (-1);
897 	}
898 
899 	cpu_acpi_cache_tpc(handle);
900 
901 	return (0);
902 }
903 
904 void
905 cpu_acpi_free_tstate_data(cpu_acpi_handle_t handle)
906 {
907 	if (handle != NULL) {
908 		if (CPU_ACPI_TSTATES(handle)) {
909 			kmem_free(CPU_ACPI_TSTATES(handle),
910 			    CPU_ACPI_TSTATES_SIZE(
911 			    CPU_ACPI_TSTATES_COUNT(handle)));
912 			CPU_ACPI_TSTATES(handle) = NULL;
913 		}
914 	}
915 }
916 
917 /*
918  * Cache the _CST data.
919  */
920 int
921 cpu_acpi_cache_cstate_data(cpu_acpi_handle_t handle)
922 {
923 	int ret;
924 
925 	if ((ret = cpu_acpi_cache_cst(handle)) != 0) {
926 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
927 		    int, CST_OBJ);
928 		return (ret);
929 	}
930 
931 	if (cpu_acpi_cache_csd(handle) < 0) {
932 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
933 		    int, CSD_OBJ);
934 		return (-1);
935 	}
936 
937 	return (0);
938 }
939 
940 void
941 cpu_acpi_free_cstate_data(cpu_acpi_handle_t handle)
942 {
943 	if (handle != NULL) {
944 		if (CPU_ACPI_CSTATES(handle)) {
945 			kmem_free(CPU_ACPI_CSTATES(handle),
946 			    CPU_ACPI_CSTATES_SIZE(
947 			    CPU_ACPI_CSTATES_COUNT(handle)));
948 			CPU_ACPI_CSTATES(handle) = NULL;
949 		}
950 	}
951 }
952 
953 /*
954  * Register a handler for processor change notifications.
955  */
956 void
957 cpu_acpi_install_notify_handler(cpu_acpi_handle_t handle,
958     ACPI_NOTIFY_HANDLER handler, void *ctx)
959 {
960 	if (ACPI_FAILURE(AcpiInstallNotifyHandler(handle->cs_handle,
961 	    ACPI_DEVICE_NOTIFY, handler, ctx)))
962 		cmn_err(CE_NOTE, "!cpu_acpi: Unable to register "
963 		    "notify handler for CPU %d.", handle->cs_id);
964 }
965 
966 /*
967  * Remove a handler for processor change notifications.
968  */
969 void
970 cpu_acpi_remove_notify_handler(cpu_acpi_handle_t handle,
971     ACPI_NOTIFY_HANDLER handler)
972 {
973 	if (ACPI_FAILURE(AcpiRemoveNotifyHandler(handle->cs_handle,
974 	    ACPI_DEVICE_NOTIFY, handler)))
975 		cmn_err(CE_NOTE, "!cpu_acpi: Unable to remove "
976 		    "notify handler for CPU %d.", handle->cs_id);
977 }
978 
979 /*
980  * Write _PDC.
981  */
982 int
983 cpu_acpi_write_pdc(cpu_acpi_handle_t handle, uint32_t revision, uint32_t count,
984     uint32_t *capabilities)
985 {
986 	ACPI_STATUS astatus;
987 	ACPI_OBJECT obj;
988 	ACPI_OBJECT_LIST list = { 1, &obj};
989 	uint32_t *buffer;
990 	uint32_t *bufptr;
991 	uint32_t bufsize;
992 	int i;
993 	int ret = 0;
994 
995 	bufsize = (count + 2) * sizeof (uint32_t);
996 	buffer = kmem_zalloc(bufsize, KM_SLEEP);
997 	buffer[0] = revision;
998 	buffer[1] = count;
999 	bufptr = &buffer[2];
1000 	for (i = 0; i < count; i++)
1001 		*bufptr++ = *capabilities++;
1002 
1003 	obj.Type = ACPI_TYPE_BUFFER;
1004 	obj.Buffer.Length = bufsize;
1005 	obj.Buffer.Pointer = (void *)buffer;
1006 
1007 	/*
1008 	 * Fetch the ??? (if present) for the CPU node.
1009 	 */
1010 	astatus = AcpiEvaluateObject(handle->cs_handle, "_PDC", &list, NULL);
1011 	if (ACPI_FAILURE(astatus)) {
1012 		if (astatus == AE_NOT_FOUND) {
1013 			DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
1014 			    int, PDC_OBJ, int, astatus);
1015 			ret = 1;
1016 		} else {
1017 			cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating _PDC "
1018 			    "package for CPU %d.", astatus, handle->cs_id);
1019 			ret = -1;
1020 		}
1021 	}
1022 
1023 	kmem_free(buffer, bufsize);
1024 	return (ret);
1025 }
1026 
1027 /*
1028  * Write to system IO port.
1029  */
1030 int
1031 cpu_acpi_write_port(ACPI_IO_ADDRESS address, uint32_t value, uint32_t width)
1032 {
1033 	if (ACPI_FAILURE(AcpiOsWritePort(address, value, width))) {
1034 		cmn_err(CE_NOTE, "!cpu_acpi: error writing system IO port "
1035 		    "%lx.", (long)address);
1036 		return (-1);
1037 	}
1038 	return (0);
1039 }
1040 
1041 /*
1042  * Read from a system IO port.
1043  */
1044 int
1045 cpu_acpi_read_port(ACPI_IO_ADDRESS address, uint32_t *value, uint32_t width)
1046 {
1047 	if (ACPI_FAILURE(AcpiOsReadPort(address, value, width))) {
1048 		cmn_err(CE_NOTE, "!cpu_acpi: error reading system IO port "
1049 		    "%lx.", (long)address);
1050 		return (-1);
1051 	}
1052 	return (0);
1053 }
1054 
1055 /*
1056  * Return supported frequencies.
1057  */
1058 uint_t
1059 cpu_acpi_get_speeds(cpu_acpi_handle_t handle, int **speeds)
1060 {
1061 	cpu_acpi_pstate_t *pstate;
1062 	int *hspeeds;
1063 	uint_t nspeeds;
1064 	int i;
1065 
1066 	nspeeds = CPU_ACPI_PSTATES_COUNT(handle);
1067 	pstate = (cpu_acpi_pstate_t *)CPU_ACPI_PSTATES(handle);
1068 	hspeeds = kmem_zalloc(nspeeds * sizeof (int), KM_SLEEP);
1069 	for (i = 0; i < nspeeds; i++) {
1070 		hspeeds[i] = CPU_ACPI_FREQ(pstate);
1071 		pstate++;
1072 	}
1073 	*speeds = hspeeds;
1074 	return (nspeeds);
1075 }
1076 
1077 /*
1078  * Free resources allocated by cpu_acpi_get_speeds().
1079  */
1080 void
1081 cpu_acpi_free_speeds(int *speeds, uint_t nspeeds)
1082 {
1083 	kmem_free(speeds, nspeeds * sizeof (int));
1084 }
1085 
1086 uint_t
1087 cpu_acpi_get_max_cstates(cpu_acpi_handle_t handle)
1088 {
1089 	if (CPU_ACPI_CSTATES(handle))
1090 		return (CPU_ACPI_CSTATES_COUNT(handle));
1091 	else
1092 		return (1);
1093 }
1094 
1095 void
1096 cpu_acpi_set_register(uint32_t bitreg, uint32_t value)
1097 {
1098 	AcpiWriteBitRegister(bitreg, value);
1099 }
1100 
1101 void
1102 cpu_acpi_get_register(uint32_t bitreg, uint32_t *value)
1103 {
1104 	AcpiReadBitRegister(bitreg, value);
1105 }
1106 
1107 /*
1108  * Map the dip to an ACPI handle for the device.
1109  */
1110 cpu_acpi_handle_t
1111 cpu_acpi_init(cpu_t *cp)
1112 {
1113 	cpu_acpi_handle_t handle;
1114 
1115 	handle = kmem_zalloc(sizeof (cpu_acpi_state_t), KM_SLEEP);
1116 
1117 	if (ACPI_FAILURE(acpica_get_handle_cpu(cp->cpu_id,
1118 	    &handle->cs_handle))) {
1119 		kmem_free(handle, sizeof (cpu_acpi_state_t));
1120 		return (NULL);
1121 	}
1122 	handle->cs_id = cp->cpu_id;
1123 	return (handle);
1124 }
1125 
1126 /*
1127  * Free any resources.
1128  */
1129 void
1130 cpu_acpi_fini(cpu_acpi_handle_t handle)
1131 {
1132 	if (handle)
1133 		kmem_free(handle, sizeof (cpu_acpi_state_t));
1134 }
1135