xref: /titanic_51/usr/src/uts/i86pc/os/cpupm/cpu_acpi.c (revision 511588bb13d2462265d682dc1cb7ba5c7a27a771)
10e751525SEric Saxe /*
20e751525SEric Saxe  * CDDL HEADER START
30e751525SEric Saxe  *
40e751525SEric Saxe  * The contents of this file are subject to the terms of the
50e751525SEric Saxe  * Common Development and Distribution License (the "License").
60e751525SEric Saxe  * You may not use this file except in compliance with the License.
70e751525SEric Saxe  *
80e751525SEric Saxe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90e751525SEric Saxe  * or http://www.opensolaris.org/os/licensing.
100e751525SEric Saxe  * See the License for the specific language governing permissions
110e751525SEric Saxe  * and limitations under the License.
120e751525SEric Saxe  *
130e751525SEric Saxe  * When distributing Covered Code, include this CDDL HEADER in each
140e751525SEric Saxe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150e751525SEric Saxe  * If applicable, add the following below this CDDL HEADER, with the
160e751525SEric Saxe  * fields enclosed by brackets "[]" replaced with your own identifying
170e751525SEric Saxe  * information: Portions Copyright [yyyy] [name of copyright owner]
180e751525SEric Saxe  *
190e751525SEric Saxe  * CDDL HEADER END
200e751525SEric Saxe  */
210e751525SEric Saxe /*
22*b3ffafc5Sjiang.liu@intel.com  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
230e751525SEric Saxe  */
240e751525SEric Saxe 
250e751525SEric Saxe #include <sys/cpu_acpi.h>
269aa01d98SBill Holler #include <sys/cpu_idle.h>
2737d22dc0SAnup Pemmaiah #include <sys/dtrace.h>
2837d22dc0SAnup Pemmaiah #include <sys/sdt.h>
290e751525SEric Saxe 
300e751525SEric Saxe /*
310e751525SEric Saxe  * List of the processor ACPI object types that are being used.
320e751525SEric Saxe  */
330e751525SEric Saxe typedef enum cpu_acpi_obj {
340e751525SEric Saxe 	PDC_OBJ = 0,
350e751525SEric Saxe 	PCT_OBJ,
360e751525SEric Saxe 	PSS_OBJ,
370e751525SEric Saxe 	PSD_OBJ,
380e751525SEric Saxe 	PPC_OBJ,
390e751525SEric Saxe 	PTC_OBJ,
400e751525SEric Saxe 	TSS_OBJ,
410e751525SEric Saxe 	TSD_OBJ,
420e751525SEric Saxe 	TPC_OBJ,
4300f97612SMark Haywood 	CST_OBJ,
440e751525SEric Saxe 	CSD_OBJ,
450e751525SEric Saxe } cpu_acpi_obj_t;
460e751525SEric Saxe 
470e751525SEric Saxe /*
480e751525SEric Saxe  * Container to store object name.
490e751525SEric Saxe  * Other attributes can be added in the future as necessary.
500e751525SEric Saxe  */
510e751525SEric Saxe typedef struct cpu_acpi_obj_attr {
520e751525SEric Saxe 	char *name;
530e751525SEric Saxe } cpu_acpi_obj_attr_t;
540e751525SEric Saxe 
550e751525SEric Saxe /*
560e751525SEric Saxe  * List of object attributes.
570e751525SEric Saxe  * NOTE: Please keep the ordering of the list as same as cpu_acpi_obj_t.
580e751525SEric Saxe  */
590e751525SEric Saxe static cpu_acpi_obj_attr_t cpu_acpi_obj_attrs[] = {
600e751525SEric Saxe 	{"_PDC"},
610e751525SEric Saxe 	{"_PCT"},
620e751525SEric Saxe 	{"_PSS"},
630e751525SEric Saxe 	{"_PSD"},
640e751525SEric Saxe 	{"_PPC"},
650e751525SEric Saxe 	{"_PTC"},
660e751525SEric Saxe 	{"_TSS"},
670e751525SEric Saxe 	{"_TSD"},
680e751525SEric Saxe 	{"_TPC"},
6900f97612SMark Haywood 	{"_CST"},
700e751525SEric Saxe 	{"_CSD"}
710e751525SEric Saxe };
720e751525SEric Saxe 
730e751525SEric Saxe /*
740e751525SEric Saxe  * Cache the ACPI CPU control data objects.
750e751525SEric Saxe  */
760e751525SEric Saxe static int
770e751525SEric Saxe cpu_acpi_cache_ctrl_regs(cpu_acpi_handle_t handle, cpu_acpi_obj_t objtype,
780e751525SEric Saxe     cpu_acpi_ctrl_regs_t *regs)
790e751525SEric Saxe {
8000f97612SMark Haywood 	ACPI_STATUS astatus;
810e751525SEric Saxe 	ACPI_BUFFER abuf;
820e751525SEric Saxe 	ACPI_OBJECT *obj;
830e751525SEric Saxe 	AML_RESOURCE_GENERIC_REGISTER *greg;
840e751525SEric Saxe 	int ret = -1;
850e751525SEric Saxe 	int i;
860e751525SEric Saxe 
870e751525SEric Saxe 	/*
880e751525SEric Saxe 	 * Fetch the control registers (if present) for the CPU node.
890e751525SEric Saxe 	 * Since they are optional, non-existence is not a failure
900e751525SEric Saxe 	 * (we just consider it a fixed hardware case).
910e751525SEric Saxe 	 */
920e751525SEric Saxe 	abuf.Length = ACPI_ALLOCATE_BUFFER;
930e751525SEric Saxe 	abuf.Pointer = NULL;
9400f97612SMark Haywood 	astatus = AcpiEvaluateObjectTyped(handle->cs_handle,
9500f97612SMark Haywood 	    cpu_acpi_obj_attrs[objtype].name, NULL, &abuf, ACPI_TYPE_PACKAGE);
9600f97612SMark Haywood 	if (ACPI_FAILURE(astatus)) {
9700f97612SMark Haywood 		if (astatus == AE_NOT_FOUND) {
9800f97612SMark Haywood 			DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
9900f97612SMark Haywood 			    int, objtype, int, astatus);
1000e751525SEric Saxe 			regs[0].cr_addrspace_id = ACPI_ADR_SPACE_FIXED_HARDWARE;
1010e751525SEric Saxe 			regs[1].cr_addrspace_id = ACPI_ADR_SPACE_FIXED_HARDWARE;
1020e751525SEric Saxe 			return (1);
1030e751525SEric Saxe 		}
10400f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating %s package "
10500f97612SMark Haywood 		    "for CPU %d.", astatus, cpu_acpi_obj_attrs[objtype].name,
10600f97612SMark Haywood 		    handle->cs_id);
10700f97612SMark Haywood 		goto out;
10800f97612SMark Haywood 	}
1090e751525SEric Saxe 
1100e751525SEric Saxe 	obj = abuf.Pointer;
1110e751525SEric Saxe 	if (obj->Package.Count != 2) {
11200f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: %s package bad count %d for "
11300f97612SMark Haywood 		    "CPU %d.", cpu_acpi_obj_attrs[objtype].name,
11400f97612SMark Haywood 		    obj->Package.Count, handle->cs_id);
1150e751525SEric Saxe 		goto out;
1160e751525SEric Saxe 	}
1170e751525SEric Saxe 
1180e751525SEric Saxe 	/*
1190e751525SEric Saxe 	 * Does the package look coherent?
1200e751525SEric Saxe 	 */
1210e751525SEric Saxe 	for (i = 0; i < obj->Package.Count; i++) {
1220e751525SEric Saxe 		if (obj->Package.Elements[i].Type != ACPI_TYPE_BUFFER) {
12300f97612SMark Haywood 			cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in "
12400f97612SMark Haywood 			    "%s package for CPU %d.",
12500f97612SMark Haywood 			    cpu_acpi_obj_attrs[objtype].name,
12600f97612SMark Haywood 			    handle->cs_id);
1270e751525SEric Saxe 			goto out;
1280e751525SEric Saxe 		}
1290e751525SEric Saxe 
1300e751525SEric Saxe 		greg = (AML_RESOURCE_GENERIC_REGISTER *)
1310e751525SEric Saxe 		    obj->Package.Elements[i].Buffer.Pointer;
1320e751525SEric Saxe 		if (greg->DescriptorType !=
1330e751525SEric Saxe 		    ACPI_RESOURCE_NAME_GENERIC_REGISTER) {
13400f97612SMark Haywood 			cmn_err(CE_NOTE, "!cpu_acpi: %s package has format "
13500f97612SMark Haywood 			    "error for CPU %d.",
13600f97612SMark Haywood 			    cpu_acpi_obj_attrs[objtype].name,
13700f97612SMark Haywood 			    handle->cs_id);
1380e751525SEric Saxe 			goto out;
1390e751525SEric Saxe 		}
1400e751525SEric Saxe 		if (greg->ResourceLength !=
1410e751525SEric Saxe 		    ACPI_AML_SIZE_LARGE(AML_RESOURCE_GENERIC_REGISTER)) {
14200f97612SMark Haywood 			cmn_err(CE_NOTE, "!cpu_acpi: %s package not right "
14300f97612SMark Haywood 			    "size for CPU %d.",
14400f97612SMark Haywood 			    cpu_acpi_obj_attrs[objtype].name,
14500f97612SMark Haywood 			    handle->cs_id);
1460e751525SEric Saxe 			goto out;
1470e751525SEric Saxe 		}
1480e751525SEric Saxe 		if (greg->AddressSpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE &&
1490e751525SEric Saxe 		    greg->AddressSpaceId != ACPI_ADR_SPACE_SYSTEM_IO) {
15000f97612SMark Haywood 			cmn_err(CE_NOTE, "!cpu_apci: %s contains unsupported "
15100f97612SMark Haywood 			    "address space type %x for CPU %d.",
1520e751525SEric Saxe 			    cpu_acpi_obj_attrs[objtype].name,
15300f97612SMark Haywood 			    greg->AddressSpaceId,
15400f97612SMark Haywood 			    handle->cs_id);
1550e751525SEric Saxe 			goto out;
1560e751525SEric Saxe 		}
1570e751525SEric Saxe 	}
1580e751525SEric Saxe 
1590e751525SEric Saxe 	/*
1600e751525SEric Saxe 	 * Looks good!
1610e751525SEric Saxe 	 */
1620e751525SEric Saxe 	for (i = 0; i < obj->Package.Count; i++) {
1630e751525SEric Saxe 		greg = (AML_RESOURCE_GENERIC_REGISTER *)
1640e751525SEric Saxe 		    obj->Package.Elements[i].Buffer.Pointer;
1650e751525SEric Saxe 		regs[i].cr_addrspace_id = greg->AddressSpaceId;
1660e751525SEric Saxe 		regs[i].cr_width = greg->BitWidth;
1670e751525SEric Saxe 		regs[i].cr_offset = greg->BitOffset;
1680e751525SEric Saxe 		regs[i].cr_asize = greg->AccessSize;
1690e751525SEric Saxe 		regs[i].cr_address = greg->Address;
1700e751525SEric Saxe 	}
1710e751525SEric Saxe 	ret = 0;
1720e751525SEric Saxe out:
17300f97612SMark Haywood 	if (abuf.Pointer != NULL)
1740e751525SEric Saxe 		AcpiOsFree(abuf.Pointer);
1750e751525SEric Saxe 	return (ret);
1760e751525SEric Saxe }
1770e751525SEric Saxe 
1780e751525SEric Saxe /*
1790e751525SEric Saxe  * Cache the ACPI _PCT data. The _PCT data defines the interface to use
1800e751525SEric Saxe  * when making power level transitions (i.e., system IO ports, fixed
1810e751525SEric Saxe  * hardware port, etc).
1820e751525SEric Saxe  */
1830e751525SEric Saxe static int
1840e751525SEric Saxe cpu_acpi_cache_pct(cpu_acpi_handle_t handle)
1850e751525SEric Saxe {
1860e751525SEric Saxe 	cpu_acpi_pct_t *pct;
1870e751525SEric Saxe 	int ret;
1880e751525SEric Saxe 
1890e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PCT_CACHED);
1900e751525SEric Saxe 	pct = &CPU_ACPI_PCT(handle)[0];
1910e751525SEric Saxe 	if ((ret = cpu_acpi_cache_ctrl_regs(handle, PCT_OBJ, pct)) == 0)
1920e751525SEric Saxe 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PCT_CACHED);
1930e751525SEric Saxe 	return (ret);
1940e751525SEric Saxe }
1950e751525SEric Saxe 
1960e751525SEric Saxe /*
1970e751525SEric Saxe  * Cache the ACPI _PTC data. The _PTC data defines the interface to use
1980e751525SEric Saxe  * when making T-state transitions (i.e., system IO ports, fixed
1990e751525SEric Saxe  * hardware port, etc).
2000e751525SEric Saxe  */
2010e751525SEric Saxe static int
2020e751525SEric Saxe cpu_acpi_cache_ptc(cpu_acpi_handle_t handle)
2030e751525SEric Saxe {
2040e751525SEric Saxe 	cpu_acpi_ptc_t *ptc;
2050e751525SEric Saxe 	int ret;
2060e751525SEric Saxe 
2070e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PTC_CACHED);
2080e751525SEric Saxe 	ptc = &CPU_ACPI_PTC(handle)[0];
2090e751525SEric Saxe 	if ((ret = cpu_acpi_cache_ctrl_regs(handle, PTC_OBJ, ptc)) == 0)
2100e751525SEric Saxe 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PTC_CACHED);
2110e751525SEric Saxe 	return (ret);
2120e751525SEric Saxe }
2130e751525SEric Saxe 
2140e751525SEric Saxe /*
2150e751525SEric Saxe  * Cache the ACPI CPU state dependency data objects.
2160e751525SEric Saxe  */
2170e751525SEric Saxe static int
2180e751525SEric Saxe cpu_acpi_cache_state_dependencies(cpu_acpi_handle_t handle,
2190e751525SEric Saxe     cpu_acpi_obj_t objtype, cpu_acpi_state_dependency_t *sd)
2200e751525SEric Saxe {
22100f97612SMark Haywood 	ACPI_STATUS astatus;
2220e751525SEric Saxe 	ACPI_BUFFER abuf;
2230e751525SEric Saxe 	ACPI_OBJECT *pkg, *elements;
2240e751525SEric Saxe 	int number;
2250e751525SEric Saxe 	int ret = -1;
2260e751525SEric Saxe 
2270e751525SEric Saxe 	if (objtype == CSD_OBJ) {
2280e751525SEric Saxe 		number = 6;
2290e751525SEric Saxe 	} else {
2300e751525SEric Saxe 		number = 5;
2310e751525SEric Saxe 	}
2320e751525SEric Saxe 	/*
2330e751525SEric Saxe 	 * Fetch the dependencies (if present) for the CPU node.
2340e751525SEric Saxe 	 * Since they are optional, non-existence is not a failure
2350e751525SEric Saxe 	 * (it's up to the caller to determine how to handle non-existence).
2360e751525SEric Saxe 	 */
2370e751525SEric Saxe 	abuf.Length = ACPI_ALLOCATE_BUFFER;
2380e751525SEric Saxe 	abuf.Pointer = NULL;
23900f97612SMark Haywood 	astatus = AcpiEvaluateObjectTyped(handle->cs_handle,
24000f97612SMark Haywood 	    cpu_acpi_obj_attrs[objtype].name, NULL, &abuf, ACPI_TYPE_PACKAGE);
24100f97612SMark Haywood 	if (ACPI_FAILURE(astatus)) {
24200f97612SMark Haywood 		if (astatus == AE_NOT_FOUND) {
24300f97612SMark Haywood 			DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
24400f97612SMark Haywood 			    int, objtype, int, astatus);
2450e751525SEric Saxe 			return (1);
2460e751525SEric Saxe 		}
24700f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating %s package "
24800f97612SMark Haywood 		    "for CPU %d.", astatus, cpu_acpi_obj_attrs[objtype].name,
24900f97612SMark Haywood 		    handle->cs_id);
25000f97612SMark Haywood 		goto out;
25100f97612SMark Haywood 	}
2520e751525SEric Saxe 
2530e751525SEric Saxe 	pkg = abuf.Pointer;
2540e751525SEric Saxe 
2550e751525SEric Saxe 	if (((objtype != CSD_OBJ) && (pkg->Package.Count != 1)) ||
2560e751525SEric Saxe 	    ((objtype == CSD_OBJ) && (pkg->Package.Count != 1) &&
2570e751525SEric Saxe 	    (pkg->Package.Count != 2))) {
25800f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: %s unsupported package count %d "
25900f97612SMark Haywood 		    "for CPU %d.", cpu_acpi_obj_attrs[objtype].name,
26000f97612SMark Haywood 		    pkg->Package.Count, handle->cs_id);
2610e751525SEric Saxe 		goto out;
2620e751525SEric Saxe 	}
2630e751525SEric Saxe 
2640e751525SEric Saxe 	/*
2650e751525SEric Saxe 	 * For C-state domain, we assume C2 and C3 have the same
2660e751525SEric Saxe 	 * domain information
2670e751525SEric Saxe 	 */
2680e751525SEric Saxe 	if (pkg->Package.Elements[0].Type != ACPI_TYPE_PACKAGE ||
2690e751525SEric Saxe 	    pkg->Package.Elements[0].Package.Count != number) {
27000f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in %s package "
27100f97612SMark Haywood 		    "for CPU %d.", cpu_acpi_obj_attrs[objtype].name,
27200f97612SMark Haywood 		    handle->cs_id);
2730e751525SEric Saxe 		goto out;
2740e751525SEric Saxe 	}
2750e751525SEric Saxe 	elements = pkg->Package.Elements[0].Package.Elements;
2760e751525SEric Saxe 	if (elements[0].Integer.Value != number ||
2770e751525SEric Saxe 	    elements[1].Integer.Value != 0) {
27800f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: Unexpected %s revision for "
27900f97612SMark Haywood 		    "CPU %d.", cpu_acpi_obj_attrs[objtype].name,
28000f97612SMark Haywood 		    handle->cs_id);
2810e751525SEric Saxe 		goto out;
2820e751525SEric Saxe 	}
2830e751525SEric Saxe 
2840e751525SEric Saxe 	sd->sd_entries = elements[0].Integer.Value;
2850e751525SEric Saxe 	sd->sd_revision = elements[1].Integer.Value;
2860e751525SEric Saxe 	sd->sd_domain = elements[2].Integer.Value;
2870e751525SEric Saxe 	sd->sd_type = elements[3].Integer.Value;
2880e751525SEric Saxe 	sd->sd_num = elements[4].Integer.Value;
2890e751525SEric Saxe 	if (objtype == CSD_OBJ) {
2900e751525SEric Saxe 		sd->sd_index = elements[5].Integer.Value;
2910e751525SEric Saxe 	}
2920e751525SEric Saxe 
2930e751525SEric Saxe 	ret = 0;
2940e751525SEric Saxe out:
29500f97612SMark Haywood 	if (abuf.Pointer != NULL)
2960e751525SEric Saxe 		AcpiOsFree(abuf.Pointer);
2970e751525SEric Saxe 	return (ret);
2980e751525SEric Saxe }
2990e751525SEric Saxe 
3000e751525SEric Saxe /*
3010e751525SEric Saxe  * Cache the ACPI _PSD data. The _PSD data defines P-state CPU dependencies
3020e751525SEric Saxe  * (think CPU domains).
3030e751525SEric Saxe  */
3040e751525SEric Saxe static int
3050e751525SEric Saxe cpu_acpi_cache_psd(cpu_acpi_handle_t handle)
3060e751525SEric Saxe {
3070e751525SEric Saxe 	cpu_acpi_psd_t *psd;
3080e751525SEric Saxe 	int ret;
3090e751525SEric Saxe 
3100e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PSD_CACHED);
3110e751525SEric Saxe 	psd = &CPU_ACPI_PSD(handle);
3120e751525SEric Saxe 	ret = cpu_acpi_cache_state_dependencies(handle, PSD_OBJ, psd);
3130e751525SEric Saxe 	if (ret == 0)
3140e751525SEric Saxe 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PSD_CACHED);
3150e751525SEric Saxe 	return (ret);
3160e751525SEric Saxe 
3170e751525SEric Saxe }
3180e751525SEric Saxe 
3190e751525SEric Saxe /*
3200e751525SEric Saxe  * Cache the ACPI _TSD data. The _TSD data defines T-state CPU dependencies
3210e751525SEric Saxe  * (think CPU domains).
3220e751525SEric Saxe  */
3230e751525SEric Saxe static int
3240e751525SEric Saxe cpu_acpi_cache_tsd(cpu_acpi_handle_t handle)
3250e751525SEric Saxe {
3260e751525SEric Saxe 	cpu_acpi_tsd_t *tsd;
3270e751525SEric Saxe 	int ret;
3280e751525SEric Saxe 
3290e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_TSD_CACHED);
3300e751525SEric Saxe 	tsd = &CPU_ACPI_TSD(handle);
3310e751525SEric Saxe 	ret = cpu_acpi_cache_state_dependencies(handle, TSD_OBJ, tsd);
3320e751525SEric Saxe 	if (ret == 0)
3330e751525SEric Saxe 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_TSD_CACHED);
3340e751525SEric Saxe 	return (ret);
3350e751525SEric Saxe 
3360e751525SEric Saxe }
3370e751525SEric Saxe 
3380e751525SEric Saxe /*
3390e751525SEric Saxe  * Cache the ACPI _CSD data. The _CSD data defines C-state CPU dependencies
3400e751525SEric Saxe  * (think CPU domains).
3410e751525SEric Saxe  */
3420e751525SEric Saxe static int
3430e751525SEric Saxe cpu_acpi_cache_csd(cpu_acpi_handle_t handle)
3440e751525SEric Saxe {
3450e751525SEric Saxe 	cpu_acpi_csd_t *csd;
3460e751525SEric Saxe 	int ret;
3470e751525SEric Saxe 
3480e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_CSD_CACHED);
3490e751525SEric Saxe 	csd = &CPU_ACPI_CSD(handle);
3500e751525SEric Saxe 	ret = cpu_acpi_cache_state_dependencies(handle, CSD_OBJ, csd);
3510e751525SEric Saxe 	if (ret == 0)
3520e751525SEric Saxe 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_CSD_CACHED);
3530e751525SEric Saxe 	return (ret);
3540e751525SEric Saxe 
3550e751525SEric Saxe }
3560e751525SEric Saxe 
3570e751525SEric Saxe static void
3580e751525SEric Saxe cpu_acpi_cache_pstate(cpu_acpi_handle_t handle, ACPI_OBJECT *obj, int cnt)
3590e751525SEric Saxe {
3600e751525SEric Saxe 	cpu_acpi_pstate_t *pstate;
3610e751525SEric Saxe 	ACPI_OBJECT *q, *l;
3620e751525SEric Saxe 	int i, j;
3630e751525SEric Saxe 
3640e751525SEric Saxe 	CPU_ACPI_PSTATES_COUNT(handle) = cnt;
3650e751525SEric Saxe 	CPU_ACPI_PSTATES(handle) = kmem_zalloc(CPU_ACPI_PSTATES_SIZE(cnt),
3660e751525SEric Saxe 	    KM_SLEEP);
3670e751525SEric Saxe 	pstate = (cpu_acpi_pstate_t *)CPU_ACPI_PSTATES(handle);
3680e751525SEric Saxe 	for (i = 0, l = NULL; i < obj->Package.Count && cnt > 0; i++, l = q) {
3690e751525SEric Saxe 		uint32_t *up;
3700e751525SEric Saxe 
3710e751525SEric Saxe 		q = obj->Package.Elements[i].Package.Elements;
3720e751525SEric Saxe 
3730e751525SEric Saxe 		/*
3740e751525SEric Saxe 		 * Skip duplicate entries.
3750e751525SEric Saxe 		 */
3760e751525SEric Saxe 		if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
3770e751525SEric Saxe 			continue;
3780e751525SEric Saxe 
3790e751525SEric Saxe 		up = (uint32_t *)pstate;
3800e751525SEric Saxe 		for (j = 0; j < CPU_ACPI_PSS_CNT; j++)
3810e751525SEric Saxe 			up[j] = q[j].Integer.Value;
3820e751525SEric Saxe 		pstate++;
3830e751525SEric Saxe 		cnt--;
3840e751525SEric Saxe 	}
3850e751525SEric Saxe }
3860e751525SEric Saxe 
3870e751525SEric Saxe static void
3880e751525SEric Saxe cpu_acpi_cache_tstate(cpu_acpi_handle_t handle, ACPI_OBJECT *obj, int cnt)
3890e751525SEric Saxe {
3900e751525SEric Saxe 	cpu_acpi_tstate_t *tstate;
3910e751525SEric Saxe 	ACPI_OBJECT *q, *l;
3920e751525SEric Saxe 	int i, j;
3930e751525SEric Saxe 
3940e751525SEric Saxe 	CPU_ACPI_TSTATES_COUNT(handle) = cnt;
3950e751525SEric Saxe 	CPU_ACPI_TSTATES(handle) = kmem_zalloc(CPU_ACPI_TSTATES_SIZE(cnt),
3960e751525SEric Saxe 	    KM_SLEEP);
3970e751525SEric Saxe 	tstate = (cpu_acpi_tstate_t *)CPU_ACPI_TSTATES(handle);
3980e751525SEric Saxe 	for (i = 0, l = NULL; i < obj->Package.Count && cnt > 0; i++, l = q) {
3990e751525SEric Saxe 		uint32_t *up;
4000e751525SEric Saxe 
4010e751525SEric Saxe 		q = obj->Package.Elements[i].Package.Elements;
4020e751525SEric Saxe 
4030e751525SEric Saxe 		/*
4040e751525SEric Saxe 		 * Skip duplicate entries.
4050e751525SEric Saxe 		 */
4060e751525SEric Saxe 		if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
4070e751525SEric Saxe 			continue;
4080e751525SEric Saxe 
4090e751525SEric Saxe 		up = (uint32_t *)tstate;
4100e751525SEric Saxe 		for (j = 0; j < CPU_ACPI_TSS_CNT; j++)
4110e751525SEric Saxe 			up[j] = q[j].Integer.Value;
4120e751525SEric Saxe 		tstate++;
4130e751525SEric Saxe 		cnt--;
4140e751525SEric Saxe 	}
4150e751525SEric Saxe }
4160e751525SEric Saxe 
4170e751525SEric Saxe /*
4180e751525SEric Saxe  * Cache the _PSS or _TSS data.
4190e751525SEric Saxe  */
4200e751525SEric Saxe static int
4210e751525SEric Saxe cpu_acpi_cache_supported_states(cpu_acpi_handle_t handle,
4220e751525SEric Saxe     cpu_acpi_obj_t objtype, int fcnt)
4230e751525SEric Saxe {
42400f97612SMark Haywood 	ACPI_STATUS astatus;
4250e751525SEric Saxe 	ACPI_BUFFER abuf;
4260e751525SEric Saxe 	ACPI_OBJECT *obj, *q, *l;
4270e751525SEric Saxe 	boolean_t eot = B_FALSE;
4280e751525SEric Saxe 	int ret = -1;
4290e751525SEric Saxe 	int cnt;
4300e751525SEric Saxe 	int i, j;
4310e751525SEric Saxe 
4320e751525SEric Saxe 	/*
43300f97612SMark Haywood 	 * Fetch the state data (if present) for the CPU node.
4340e751525SEric Saxe 	 */
4350e751525SEric Saxe 	abuf.Length = ACPI_ALLOCATE_BUFFER;
4360e751525SEric Saxe 	abuf.Pointer = NULL;
43700f97612SMark Haywood 	astatus = AcpiEvaluateObjectTyped(handle->cs_handle,
4380e751525SEric Saxe 	    cpu_acpi_obj_attrs[objtype].name, NULL, &abuf,
43900f97612SMark Haywood 	    ACPI_TYPE_PACKAGE);
44000f97612SMark Haywood 	if (ACPI_FAILURE(astatus)) {
44100f97612SMark Haywood 		if (astatus == AE_NOT_FOUND) {
44200f97612SMark Haywood 			DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
44300f97612SMark Haywood 			    int, objtype, int, astatus);
4440e751525SEric Saxe 			return (1);
4450e751525SEric Saxe 		}
44600f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating %s package "
44700f97612SMark Haywood 		    "for CPU %d.", astatus, cpu_acpi_obj_attrs[objtype].name,
44800f97612SMark Haywood 		    handle->cs_id);
44900f97612SMark Haywood 		goto out;
45000f97612SMark Haywood 	}
4510e751525SEric Saxe 	obj = abuf.Pointer;
4520e751525SEric Saxe 	if (obj->Package.Count < 2) {
45300f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: %s package bad count %d for "
45400f97612SMark Haywood 		    "CPU %d.", cpu_acpi_obj_attrs[objtype].name,
45500f97612SMark Haywood 		    obj->Package.Count, handle->cs_id);
4560e751525SEric Saxe 		goto out;
4570e751525SEric Saxe 	}
4580e751525SEric Saxe 
4590e751525SEric Saxe 	/*
4600e751525SEric Saxe 	 * Does the package look coherent?
4610e751525SEric Saxe 	 */
4620e751525SEric Saxe 	cnt = 0;
4630e751525SEric Saxe 	for (i = 0, l = NULL; i < obj->Package.Count; i++, l = q) {
4640e751525SEric Saxe 		if (obj->Package.Elements[i].Type != ACPI_TYPE_PACKAGE ||
4650e751525SEric Saxe 		    obj->Package.Elements[i].Package.Count != fcnt) {
46600f97612SMark Haywood 			cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in "
46700f97612SMark Haywood 			    "%s package for CPU %d.",
46800f97612SMark Haywood 			    cpu_acpi_obj_attrs[objtype].name,
46900f97612SMark Haywood 			    handle->cs_id);
4700e751525SEric Saxe 			goto out;
4710e751525SEric Saxe 		}
4720e751525SEric Saxe 
4730e751525SEric Saxe 		q = obj->Package.Elements[i].Package.Elements;
4740e751525SEric Saxe 		for (j = 0; j < fcnt; j++) {
4750e751525SEric Saxe 			if (q[j].Type != ACPI_TYPE_INTEGER) {
47600f97612SMark Haywood 				cmn_err(CE_NOTE, "!cpu_acpi: %s element "
47700f97612SMark Haywood 				    "invalid (type) for CPU %d.",
47800f97612SMark Haywood 				    cpu_acpi_obj_attrs[objtype].name,
47900f97612SMark Haywood 				    handle->cs_id);
4800e751525SEric Saxe 				goto out;
4810e751525SEric Saxe 			}
4820e751525SEric Saxe 		}
4830e751525SEric Saxe 
4840e751525SEric Saxe 		/*
4850e751525SEric Saxe 		 * Ignore duplicate entries.
4860e751525SEric Saxe 		 */
4870e751525SEric Saxe 		if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
4880e751525SEric Saxe 			continue;
4890e751525SEric Saxe 
4900e751525SEric Saxe 		/*
4910e751525SEric Saxe 		 * Some supported state tables are larger than required
4920e751525SEric Saxe 		 * and unused elements are filled with patterns
4930e751525SEric Saxe 		 * of 0xff.  Simply check here for frequency = 0xffff
4940e751525SEric Saxe 		 * and stop counting if found.
4950e751525SEric Saxe 		 */
4960e751525SEric Saxe 		if (q[0].Integer.Value == 0xffff) {
4970e751525SEric Saxe 			eot = B_TRUE;
4980e751525SEric Saxe 			continue;
4990e751525SEric Saxe 		}
5000e751525SEric Saxe 
5010e751525SEric Saxe 		/*
5020e751525SEric Saxe 		 * We should never find a valid entry after we've hit
5030e751525SEric Saxe 		 * an the end-of-table entry.
5040e751525SEric Saxe 		 */
5050e751525SEric Saxe 		if (eot) {
50600f97612SMark Haywood 			cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in %s "
50700f97612SMark Haywood 			    "package after eot for CPU %d.",
50800f97612SMark Haywood 			    cpu_acpi_obj_attrs[objtype].name,
50900f97612SMark Haywood 			    handle->cs_id);
5100e751525SEric Saxe 			goto out;
5110e751525SEric Saxe 		}
5120e751525SEric Saxe 
5130e751525SEric Saxe 		/*
5140e751525SEric Saxe 		 * states must be defined in order from highest to lowest.
5150e751525SEric Saxe 		 */
5160e751525SEric Saxe 		if (l != NULL && l[0].Integer.Value < q[0].Integer.Value) {
51700f97612SMark Haywood 			cmn_err(CE_NOTE, "!cpu_acpi: %s package state "
51800f97612SMark Haywood 			    "definitions out of order for CPU %d.",
51900f97612SMark Haywood 			    cpu_acpi_obj_attrs[objtype].name,
52000f97612SMark Haywood 			    handle->cs_id);
5210e751525SEric Saxe 			goto out;
5220e751525SEric Saxe 		}
5230e751525SEric Saxe 
5240e751525SEric Saxe 		/*
5250e751525SEric Saxe 		 * This entry passes.
5260e751525SEric Saxe 		 */
5270e751525SEric Saxe 		cnt++;
5280e751525SEric Saxe 	}
5290e751525SEric Saxe 	if (cnt == 0)
5300e751525SEric Saxe 		goto out;
5310e751525SEric Saxe 
5320e751525SEric Saxe 	/*
5330e751525SEric Saxe 	 * Yes, fill in the structure.
5340e751525SEric Saxe 	 */
5350e751525SEric Saxe 	ASSERT(objtype == PSS_OBJ || objtype == TSS_OBJ);
5360e751525SEric Saxe 	(objtype == PSS_OBJ) ? cpu_acpi_cache_pstate(handle, obj, cnt) :
5370e751525SEric Saxe 	    cpu_acpi_cache_tstate(handle, obj, cnt);
5380e751525SEric Saxe 
5390e751525SEric Saxe 	ret = 0;
5400e751525SEric Saxe out:
54100f97612SMark Haywood 	if (abuf.Pointer != NULL)
5420e751525SEric Saxe 		AcpiOsFree(abuf.Pointer);
5430e751525SEric Saxe 	return (ret);
5440e751525SEric Saxe }
5450e751525SEric Saxe 
5460e751525SEric Saxe /*
5470e751525SEric Saxe  * Cache the _PSS data. The _PSS data defines the different power levels
5480e751525SEric Saxe  * supported by the CPU and the attributes associated with each power level
5490e751525SEric Saxe  * (i.e., frequency, voltage, etc.). The power levels are number from
5500e751525SEric Saxe  * highest to lowest. That is, the highest power level is _PSS entry 0
5510e751525SEric Saxe  * and the lowest power level is the last _PSS entry.
5520e751525SEric Saxe  */
5530e751525SEric Saxe static int
5540e751525SEric Saxe cpu_acpi_cache_pstates(cpu_acpi_handle_t handle)
5550e751525SEric Saxe {
5560e751525SEric Saxe 	int ret;
5570e751525SEric Saxe 
5580e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PSS_CACHED);
5590e751525SEric Saxe 	ret = cpu_acpi_cache_supported_states(handle, PSS_OBJ,
5600e751525SEric Saxe 	    CPU_ACPI_PSS_CNT);
5610e751525SEric Saxe 	if (ret == 0)
5620e751525SEric Saxe 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PSS_CACHED);
5630e751525SEric Saxe 	return (ret);
5640e751525SEric Saxe }
5650e751525SEric Saxe 
5660e751525SEric Saxe /*
5670e751525SEric Saxe  * Cache the _TSS data. The _TSS data defines the different freq throttle
5680e751525SEric Saxe  * levels supported by the CPU and the attributes associated with each
5690e751525SEric Saxe  * throttle level (i.e., frequency throttle percentage, voltage, etc.).
5700e751525SEric Saxe  * The throttle levels are number from highest to lowest.
5710e751525SEric Saxe  */
5720e751525SEric Saxe static int
5730e751525SEric Saxe cpu_acpi_cache_tstates(cpu_acpi_handle_t handle)
5740e751525SEric Saxe {
5750e751525SEric Saxe 	int ret;
5760e751525SEric Saxe 
5770e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_TSS_CACHED);
5780e751525SEric Saxe 	ret = cpu_acpi_cache_supported_states(handle, TSS_OBJ,
5790e751525SEric Saxe 	    CPU_ACPI_TSS_CNT);
5800e751525SEric Saxe 	if (ret == 0)
5810e751525SEric Saxe 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_TSS_CACHED);
5820e751525SEric Saxe 	return (ret);
5830e751525SEric Saxe }
5840e751525SEric Saxe 
5850e751525SEric Saxe /*
5860e751525SEric Saxe  * Cache the ACPI CPU present capabilities data objects.
5870e751525SEric Saxe  */
5880e751525SEric Saxe static int
5890e751525SEric Saxe cpu_acpi_cache_present_capabilities(cpu_acpi_handle_t handle,
5900e751525SEric Saxe     cpu_acpi_obj_t objtype, cpu_acpi_present_capabilities_t *pc)
5910e751525SEric Saxe 
5920e751525SEric Saxe {
59300f97612SMark Haywood 	ACPI_STATUS astatus;
5940e751525SEric Saxe 	ACPI_BUFFER abuf;
5950e751525SEric Saxe 	ACPI_OBJECT *obj;
59600f97612SMark Haywood 	int ret = -1;
5970e751525SEric Saxe 
5980e751525SEric Saxe 	/*
5990e751525SEric Saxe 	 * Fetch the present capabilites object (if present) for the CPU node.
6000e751525SEric Saxe 	 */
6010e751525SEric Saxe 	abuf.Length = ACPI_ALLOCATE_BUFFER;
6020e751525SEric Saxe 	abuf.Pointer = NULL;
60300f97612SMark Haywood 	astatus = AcpiEvaluateObject(handle->cs_handle,
60400f97612SMark Haywood 	    cpu_acpi_obj_attrs[objtype].name, NULL, &abuf);
60500f97612SMark Haywood 	if (ACPI_FAILURE(astatus) && astatus != AE_NOT_FOUND) {
60600f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating %s "
60700f97612SMark Haywood 		    "package for CPU %d.", astatus,
60800f97612SMark Haywood 		    cpu_acpi_obj_attrs[objtype].name, handle->cs_id);
60900f97612SMark Haywood 		goto out;
61000f97612SMark Haywood 	}
61100f97612SMark Haywood 	if (astatus == AE_NOT_FOUND || abuf.Length == 0) {
6120e751525SEric Saxe 		*pc = 0;
6130e751525SEric Saxe 		return (1);
6140e751525SEric Saxe 	}
6150e751525SEric Saxe 
6160e751525SEric Saxe 	obj = (ACPI_OBJECT *)abuf.Pointer;
6170e751525SEric Saxe 	*pc = obj->Integer.Value;
61800f97612SMark Haywood 
61900f97612SMark Haywood 	ret = 0;
62000f97612SMark Haywood out:
62100f97612SMark Haywood 	if (abuf.Pointer != NULL)
6220e751525SEric Saxe 		AcpiOsFree(abuf.Pointer);
62300f97612SMark Haywood 	return (ret);
6240e751525SEric Saxe }
6250e751525SEric Saxe 
6260e751525SEric Saxe /*
6270e751525SEric Saxe  * Cache the _PPC data. The _PPC simply contains an integer value which
6280e751525SEric Saxe  * represents the highest power level that a CPU should transition to.
6290e751525SEric Saxe  * That is, it's an index into the array of _PSS entries and will be
6300e751525SEric Saxe  * greater than or equal to zero.
6310e751525SEric Saxe  */
6320e751525SEric Saxe void
6330e751525SEric Saxe cpu_acpi_cache_ppc(cpu_acpi_handle_t handle)
6340e751525SEric Saxe {
6350e751525SEric Saxe 	cpu_acpi_ppc_t *ppc;
6360e751525SEric Saxe 	int ret;
6370e751525SEric Saxe 
6380e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PPC_CACHED);
6390e751525SEric Saxe 	ppc = &CPU_ACPI_PPC(handle);
6400e751525SEric Saxe 	ret = cpu_acpi_cache_present_capabilities(handle, PPC_OBJ, ppc);
6410e751525SEric Saxe 	if (ret == 0)
6420e751525SEric Saxe 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PPC_CACHED);
6430e751525SEric Saxe }
6440e751525SEric Saxe 
6450e751525SEric Saxe /*
6460e751525SEric Saxe  * Cache the _TPC data. The _TPC simply contains an integer value which
6470e751525SEric Saxe  * represents the throttle level that a CPU should transition to.
6480e751525SEric Saxe  * That is, it's an index into the array of _TSS entries and will be
6490e751525SEric Saxe  * greater than or equal to zero.
6500e751525SEric Saxe  */
6510e751525SEric Saxe void
6520e751525SEric Saxe cpu_acpi_cache_tpc(cpu_acpi_handle_t handle)
6530e751525SEric Saxe {
6540e751525SEric Saxe 	cpu_acpi_tpc_t *tpc;
6550e751525SEric Saxe 	int ret;
6560e751525SEric Saxe 
6570e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_TPC_CACHED);
6580e751525SEric Saxe 	tpc = &CPU_ACPI_TPC(handle);
6590e751525SEric Saxe 	ret = cpu_acpi_cache_present_capabilities(handle, TPC_OBJ, tpc);
6600e751525SEric Saxe 	if (ret == 0)
6610e751525SEric Saxe 		CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_TPC_CACHED);
6620e751525SEric Saxe }
6630e751525SEric Saxe 
6640e751525SEric Saxe int
6650e751525SEric Saxe cpu_acpi_verify_cstate(cpu_acpi_cstate_t *cstate)
6660e751525SEric Saxe {
6670e751525SEric Saxe 	uint32_t addrspaceid = cstate->cs_addrspace_id;
6680e751525SEric Saxe 
6690e751525SEric Saxe 	if ((addrspaceid != ACPI_ADR_SPACE_FIXED_HARDWARE) &&
6700e751525SEric Saxe 	    (addrspaceid != ACPI_ADR_SPACE_SYSTEM_IO)) {
67100f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: _CST unsupported address space id"
6720e751525SEric Saxe 		    ":C%d, type: %d\n", cstate->cs_type, addrspaceid);
6730e751525SEric Saxe 		return (1);
6740e751525SEric Saxe 	}
6750e751525SEric Saxe 	return (0);
6760e751525SEric Saxe }
6770e751525SEric Saxe 
6780e751525SEric Saxe int
6790e751525SEric Saxe cpu_acpi_cache_cst(cpu_acpi_handle_t handle)
6800e751525SEric Saxe {
68100f97612SMark Haywood 	ACPI_STATUS astatus;
6820e751525SEric Saxe 	ACPI_BUFFER abuf;
6830e751525SEric Saxe 	ACPI_OBJECT *obj;
684*b3ffafc5Sjiang.liu@intel.com 	ACPI_INTEGER cnt, old_cnt;
6850e751525SEric Saxe 	cpu_acpi_cstate_t *cstate, *p;
686621e6c37SBill Holler 	size_t alloc_size;
6870e751525SEric Saxe 	int i, count;
68800f97612SMark Haywood 	int ret = 1;
6890e751525SEric Saxe 
6900e751525SEric Saxe 	CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_CST_CACHED);
6910e751525SEric Saxe 
6920e751525SEric Saxe 	abuf.Length = ACPI_ALLOCATE_BUFFER;
6930e751525SEric Saxe 	abuf.Pointer = NULL;
6940e751525SEric Saxe 
69500f97612SMark Haywood 	/*
69600f97612SMark Haywood 	 * Fetch the C-state data (if present) for the CPU node.
69700f97612SMark Haywood 	 */
69800f97612SMark Haywood 	astatus = AcpiEvaluateObjectTyped(handle->cs_handle, "_CST",
69900f97612SMark Haywood 	    NULL, &abuf, ACPI_TYPE_PACKAGE);
70000f97612SMark Haywood 	if (ACPI_FAILURE(astatus)) {
70100f97612SMark Haywood 		if (astatus == AE_NOT_FOUND) {
70200f97612SMark Haywood 			DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
70300f97612SMark Haywood 			    int, CST_OBJ, int, astatus);
70400f97612SMark Haywood 			return (1);
70500f97612SMark Haywood 		}
70600f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating _CST package "
70700f97612SMark Haywood 		    "for CPU %d.", astatus, handle->cs_id);
70800f97612SMark Haywood 		goto out;
70900f97612SMark Haywood 
7100e751525SEric Saxe 	}
7110e751525SEric Saxe 	obj = (ACPI_OBJECT *)abuf.Pointer;
7120e751525SEric Saxe 	if (obj->Package.Count < 2) {
71300f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: _CST unsupported package "
71400f97612SMark Haywood 		    "count %d for CPU %d.", obj->Package.Count, handle->cs_id);
71500f97612SMark Haywood 		goto out;
7160e751525SEric Saxe 	}
7170e751525SEric Saxe 
7180e751525SEric Saxe 	/*
7190e751525SEric Saxe 	 * Does the package look coherent?
7200e751525SEric Saxe 	 */
7210e751525SEric Saxe 	cnt = obj->Package.Elements[0].Integer.Value;
7220e751525SEric Saxe 	if (cnt < 1 || cnt != obj->Package.Count - 1) {
72300f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: _CST invalid element "
72400f97612SMark Haywood 		    "count %d != Package count %d for CPU %d",
72500f97612SMark Haywood 		    (int)cnt, (int)obj->Package.Count - 1, handle->cs_id);
72600f97612SMark Haywood 		goto out;
7270e751525SEric Saxe 	}
7280e751525SEric Saxe 
729*b3ffafc5Sjiang.liu@intel.com 	/*
730*b3ffafc5Sjiang.liu@intel.com 	 * Reuse the old buffer if the number of C states is the same.
731*b3ffafc5Sjiang.liu@intel.com 	 */
732*b3ffafc5Sjiang.liu@intel.com 	if (CPU_ACPI_CSTATES(handle) &&
733*b3ffafc5Sjiang.liu@intel.com 	    (old_cnt = CPU_ACPI_CSTATES_COUNT(handle)) != cnt) {
734*b3ffafc5Sjiang.liu@intel.com 		kmem_free(CPU_ACPI_CSTATES(handle),
735*b3ffafc5Sjiang.liu@intel.com 		    CPU_ACPI_CSTATES_SIZE(old_cnt));
736*b3ffafc5Sjiang.liu@intel.com 		CPU_ACPI_CSTATES(handle) = NULL;
737*b3ffafc5Sjiang.liu@intel.com 	}
738*b3ffafc5Sjiang.liu@intel.com 
7390e751525SEric Saxe 	CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)cnt;
740621e6c37SBill Holler 	alloc_size = CPU_ACPI_CSTATES_SIZE(cnt);
741a3114836SGerry Liu 	if (CPU_ACPI_CSTATES(handle) == NULL)
742621e6c37SBill Holler 		CPU_ACPI_CSTATES(handle) = kmem_zalloc(alloc_size, KM_SLEEP);
7430e751525SEric Saxe 	cstate = (cpu_acpi_cstate_t *)CPU_ACPI_CSTATES(handle);
7440e751525SEric Saxe 	p = cstate;
7450e751525SEric Saxe 
7460e751525SEric Saxe 	for (i = 1, count = 1; i <= cnt; i++) {
7470e751525SEric Saxe 		ACPI_OBJECT *pkg;
7480e751525SEric Saxe 		AML_RESOURCE_GENERIC_REGISTER *reg;
7490e751525SEric Saxe 		ACPI_OBJECT *element;
7500e751525SEric Saxe 
7510e751525SEric Saxe 		pkg = &(obj->Package.Elements[i]);
7520e751525SEric Saxe 		reg = (AML_RESOURCE_GENERIC_REGISTER *)
7530e751525SEric Saxe 		    pkg->Package.Elements[0].Buffer.Pointer;
7540e751525SEric Saxe 		cstate->cs_addrspace_id = reg->AddressSpaceId;
7550e751525SEric Saxe 		cstate->cs_address = reg->Address;
7560e751525SEric Saxe 		element = &(pkg->Package.Elements[1]);
7570e751525SEric Saxe 		cstate->cs_type = element->Integer.Value;
7580e751525SEric Saxe 		element = &(pkg->Package.Elements[2]);
7590e751525SEric Saxe 		cstate->cs_latency = element->Integer.Value;
7600e751525SEric Saxe 		element = &(pkg->Package.Elements[3]);
7610e751525SEric Saxe 		cstate->cs_power = element->Integer.Value;
7620e751525SEric Saxe 
7630e751525SEric Saxe 		if (cpu_acpi_verify_cstate(cstate)) {
7640e751525SEric Saxe 			/*
7650e751525SEric Saxe 			 * ignore this entry if it's not valid
7660e751525SEric Saxe 			 */
7670e751525SEric Saxe 			continue;
7680e751525SEric Saxe 		}
7690e751525SEric Saxe 		if (cstate == p) {
7700e751525SEric Saxe 			cstate++;
7710e751525SEric Saxe 		} else if (p->cs_type == cstate->cs_type) {
7720e751525SEric Saxe 			/*
7730e751525SEric Saxe 			 * if there are duplicate entries, we keep the
7740e751525SEric Saxe 			 * last one. This fixes:
7750e751525SEric Saxe 			 * 1) some buggy BIOS have total duplicate entries.
7760e751525SEric Saxe 			 * 2) ACPI Spec allows the same cstate entry with
7770e751525SEric Saxe 			 *    different power and latency, we use the one
7780e751525SEric Saxe 			 *    with more power saving.
7790e751525SEric Saxe 			 */
7800e751525SEric Saxe 			(void) memcpy(p, cstate, sizeof (cpu_acpi_cstate_t));
7810e751525SEric Saxe 		} else {
7820e751525SEric Saxe 			/*
7830e751525SEric Saxe 			 * we got a valid entry, cache it to the
7840e751525SEric Saxe 			 * cstate structure
7850e751525SEric Saxe 			 */
7860e751525SEric Saxe 			p = cstate++;
7870e751525SEric Saxe 			count++;
7880e751525SEric Saxe 		}
7890e751525SEric Saxe 	}
7900e751525SEric Saxe 
7910e751525SEric Saxe 	if (count < 2) {
79200f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: _CST invalid count %d < 2 for "
79300f97612SMark Haywood 		    "CPU %d", count, handle->cs_id);
794621e6c37SBill Holler 		kmem_free(CPU_ACPI_CSTATES(handle), alloc_size);
795621e6c37SBill Holler 		CPU_ACPI_CSTATES(handle) = NULL;
796621e6c37SBill Holler 		CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)0;
79700f97612SMark Haywood 		goto out;
7980e751525SEric Saxe 	}
7999aa01d98SBill Holler 	cstate = (cpu_acpi_cstate_t *)CPU_ACPI_CSTATES(handle);
8009aa01d98SBill Holler 	if (cstate[0].cs_type != CPU_ACPI_C1) {
80100f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: _CST first element type not "
80200f97612SMark Haywood 		    "C1: %d for CPU %d", (int)cstate->cs_type, handle->cs_id);
803621e6c37SBill Holler 		kmem_free(CPU_ACPI_CSTATES(handle), alloc_size);
804621e6c37SBill Holler 		CPU_ACPI_CSTATES(handle) = NULL;
805621e6c37SBill Holler 		CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)0;
80600f97612SMark Haywood 		goto out;
8079aa01d98SBill Holler 	}
8080e751525SEric Saxe 
809621e6c37SBill Holler 	if (count != cnt) {
810621e6c37SBill Holler 		void	*orig = CPU_ACPI_CSTATES(handle);
811621e6c37SBill Holler 
8120e751525SEric Saxe 		CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)count;
813621e6c37SBill Holler 		CPU_ACPI_CSTATES(handle) = kmem_zalloc(
814621e6c37SBill Holler 		    CPU_ACPI_CSTATES_SIZE(count), KM_SLEEP);
815621e6c37SBill Holler 		(void) memcpy(CPU_ACPI_CSTATES(handle), orig,
816621e6c37SBill Holler 		    CPU_ACPI_CSTATES_SIZE(count));
817621e6c37SBill Holler 		kmem_free(orig, alloc_size);
818621e6c37SBill Holler 	}
8190e751525SEric Saxe 
8200e751525SEric Saxe 	CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_CST_CACHED);
82100f97612SMark Haywood 
82200f97612SMark Haywood 	ret = 0;
82300f97612SMark Haywood 
82400f97612SMark Haywood out:
82500f97612SMark Haywood 	if (abuf.Pointer != NULL)
82600f97612SMark Haywood 		AcpiOsFree(abuf.Pointer);
82700f97612SMark Haywood 	return (ret);
8280e751525SEric Saxe }
8290e751525SEric Saxe 
8300e751525SEric Saxe /*
8310e751525SEric Saxe  * Cache the _PCT, _PSS, _PSD and _PPC data.
8320e751525SEric Saxe  */
8330e751525SEric Saxe int
8340e751525SEric Saxe cpu_acpi_cache_pstate_data(cpu_acpi_handle_t handle)
8350e751525SEric Saxe {
8360e751525SEric Saxe 	if (cpu_acpi_cache_pct(handle) < 0) {
83700f97612SMark Haywood 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
83800f97612SMark Haywood 		    int, PCT_OBJ);
8390e751525SEric Saxe 		return (-1);
8400e751525SEric Saxe 	}
8410e751525SEric Saxe 
8420e751525SEric Saxe 	if (cpu_acpi_cache_pstates(handle) != 0) {
84300f97612SMark Haywood 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
84400f97612SMark Haywood 		    int, PSS_OBJ);
8450e751525SEric Saxe 		return (-1);
8460e751525SEric Saxe 	}
8470e751525SEric Saxe 
8480e751525SEric Saxe 	if (cpu_acpi_cache_psd(handle) < 0) {
84900f97612SMark Haywood 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
85000f97612SMark Haywood 		    int, PSD_OBJ);
8510e751525SEric Saxe 		return (-1);
8520e751525SEric Saxe 	}
8530e751525SEric Saxe 
8540e751525SEric Saxe 	cpu_acpi_cache_ppc(handle);
8550e751525SEric Saxe 
8560e751525SEric Saxe 	return (0);
8570e751525SEric Saxe }
8580e751525SEric Saxe 
8590e751525SEric Saxe void
8600e751525SEric Saxe cpu_acpi_free_pstate_data(cpu_acpi_handle_t handle)
8610e751525SEric Saxe {
8620e751525SEric Saxe 	if (handle != NULL) {
8630e751525SEric Saxe 		if (CPU_ACPI_PSTATES(handle)) {
8640e751525SEric Saxe 			kmem_free(CPU_ACPI_PSTATES(handle),
8650e751525SEric Saxe 			    CPU_ACPI_PSTATES_SIZE(
8660e751525SEric Saxe 			    CPU_ACPI_PSTATES_COUNT(handle)));
8670e751525SEric Saxe 			CPU_ACPI_PSTATES(handle) = NULL;
8680e751525SEric Saxe 		}
8690e751525SEric Saxe 	}
8700e751525SEric Saxe }
8710e751525SEric Saxe 
8720e751525SEric Saxe /*
8730e751525SEric Saxe  * Cache the _PTC, _TSS, _TSD and _TPC data.
8740e751525SEric Saxe  */
8750e751525SEric Saxe int
8760e751525SEric Saxe cpu_acpi_cache_tstate_data(cpu_acpi_handle_t handle)
8770e751525SEric Saxe {
87800f97612SMark Haywood 	int ret;
87937d22dc0SAnup Pemmaiah 
8800e751525SEric Saxe 	if (cpu_acpi_cache_ptc(handle) < 0) {
88100f97612SMark Haywood 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
88200f97612SMark Haywood 		    int, PTC_OBJ);
8830e751525SEric Saxe 		return (-1);
8840e751525SEric Saxe 	}
8850e751525SEric Saxe 
88600f97612SMark Haywood 	if ((ret = cpu_acpi_cache_tstates(handle)) != 0) {
88700f97612SMark Haywood 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
88800f97612SMark Haywood 		    int, TSS_OBJ);
88900f97612SMark Haywood 		return (ret);
8900e751525SEric Saxe 	}
8910e751525SEric Saxe 
8920e751525SEric Saxe 	if (cpu_acpi_cache_tsd(handle) < 0) {
89300f97612SMark Haywood 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
89400f97612SMark Haywood 		    int, TSD_OBJ);
8950e751525SEric Saxe 		return (-1);
8960e751525SEric Saxe 	}
8970e751525SEric Saxe 
8980e751525SEric Saxe 	cpu_acpi_cache_tpc(handle);
8990e751525SEric Saxe 
9000e751525SEric Saxe 	return (0);
9010e751525SEric Saxe }
9020e751525SEric Saxe 
9030e751525SEric Saxe void
9040e751525SEric Saxe cpu_acpi_free_tstate_data(cpu_acpi_handle_t handle)
9050e751525SEric Saxe {
9060e751525SEric Saxe 	if (handle != NULL) {
9070e751525SEric Saxe 		if (CPU_ACPI_TSTATES(handle)) {
9080e751525SEric Saxe 			kmem_free(CPU_ACPI_TSTATES(handle),
9090e751525SEric Saxe 			    CPU_ACPI_TSTATES_SIZE(
9100e751525SEric Saxe 			    CPU_ACPI_TSTATES_COUNT(handle)));
9110e751525SEric Saxe 			CPU_ACPI_TSTATES(handle) = NULL;
9120e751525SEric Saxe 		}
9130e751525SEric Saxe 	}
9140e751525SEric Saxe }
9150e751525SEric Saxe 
9160e751525SEric Saxe /*
9170e751525SEric Saxe  * Cache the _CST data.
9180e751525SEric Saxe  */
9190e751525SEric Saxe int
9200e751525SEric Saxe cpu_acpi_cache_cstate_data(cpu_acpi_handle_t handle)
9210e751525SEric Saxe {
92200f97612SMark Haywood 	int ret;
92300f97612SMark Haywood 
92400f97612SMark Haywood 	if ((ret = cpu_acpi_cache_cst(handle)) != 0) {
92500f97612SMark Haywood 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
92600f97612SMark Haywood 		    int, CST_OBJ);
92700f97612SMark Haywood 		return (ret);
9280e751525SEric Saxe 	}
9290e751525SEric Saxe 
9300e751525SEric Saxe 	if (cpu_acpi_cache_csd(handle) < 0) {
93100f97612SMark Haywood 		DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
93200f97612SMark Haywood 		    int, CSD_OBJ);
9330e751525SEric Saxe 		return (-1);
9340e751525SEric Saxe 	}
9350e751525SEric Saxe 
9360e751525SEric Saxe 	return (0);
9370e751525SEric Saxe }
9380e751525SEric Saxe 
9390e751525SEric Saxe void
9400e751525SEric Saxe cpu_acpi_free_cstate_data(cpu_acpi_handle_t handle)
9410e751525SEric Saxe {
9420e751525SEric Saxe 	if (handle != NULL) {
9430e751525SEric Saxe 		if (CPU_ACPI_CSTATES(handle)) {
9440e751525SEric Saxe 			kmem_free(CPU_ACPI_CSTATES(handle),
9450e751525SEric Saxe 			    CPU_ACPI_CSTATES_SIZE(
9460e751525SEric Saxe 			    CPU_ACPI_CSTATES_COUNT(handle)));
9470e751525SEric Saxe 			CPU_ACPI_CSTATES(handle) = NULL;
9480e751525SEric Saxe 		}
9490e751525SEric Saxe 	}
9500e751525SEric Saxe }
9510e751525SEric Saxe 
9520e751525SEric Saxe /*
9530e751525SEric Saxe  * Register a handler for processor change notifications.
9540e751525SEric Saxe  */
9550e751525SEric Saxe void
9560e751525SEric Saxe cpu_acpi_install_notify_handler(cpu_acpi_handle_t handle,
9570e751525SEric Saxe     ACPI_NOTIFY_HANDLER handler, void *ctx)
9580e751525SEric Saxe {
9590e751525SEric Saxe 	if (ACPI_FAILURE(AcpiInstallNotifyHandler(handle->cs_handle,
9600e751525SEric Saxe 	    ACPI_DEVICE_NOTIFY, handler, ctx)))
9610e751525SEric Saxe 		cmn_err(CE_NOTE, "!cpu_acpi: Unable to register "
96200f97612SMark Haywood 		    "notify handler for CPU %d.", handle->cs_id);
9630e751525SEric Saxe }
9640e751525SEric Saxe 
9650e751525SEric Saxe /*
9660e751525SEric Saxe  * Remove a handler for processor change notifications.
9670e751525SEric Saxe  */
9680e751525SEric Saxe void
9690e751525SEric Saxe cpu_acpi_remove_notify_handler(cpu_acpi_handle_t handle,
9700e751525SEric Saxe     ACPI_NOTIFY_HANDLER handler)
9710e751525SEric Saxe {
9720e751525SEric Saxe 	if (ACPI_FAILURE(AcpiRemoveNotifyHandler(handle->cs_handle,
9730e751525SEric Saxe 	    ACPI_DEVICE_NOTIFY, handler)))
9740e751525SEric Saxe 		cmn_err(CE_NOTE, "!cpu_acpi: Unable to remove "
97500f97612SMark Haywood 		    "notify handler for CPU %d.", handle->cs_id);
9760e751525SEric Saxe }
9770e751525SEric Saxe 
9780e751525SEric Saxe /*
9790e751525SEric Saxe  * Write _PDC.
9800e751525SEric Saxe  */
9810e751525SEric Saxe int
9820e751525SEric Saxe cpu_acpi_write_pdc(cpu_acpi_handle_t handle, uint32_t revision, uint32_t count,
9830e751525SEric Saxe     uint32_t *capabilities)
9840e751525SEric Saxe {
98500f97612SMark Haywood 	ACPI_STATUS astatus;
9860e751525SEric Saxe 	ACPI_OBJECT obj;
9870e751525SEric Saxe 	ACPI_OBJECT_LIST list = { 1, &obj};
9880e751525SEric Saxe 	uint32_t *buffer;
9890e751525SEric Saxe 	uint32_t *bufptr;
9900e751525SEric Saxe 	uint32_t bufsize;
9910e751525SEric Saxe 	int i;
99200f97612SMark Haywood 	int ret = 0;
9930e751525SEric Saxe 
9940e751525SEric Saxe 	bufsize = (count + 2) * sizeof (uint32_t);
9950e751525SEric Saxe 	buffer = kmem_zalloc(bufsize, KM_SLEEP);
9960e751525SEric Saxe 	buffer[0] = revision;
9970e751525SEric Saxe 	buffer[1] = count;
9980e751525SEric Saxe 	bufptr = &buffer[2];
9990e751525SEric Saxe 	for (i = 0; i < count; i++)
10000e751525SEric Saxe 		*bufptr++ = *capabilities++;
10010e751525SEric Saxe 
10020e751525SEric Saxe 	obj.Type = ACPI_TYPE_BUFFER;
10030e751525SEric Saxe 	obj.Buffer.Length = bufsize;
10040e751525SEric Saxe 	obj.Buffer.Pointer = (void *)buffer;
10050e751525SEric Saxe 
10060e751525SEric Saxe 	/*
100700f97612SMark Haywood 	 * Fetch the ??? (if present) for the CPU node.
10080e751525SEric Saxe 	 */
100900f97612SMark Haywood 	astatus = AcpiEvaluateObject(handle->cs_handle, "_PDC", &list, NULL);
101000f97612SMark Haywood 	if (ACPI_FAILURE(astatus)) {
101100f97612SMark Haywood 		if (astatus == AE_NOT_FOUND) {
101200f97612SMark Haywood 			DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
101300f97612SMark Haywood 			    int, PDC_OBJ, int, astatus);
101400f97612SMark Haywood 			ret = 1;
101500f97612SMark Haywood 		} else {
101600f97612SMark Haywood 			cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating _PDC "
101700f97612SMark Haywood 			    "package for CPU %d.", astatus, handle->cs_id);
101800f97612SMark Haywood 			ret = -1;
101900f97612SMark Haywood 		}
10200e751525SEric Saxe 	}
10210e751525SEric Saxe 
10220e751525SEric Saxe 	kmem_free(buffer, bufsize);
102300f97612SMark Haywood 	return (ret);
10240e751525SEric Saxe }
10250e751525SEric Saxe 
10260e751525SEric Saxe /*
10270e751525SEric Saxe  * Write to system IO port.
10280e751525SEric Saxe  */
10290e751525SEric Saxe int
10300e751525SEric Saxe cpu_acpi_write_port(ACPI_IO_ADDRESS address, uint32_t value, uint32_t width)
10310e751525SEric Saxe {
10320e751525SEric Saxe 	if (ACPI_FAILURE(AcpiOsWritePort(address, value, width))) {
103300f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: error writing system IO port "
10340e751525SEric Saxe 		    "%lx.", (long)address);
10350e751525SEric Saxe 		return (-1);
10360e751525SEric Saxe 	}
10370e751525SEric Saxe 	return (0);
10380e751525SEric Saxe }
10390e751525SEric Saxe 
10400e751525SEric Saxe /*
10410e751525SEric Saxe  * Read from a system IO port.
10420e751525SEric Saxe  */
10430e751525SEric Saxe int
10440e751525SEric Saxe cpu_acpi_read_port(ACPI_IO_ADDRESS address, uint32_t *value, uint32_t width)
10450e751525SEric Saxe {
10460e751525SEric Saxe 	if (ACPI_FAILURE(AcpiOsReadPort(address, value, width))) {
104700f97612SMark Haywood 		cmn_err(CE_NOTE, "!cpu_acpi: error reading system IO port "
10480e751525SEric Saxe 		    "%lx.", (long)address);
10490e751525SEric Saxe 		return (-1);
10500e751525SEric Saxe 	}
10510e751525SEric Saxe 	return (0);
10520e751525SEric Saxe }
10530e751525SEric Saxe 
10540e751525SEric Saxe /*
10550e751525SEric Saxe  * Return supported frequencies.
10560e751525SEric Saxe  */
10570e751525SEric Saxe uint_t
10580e751525SEric Saxe cpu_acpi_get_speeds(cpu_acpi_handle_t handle, int **speeds)
10590e751525SEric Saxe {
10600e751525SEric Saxe 	cpu_acpi_pstate_t *pstate;
10610e751525SEric Saxe 	int *hspeeds;
10620e751525SEric Saxe 	uint_t nspeeds;
10630e751525SEric Saxe 	int i;
10640e751525SEric Saxe 
10650e751525SEric Saxe 	nspeeds = CPU_ACPI_PSTATES_COUNT(handle);
10660e751525SEric Saxe 	pstate = (cpu_acpi_pstate_t *)CPU_ACPI_PSTATES(handle);
10670e751525SEric Saxe 	hspeeds = kmem_zalloc(nspeeds * sizeof (int), KM_SLEEP);
10680e751525SEric Saxe 	for (i = 0; i < nspeeds; i++) {
10690e751525SEric Saxe 		hspeeds[i] = CPU_ACPI_FREQ(pstate);
10700e751525SEric Saxe 		pstate++;
10710e751525SEric Saxe 	}
10720e751525SEric Saxe 	*speeds = hspeeds;
10730e751525SEric Saxe 	return (nspeeds);
10740e751525SEric Saxe }
10750e751525SEric Saxe 
10760e751525SEric Saxe /*
10770e751525SEric Saxe  * Free resources allocated by cpu_acpi_get_speeds().
10780e751525SEric Saxe  */
10790e751525SEric Saxe void
10800e751525SEric Saxe cpu_acpi_free_speeds(int *speeds, uint_t nspeeds)
10810e751525SEric Saxe {
10820e751525SEric Saxe 	kmem_free(speeds, nspeeds * sizeof (int));
10830e751525SEric Saxe }
10840e751525SEric Saxe 
10850e751525SEric Saxe uint_t
10860e751525SEric Saxe cpu_acpi_get_max_cstates(cpu_acpi_handle_t handle)
10870e751525SEric Saxe {
10880e751525SEric Saxe 	if (CPU_ACPI_CSTATES(handle))
10890e751525SEric Saxe 		return (CPU_ACPI_CSTATES_COUNT(handle));
10900e751525SEric Saxe 	else
10910e751525SEric Saxe 		return (1);
10920e751525SEric Saxe }
10930e751525SEric Saxe 
10940e751525SEric Saxe void
10950e751525SEric Saxe cpu_acpi_set_register(uint32_t bitreg, uint32_t value)
10960e751525SEric Saxe {
1097444f66e7SMark Haywood 	(void) AcpiWriteBitRegister(bitreg, value);
10980e751525SEric Saxe }
10990e751525SEric Saxe 
11000e751525SEric Saxe void
11010e751525SEric Saxe cpu_acpi_get_register(uint32_t bitreg, uint32_t *value)
11020e751525SEric Saxe {
1103444f66e7SMark Haywood 	(void) AcpiReadBitRegister(bitreg, value);
11040e751525SEric Saxe }
11050e751525SEric Saxe 
11060e751525SEric Saxe /*
11070e751525SEric Saxe  * Map the dip to an ACPI handle for the device.
11080e751525SEric Saxe  */
11090e751525SEric Saxe cpu_acpi_handle_t
11100e751525SEric Saxe cpu_acpi_init(cpu_t *cp)
11110e751525SEric Saxe {
11120e751525SEric Saxe 	cpu_acpi_handle_t handle;
11130e751525SEric Saxe 
11140e751525SEric Saxe 	handle = kmem_zalloc(sizeof (cpu_acpi_state_t), KM_SLEEP);
11150e751525SEric Saxe 
11160e751525SEric Saxe 	if (ACPI_FAILURE(acpica_get_handle_cpu(cp->cpu_id,
11170e751525SEric Saxe 	    &handle->cs_handle))) {
11180e751525SEric Saxe 		kmem_free(handle, sizeof (cpu_acpi_state_t));
11190e751525SEric Saxe 		return (NULL);
11200e751525SEric Saxe 	}
11210e751525SEric Saxe 	handle->cs_id = cp->cpu_id;
11220e751525SEric Saxe 	return (handle);
11230e751525SEric Saxe }
11240e751525SEric Saxe 
11250e751525SEric Saxe /*
11260e751525SEric Saxe  * Free any resources.
11270e751525SEric Saxe  */
11280e751525SEric Saxe void
11290e751525SEric Saxe cpu_acpi_fini(cpu_acpi_handle_t handle)
11300e751525SEric Saxe {
11310e751525SEric Saxe 	if (handle)
11320e751525SEric Saxe 		kmem_free(handle, sizeof (cpu_acpi_state_t));
11330e751525SEric Saxe }
1134