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