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