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 CPU_ACPI_BM_INFO(handle) = 0; 738 cstate = (cpu_acpi_cstate_t *)CPU_ACPI_CSTATES(handle); 739 p = cstate; 740 741 for (i = 1, count = 1; i <= cnt; i++) { 742 ACPI_OBJECT *pkg; 743 AML_RESOURCE_GENERIC_REGISTER *reg; 744 ACPI_OBJECT *element; 745 746 pkg = &(obj->Package.Elements[i]); 747 reg = (AML_RESOURCE_GENERIC_REGISTER *) 748 pkg->Package.Elements[0].Buffer.Pointer; 749 cstate->cs_addrspace_id = reg->AddressSpaceId; 750 cstate->cs_address = reg->Address; 751 element = &(pkg->Package.Elements[1]); 752 cstate->cs_type = element->Integer.Value; 753 element = &(pkg->Package.Elements[2]); 754 cstate->cs_latency = element->Integer.Value; 755 element = &(pkg->Package.Elements[3]); 756 cstate->cs_power = element->Integer.Value; 757 758 if (cpu_acpi_verify_cstate(cstate)) { 759 /* 760 * ignore this entry if it's not valid 761 */ 762 continue; 763 } 764 if (cstate == p) { 765 cstate++; 766 } else if (p->cs_type == cstate->cs_type) { 767 /* 768 * if there are duplicate entries, we keep the 769 * last one. This fixes: 770 * 1) some buggy BIOS have total duplicate entries. 771 * 2) ACPI Spec allows the same cstate entry with 772 * different power and latency, we use the one 773 * with more power saving. 774 */ 775 (void) memcpy(p, cstate, sizeof (cpu_acpi_cstate_t)); 776 } else { 777 /* 778 * we got a valid entry, cache it to the 779 * cstate structure 780 */ 781 p = cstate++; 782 count++; 783 } 784 } 785 786 if (count < 2) { 787 cmn_err(CE_NOTE, "!cpu_acpi: _CST invalid count %d < 2 for " 788 "CPU %d", count, handle->cs_id); 789 kmem_free(CPU_ACPI_CSTATES(handle), alloc_size); 790 CPU_ACPI_CSTATES(handle) = NULL; 791 CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)0; 792 goto out; 793 } 794 cstate = (cpu_acpi_cstate_t *)CPU_ACPI_CSTATES(handle); 795 if (cstate[0].cs_type != CPU_ACPI_C1) { 796 cmn_err(CE_NOTE, "!cpu_acpi: _CST first element type not " 797 "C1: %d for CPU %d", (int)cstate->cs_type, handle->cs_id); 798 kmem_free(CPU_ACPI_CSTATES(handle), alloc_size); 799 CPU_ACPI_CSTATES(handle) = NULL; 800 CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)0; 801 goto out; 802 } 803 804 if (count != cnt) { 805 void *orig = CPU_ACPI_CSTATES(handle); 806 807 CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)count; 808 CPU_ACPI_CSTATES(handle) = kmem_zalloc( 809 CPU_ACPI_CSTATES_SIZE(count), KM_SLEEP); 810 (void) memcpy(CPU_ACPI_CSTATES(handle), orig, 811 CPU_ACPI_CSTATES_SIZE(count)); 812 kmem_free(orig, alloc_size); 813 } 814 815 CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_CST_CACHED); 816 817 ret = 0; 818 819 out: 820 if (abuf.Pointer != NULL) 821 AcpiOsFree(abuf.Pointer); 822 return (ret); 823 } 824 825 /* 826 * Cache the _PCT, _PSS, _PSD and _PPC data. 827 */ 828 int 829 cpu_acpi_cache_pstate_data(cpu_acpi_handle_t handle) 830 { 831 if (cpu_acpi_cache_pct(handle) < 0) { 832 DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id, 833 int, PCT_OBJ); 834 cmn_err(CE_NOTE, "!cpu_acpi: error parsing _PCT for " 835 "CPU %d", handle->cs_id); 836 return (-1); 837 } 838 839 if (cpu_acpi_cache_pstates(handle) != 0) { 840 DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id, 841 int, PSS_OBJ); 842 cmn_err(CE_NOTE, "!cpu_acpi: error parsing _PSS for " 843 "CPU %d", handle->cs_id); 844 return (-1); 845 } 846 847 if (cpu_acpi_cache_psd(handle) < 0) { 848 DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id, 849 int, PSD_OBJ); 850 cmn_err(CE_NOTE, "!cpu_acpi: error parsing _PSD for " 851 "CPU %d", handle->cs_id); 852 return (-1); 853 } 854 855 cpu_acpi_cache_ppc(handle); 856 857 return (0); 858 } 859 860 void 861 cpu_acpi_free_pstate_data(cpu_acpi_handle_t handle) 862 { 863 if (handle != NULL) { 864 if (CPU_ACPI_PSTATES(handle)) { 865 kmem_free(CPU_ACPI_PSTATES(handle), 866 CPU_ACPI_PSTATES_SIZE( 867 CPU_ACPI_PSTATES_COUNT(handle))); 868 CPU_ACPI_PSTATES(handle) = NULL; 869 } 870 } 871 } 872 873 /* 874 * Cache the _PTC, _TSS, _TSD and _TPC data. 875 */ 876 int 877 cpu_acpi_cache_tstate_data(cpu_acpi_handle_t handle) 878 { 879 int ret; 880 881 if (cpu_acpi_cache_ptc(handle) < 0) { 882 DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id, 883 int, PTC_OBJ); 884 return (-1); 885 } 886 887 if ((ret = cpu_acpi_cache_tstates(handle)) != 0) { 888 DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id, 889 int, TSS_OBJ); 890 return (ret); 891 } 892 893 if (cpu_acpi_cache_tsd(handle) < 0) { 894 DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id, 895 int, TSD_OBJ); 896 return (-1); 897 } 898 899 cpu_acpi_cache_tpc(handle); 900 901 return (0); 902 } 903 904 void 905 cpu_acpi_free_tstate_data(cpu_acpi_handle_t handle) 906 { 907 if (handle != NULL) { 908 if (CPU_ACPI_TSTATES(handle)) { 909 kmem_free(CPU_ACPI_TSTATES(handle), 910 CPU_ACPI_TSTATES_SIZE( 911 CPU_ACPI_TSTATES_COUNT(handle))); 912 CPU_ACPI_TSTATES(handle) = NULL; 913 } 914 } 915 } 916 917 /* 918 * Cache the _CST data. 919 */ 920 int 921 cpu_acpi_cache_cstate_data(cpu_acpi_handle_t handle) 922 { 923 int ret; 924 925 if ((ret = cpu_acpi_cache_cst(handle)) != 0) { 926 DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id, 927 int, CST_OBJ); 928 return (ret); 929 } 930 931 if (cpu_acpi_cache_csd(handle) < 0) { 932 DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id, 933 int, CSD_OBJ); 934 return (-1); 935 } 936 937 return (0); 938 } 939 940 void 941 cpu_acpi_free_cstate_data(cpu_acpi_handle_t handle) 942 { 943 if (handle != NULL) { 944 if (CPU_ACPI_CSTATES(handle)) { 945 kmem_free(CPU_ACPI_CSTATES(handle), 946 CPU_ACPI_CSTATES_SIZE( 947 CPU_ACPI_CSTATES_COUNT(handle))); 948 CPU_ACPI_CSTATES(handle) = NULL; 949 } 950 } 951 } 952 953 /* 954 * Register a handler for processor change notifications. 955 */ 956 void 957 cpu_acpi_install_notify_handler(cpu_acpi_handle_t handle, 958 ACPI_NOTIFY_HANDLER handler, void *ctx) 959 { 960 if (ACPI_FAILURE(AcpiInstallNotifyHandler(handle->cs_handle, 961 ACPI_DEVICE_NOTIFY, handler, ctx))) 962 cmn_err(CE_NOTE, "!cpu_acpi: Unable to register " 963 "notify handler for CPU %d.", handle->cs_id); 964 } 965 966 /* 967 * Remove a handler for processor change notifications. 968 */ 969 void 970 cpu_acpi_remove_notify_handler(cpu_acpi_handle_t handle, 971 ACPI_NOTIFY_HANDLER handler) 972 { 973 if (ACPI_FAILURE(AcpiRemoveNotifyHandler(handle->cs_handle, 974 ACPI_DEVICE_NOTIFY, handler))) 975 cmn_err(CE_NOTE, "!cpu_acpi: Unable to remove " 976 "notify handler for CPU %d.", handle->cs_id); 977 } 978 979 /* 980 * Write _PDC. 981 */ 982 int 983 cpu_acpi_write_pdc(cpu_acpi_handle_t handle, uint32_t revision, uint32_t count, 984 uint32_t *capabilities) 985 { 986 ACPI_STATUS astatus; 987 ACPI_OBJECT obj; 988 ACPI_OBJECT_LIST list = { 1, &obj}; 989 uint32_t *buffer; 990 uint32_t *bufptr; 991 uint32_t bufsize; 992 int i; 993 int ret = 0; 994 995 bufsize = (count + 2) * sizeof (uint32_t); 996 buffer = kmem_zalloc(bufsize, KM_SLEEP); 997 buffer[0] = revision; 998 buffer[1] = count; 999 bufptr = &buffer[2]; 1000 for (i = 0; i < count; i++) 1001 *bufptr++ = *capabilities++; 1002 1003 obj.Type = ACPI_TYPE_BUFFER; 1004 obj.Buffer.Length = bufsize; 1005 obj.Buffer.Pointer = (void *)buffer; 1006 1007 /* 1008 * Fetch the ??? (if present) for the CPU node. 1009 */ 1010 astatus = AcpiEvaluateObject(handle->cs_handle, "_PDC", &list, NULL); 1011 if (ACPI_FAILURE(astatus)) { 1012 if (astatus == AE_NOT_FOUND) { 1013 DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id, 1014 int, PDC_OBJ, int, astatus); 1015 ret = 1; 1016 } else { 1017 cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating _PDC " 1018 "package for CPU %d.", astatus, handle->cs_id); 1019 ret = -1; 1020 } 1021 } 1022 1023 kmem_free(buffer, bufsize); 1024 return (ret); 1025 } 1026 1027 /* 1028 * Write to system IO port. 1029 */ 1030 int 1031 cpu_acpi_write_port(ACPI_IO_ADDRESS address, uint32_t value, uint32_t width) 1032 { 1033 if (ACPI_FAILURE(AcpiOsWritePort(address, value, width))) { 1034 cmn_err(CE_NOTE, "!cpu_acpi: error writing system IO port " 1035 "%lx.", (long)address); 1036 return (-1); 1037 } 1038 return (0); 1039 } 1040 1041 /* 1042 * Read from a system IO port. 1043 */ 1044 int 1045 cpu_acpi_read_port(ACPI_IO_ADDRESS address, uint32_t *value, uint32_t width) 1046 { 1047 if (ACPI_FAILURE(AcpiOsReadPort(address, value, width))) { 1048 cmn_err(CE_NOTE, "!cpu_acpi: error reading system IO port " 1049 "%lx.", (long)address); 1050 return (-1); 1051 } 1052 return (0); 1053 } 1054 1055 /* 1056 * Return supported frequencies. 1057 */ 1058 uint_t 1059 cpu_acpi_get_speeds(cpu_acpi_handle_t handle, int **speeds) 1060 { 1061 cpu_acpi_pstate_t *pstate; 1062 int *hspeeds; 1063 uint_t nspeeds; 1064 int i; 1065 1066 nspeeds = CPU_ACPI_PSTATES_COUNT(handle); 1067 pstate = (cpu_acpi_pstate_t *)CPU_ACPI_PSTATES(handle); 1068 hspeeds = kmem_zalloc(nspeeds * sizeof (int), KM_SLEEP); 1069 for (i = 0; i < nspeeds; i++) { 1070 hspeeds[i] = CPU_ACPI_FREQ(pstate); 1071 pstate++; 1072 } 1073 *speeds = hspeeds; 1074 return (nspeeds); 1075 } 1076 1077 /* 1078 * Free resources allocated by cpu_acpi_get_speeds(). 1079 */ 1080 void 1081 cpu_acpi_free_speeds(int *speeds, uint_t nspeeds) 1082 { 1083 kmem_free(speeds, nspeeds * sizeof (int)); 1084 } 1085 1086 uint_t 1087 cpu_acpi_get_max_cstates(cpu_acpi_handle_t handle) 1088 { 1089 if (CPU_ACPI_CSTATES(handle)) 1090 return (CPU_ACPI_CSTATES_COUNT(handle)); 1091 else 1092 return (1); 1093 } 1094 1095 void 1096 cpu_acpi_set_register(uint32_t bitreg, uint32_t value) 1097 { 1098 AcpiWriteBitRegister(bitreg, value); 1099 } 1100 1101 void 1102 cpu_acpi_get_register(uint32_t bitreg, uint32_t *value) 1103 { 1104 AcpiReadBitRegister(bitreg, value); 1105 } 1106 1107 /* 1108 * Map the dip to an ACPI handle for the device. 1109 */ 1110 cpu_acpi_handle_t 1111 cpu_acpi_init(cpu_t *cp) 1112 { 1113 cpu_acpi_handle_t handle; 1114 1115 handle = kmem_zalloc(sizeof (cpu_acpi_state_t), KM_SLEEP); 1116 1117 if (ACPI_FAILURE(acpica_get_handle_cpu(cp->cpu_id, 1118 &handle->cs_handle))) { 1119 kmem_free(handle, sizeof (cpu_acpi_state_t)); 1120 return (NULL); 1121 } 1122 handle->cs_id = cp->cpu_id; 1123 return (handle); 1124 } 1125 1126 /* 1127 * Free any resources. 1128 */ 1129 void 1130 cpu_acpi_fini(cpu_acpi_handle_t handle) 1131 { 1132 if (handle) 1133 kmem_free(handle, sizeof (cpu_acpi_state_t)); 1134 } 1135