Home | History | Annotate | Download | only in cpupm
      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