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