1 /* 2 * Copyright (c) 2009 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Sepherosa Ziehau <sepherosa@gmail.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "opt_acpi.h" 36 37 #include <sys/param.h> 38 #include <sys/bus.h> 39 #include <sys/kernel.h> 40 #include <sys/malloc.h> 41 #include <sys/queue.h> 42 #include <sys/rman.h> 43 #include <sys/sysctl.h> 44 #include <sys/msgport2.h> 45 #include <sys/cpu_topology.h> 46 47 #include <net/netisr2.h> 48 #include <net/netmsg2.h> 49 #include <net/if_var.h> 50 51 #include "acpi.h" 52 #include "acpivar.h" 53 #include "acpi_cpu.h" 54 #include "acpi_cpu_pstate.h" 55 56 #define ACPI_NPSTATE_MAX 16 57 58 #define ACPI_PSS_PX_NENTRY 6 59 60 #define ACPI_PSD_COORD_SWALL 0xfc 61 #define ACPI_PSD_COORD_SWANY 0xfd 62 #define ACPI_PSD_COORD_HWALL 0xfe 63 #define ACPI_PSD_COORD_VALID(coord) \ 64 ((coord) == ACPI_PSD_COORD_SWALL || \ 65 (coord) == ACPI_PSD_COORD_SWANY || \ 66 (coord) == ACPI_PSD_COORD_HWALL) 67 68 struct acpi_pst_softc; 69 LIST_HEAD(acpi_pst_list, acpi_pst_softc); 70 71 struct netmsg_acpi_pst { 72 struct netmsg_base base; 73 const struct acpi_pst_res *ctrl; 74 const struct acpi_pst_res *status; 75 }; 76 77 struct acpi_pst_domain { 78 uint32_t pd_dom; 79 uint32_t pd_coord; 80 uint32_t pd_nproc; 81 LIST_ENTRY(acpi_pst_domain) pd_link; 82 83 uint32_t pd_flags; 84 85 int pd_state; 86 int pd_sstart; 87 struct acpi_pst_list pd_pstlist; 88 89 struct sysctl_ctx_list pd_sysctl_ctx; 90 struct sysctl_oid *pd_sysctl_tree; 91 }; 92 LIST_HEAD(acpi_pst_domlist, acpi_pst_domain); 93 94 #define ACPI_PSTDOM_FLAG_STUB 0x1 /* stub domain, no _PSD */ 95 #define ACPI_PSTDOM_FLAG_DEAD 0x2 /* domain can't be started */ 96 #define ACPI_PSTDOM_FLAG_INT 0x4 /* domain created from Integer _PSD */ 97 98 struct acpi_pst_softc { 99 device_t pst_dev; 100 struct acpi_cpu_softc *pst_parent; 101 struct acpi_pst_domain *pst_domain; 102 struct acpi_pst_res pst_creg; 103 struct acpi_pst_res pst_sreg; 104 105 int pst_state; 106 int pst_sstart; 107 int pst_cpuid; 108 109 ACPI_HANDLE pst_handle; 110 111 LIST_ENTRY(acpi_pst_softc) pst_link; 112 }; 113 114 static int acpi_pst_probe(device_t dev); 115 static int acpi_pst_attach(device_t dev); 116 117 static void acpi_pst_postattach(void *); 118 static struct acpi_pst_domain * 119 acpi_pst_domain_create_int(device_t, uint32_t); 120 static struct acpi_pst_domain * 121 acpi_pst_domain_create_pkg(device_t, ACPI_OBJECT *); 122 static struct acpi_pst_domain * 123 acpi_pst_domain_find(uint32_t); 124 static struct acpi_pst_domain * 125 acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t); 126 static int acpi_pst_domain_set_pstate(struct acpi_pst_domain *, int); 127 static void acpi_pst_domain_check_nproc(device_t, struct acpi_pst_domain *); 128 static int acpi_pst_global_set_pstate(int); 129 130 static int acpi_pst_check_csr(struct acpi_pst_softc *); 131 static int acpi_pst_check_pstates(struct acpi_pst_softc *); 132 static int acpi_pst_init(struct acpi_pst_softc *); 133 static int acpi_pst_set_pstate(struct acpi_pst_softc *, 134 const struct acpi_pstate *); 135 static const struct acpi_pstate * 136 acpi_pst_get_pstate(struct acpi_pst_softc *); 137 static int acpi_pst_alloc_resource(device_t, ACPI_OBJECT *, int, 138 struct acpi_pst_res *); 139 140 static void acpi_pst_check_csr_handler(netmsg_t); 141 static void acpi_pst_check_pstates_handler(netmsg_t); 142 static void acpi_pst_init_handler(netmsg_t); 143 static void acpi_pst_set_pstate_handler(netmsg_t); 144 static void acpi_pst_get_pstate_handler(netmsg_t); 145 146 static int acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS); 147 static int acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS); 148 static int acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS); 149 static int acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS); 150 151 static struct acpi_pst_domlist acpi_pst_domains = 152 LIST_HEAD_INITIALIZER(acpi_pst_domains); 153 static int acpi_pst_domain_id; 154 155 static int acpi_pst_global_state; 156 157 static int acpi_npstates; 158 static struct acpi_pstate *acpi_pstates; 159 160 static const struct acpi_pst_md *acpi_pst_md; 161 162 static int acpi_pst_ht_reuse_domain = 1; 163 TUNABLE_INT("hw.acpi.cpu.pst.ht_reuse_domain", &acpi_pst_ht_reuse_domain); 164 165 static device_method_t acpi_pst_methods[] = { 166 /* Device interface */ 167 DEVMETHOD(device_probe, acpi_pst_probe), 168 DEVMETHOD(device_attach, acpi_pst_attach), 169 DEVMETHOD(device_detach, bus_generic_detach), 170 DEVMETHOD(device_shutdown, bus_generic_shutdown), 171 DEVMETHOD(device_suspend, bus_generic_suspend), 172 DEVMETHOD(device_resume, bus_generic_resume), 173 174 /* Bus interface */ 175 DEVMETHOD(bus_add_child, bus_generic_add_child), 176 DEVMETHOD(bus_print_child, bus_generic_print_child), 177 DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), 178 DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), 179 DEVMETHOD(bus_get_resource_list, bus_generic_get_resource_list), 180 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 181 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 182 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 183 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 184 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 185 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 186 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 187 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 188 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 189 190 DEVMETHOD_END 191 }; 192 193 static driver_t acpi_pst_driver = { 194 "cpu_pst", 195 acpi_pst_methods, 196 sizeof(struct acpi_pst_softc) 197 }; 198 199 static devclass_t acpi_pst_devclass; 200 DRIVER_MODULE(cpu_pst, cpu, acpi_pst_driver, acpi_pst_devclass, NULL, NULL); 201 MODULE_DEPEND(cpu_pst, acpi, 1, 1, 1); 202 203 static __inline int 204 acpi_pst_freq2index(int freq) 205 { 206 int i; 207 208 for (i = 0; i < acpi_npstates; ++i) { 209 if (acpi_pstates[i].st_freq == freq) 210 return i; 211 } 212 return -1; 213 } 214 215 static int 216 acpi_pst_probe(device_t dev) 217 { 218 ACPI_BUFFER buf; 219 ACPI_HANDLE handle; 220 ACPI_STATUS status; 221 ACPI_OBJECT *obj; 222 223 if (acpi_disabled("cpu_pst") || 224 acpi_get_type(dev) != ACPI_TYPE_PROCESSOR) 225 return ENXIO; 226 227 if (acpi_pst_md == NULL) 228 acpi_pst_md = acpi_pst_md_probe(); 229 230 handle = acpi_get_handle(dev); 231 232 /* 233 * Check _PSD package 234 * 235 * NOTE: 236 * Some BIOSes do not expose _PCT for the second thread of 237 * CPU cores. In this case, _PSD should be enough to get the 238 * P-state of the second thread working, since it must have 239 * the same _PCT and _PSS as the first thread in the same 240 * core. 241 */ 242 buf.Pointer = NULL; 243 buf.Length = ACPI_ALLOCATE_BUFFER; 244 status = AcpiEvaluateObject(handle, "_PSD", NULL, &buf); 245 if (!ACPI_FAILURE(status)) { 246 AcpiOsFree((ACPI_OBJECT *)buf.Pointer); 247 goto done; 248 } 249 250 /* 251 * Check _PCT package 252 */ 253 buf.Pointer = NULL; 254 buf.Length = ACPI_ALLOCATE_BUFFER; 255 status = AcpiEvaluateObject(handle, "_PCT", NULL, &buf); 256 if (ACPI_FAILURE(status)) { 257 if (bootverbose) { 258 device_printf(dev, "Can't get _PCT package - %s\n", 259 AcpiFormatException(status)); 260 } 261 return ENXIO; 262 } 263 264 obj = (ACPI_OBJECT *)buf.Pointer; 265 if (!ACPI_PKG_VALID_EQ(obj, 2)) { 266 device_printf(dev, "Invalid _PCT package\n"); 267 AcpiOsFree(obj); 268 return ENXIO; 269 } 270 AcpiOsFree(obj); 271 272 /* 273 * Check _PSS package 274 */ 275 buf.Pointer = NULL; 276 buf.Length = ACPI_ALLOCATE_BUFFER; 277 status = AcpiEvaluateObject(handle, "_PSS", NULL, &buf); 278 if (ACPI_FAILURE(status)) { 279 device_printf(dev, "Can't get _PSS package - %s\n", 280 AcpiFormatException(status)); 281 return ENXIO; 282 } 283 284 obj = (ACPI_OBJECT *)buf.Pointer; 285 if (!ACPI_PKG_VALID(obj, 1)) { 286 device_printf(dev, "Invalid _PSS package\n"); 287 AcpiOsFree(obj); 288 return ENXIO; 289 } 290 AcpiOsFree(obj); 291 292 done: 293 device_set_desc(dev, "ACPI CPU P-State"); 294 return 0; 295 } 296 297 static int 298 acpi_pst_attach(device_t dev) 299 { 300 struct acpi_pst_softc *sc = device_get_softc(dev), *pst; 301 struct acpi_pst_domain *dom = NULL; 302 ACPI_BUFFER buf; 303 ACPI_STATUS status; 304 ACPI_OBJECT *obj; 305 struct acpi_pstate *pstate, *p; 306 int i, npstate, error; 307 308 sc->pst_dev = dev; 309 sc->pst_parent = device_get_softc(device_get_parent(dev)); 310 sc->pst_handle = acpi_get_handle(dev); 311 sc->pst_cpuid = acpi_get_magic(dev); 312 313 /* 314 * If there is a _PSD, then we create procossor domain 315 * accordingly. If there is no _PSD, we just fake a 316 * default processor domain0. 317 */ 318 buf.Pointer = NULL; 319 buf.Length = ACPI_ALLOCATE_BUFFER; 320 status = AcpiEvaluateObject(sc->pst_handle, "_PSD", NULL, &buf); 321 if (!ACPI_FAILURE(status)) { 322 obj = (ACPI_OBJECT *)buf.Pointer; 323 324 if (acpi_pst_domain_id > 0) { 325 device_printf(dev, "Missing _PSD for certain CPUs\n"); 326 AcpiOsFree(obj); 327 return ENXIO; 328 } 329 acpi_pst_domain_id = -1; 330 331 if (ACPI_PKG_VALID_EQ(obj, 1)) { 332 dom = acpi_pst_domain_create_pkg(dev, 333 &obj->Package.Elements[0]); 334 if (dom == NULL) { 335 AcpiOsFree(obj); 336 return ENXIO; 337 } 338 } else { 339 if (obj->Type != ACPI_TYPE_INTEGER) { 340 device_printf(dev, 341 "Invalid _PSD package, Type 0x%x\n", 342 obj->Type); 343 AcpiOsFree(obj); 344 return ENXIO; 345 } else { 346 device_printf(dev, "Integer _PSD %ju\n", 347 (uintmax_t)obj->Integer.Value); 348 dom = acpi_pst_domain_create_int(dev, 349 obj->Integer.Value); 350 if (dom == NULL) { 351 AcpiOsFree(obj); 352 return ENXIO; 353 } 354 } 355 } 356 357 /* Free _PSD */ 358 AcpiOsFree(buf.Pointer); 359 } else { 360 if (acpi_pst_domain_id < 0) { 361 device_printf(dev, "Missing _PSD for cpu%d\n", 362 sc->pst_cpuid); 363 return ENXIO; 364 } 365 366 /* 367 * Create a stub one processor domain for each processor 368 */ 369 dom = acpi_pst_domain_alloc(acpi_pst_domain_id, 370 ACPI_PSD_COORD_SWANY, 1); 371 dom->pd_flags |= ACPI_PSTDOM_FLAG_STUB; 372 373 ++acpi_pst_domain_id; 374 } 375 376 /* Make sure that adding us will not overflow our domain */ 377 acpi_pst_domain_check_nproc(dev, dom); 378 379 /* 380 * Get control/status registers from _PCT 381 */ 382 buf.Pointer = NULL; 383 buf.Length = ACPI_ALLOCATE_BUFFER; 384 status = AcpiEvaluateObject(sc->pst_handle, "_PCT", NULL, &buf); 385 if (ACPI_FAILURE(status)) { 386 /* 387 * No _PCT. See the comment in acpi_pst_probe() near 388 * _PSD check. 389 * 390 * Use control/status registers of another CPU in the 391 * same domain, or in the same core, if the type of 392 * these registers are "Fixed Hardware", e.g. on most 393 * of the model Intel CPUs. 394 */ 395 pst = LIST_FIRST(&dom->pd_pstlist); 396 if (pst == NULL) { 397 cpumask_t mask; 398 399 mask = get_cpumask_from_level(sc->pst_cpuid, 400 CORE_LEVEL); 401 if (CPUMASK_TESTNZERO(mask)) { 402 struct acpi_pst_domain *dom1; 403 404 LIST_FOREACH(dom1, &acpi_pst_domains, pd_link) { 405 LIST_FOREACH(pst, &dom1->pd_pstlist, 406 pst_link) { 407 if (CPUMASK_TESTBIT(mask, 408 pst->pst_cpuid)) 409 break; 410 } 411 if (pst != NULL) 412 break; 413 } 414 if (pst != NULL && acpi_pst_ht_reuse_domain) { 415 /* 416 * Use the same domain for CPUs in the 417 * same core. 418 */ 419 device_printf(dev, "Destroy domain%u, " 420 "reuse domain%u\n", 421 dom->pd_dom, dom1->pd_dom); 422 LIST_REMOVE(dom, pd_link); 423 kfree(dom, M_DEVBUF); 424 dom = dom1; 425 /* 426 * Make sure that adding us will not 427 * overflow the domain containing 428 * siblings in the same core. 429 */ 430 acpi_pst_domain_check_nproc(dev, dom); 431 } 432 } 433 } 434 if (pst != NULL && 435 pst->pst_creg.pr_res == NULL && 436 pst->pst_creg.pr_rid == 0 && 437 pst->pst_creg.pr_gas.SpaceId == 438 ACPI_ADR_SPACE_FIXED_HARDWARE && 439 pst->pst_sreg.pr_res == NULL && 440 pst->pst_sreg.pr_rid == 0 && 441 pst->pst_sreg.pr_gas.SpaceId == 442 ACPI_ADR_SPACE_FIXED_HARDWARE) { 443 sc->pst_creg = pst->pst_creg; 444 sc->pst_sreg = pst->pst_sreg; 445 device_printf(dev, 446 "No _PCT; reuse %s control/status regs\n", 447 device_get_nameunit(pst->pst_dev)); 448 goto fetch_pss; 449 } 450 device_printf(dev, "Can't get _PCT package - %s\n", 451 AcpiFormatException(status)); 452 return ENXIO; 453 } 454 455 obj = (ACPI_OBJECT *)buf.Pointer; 456 if (!ACPI_PKG_VALID_EQ(obj, 2)) { 457 device_printf(dev, "Invalid _PCT package\n"); 458 AcpiOsFree(obj); 459 return ENXIO; 460 } 461 462 /* Save and try allocating control register */ 463 error = acpi_pst_alloc_resource(dev, obj, 0, &sc->pst_creg); 464 if (error) { 465 AcpiOsFree(obj); 466 return error; 467 } 468 if (bootverbose) { 469 device_printf(dev, "control reg %d %jx\n", 470 sc->pst_creg.pr_gas.SpaceId, 471 (uintmax_t)sc->pst_creg.pr_gas.Address); 472 } 473 474 /* Save and try allocating status register */ 475 error = acpi_pst_alloc_resource(dev, obj, 1, &sc->pst_sreg); 476 if (error) { 477 AcpiOsFree(obj); 478 return error; 479 } 480 if (bootverbose) { 481 device_printf(dev, "status reg %d %jx\n", 482 sc->pst_sreg.pr_gas.SpaceId, 483 (uintmax_t)sc->pst_sreg.pr_gas.Address); 484 } 485 486 /* Free _PCT */ 487 AcpiOsFree(obj); 488 489 fetch_pss: 490 /* 491 * Create P-State table according to _PSS 492 */ 493 buf.Pointer = NULL; 494 buf.Length = ACPI_ALLOCATE_BUFFER; 495 status = AcpiEvaluateObject(sc->pst_handle, "_PSS", NULL, &buf); 496 if (ACPI_FAILURE(status)) { 497 /* 498 * No _PSS. See the comment in acpi_pst_probe() near 499 * _PSD check. 500 * 501 * Assume _PSS are same across all CPUs; well, they 502 * should/have to be so. 503 */ 504 if (acpi_npstates > 0 && acpi_pstates != NULL) { 505 device_printf(dev, "No _PSS\n"); 506 goto fetch_ppc; 507 } 508 device_printf(dev, "Can't get _PSS package - %s\n", 509 AcpiFormatException(status)); 510 return ENXIO; 511 } 512 513 obj = (ACPI_OBJECT *)buf.Pointer; 514 if (!ACPI_PKG_VALID(obj, 1)) { 515 device_printf(dev, "Invalid _PSS package\n"); 516 AcpiOsFree(obj); 517 return ENXIO; 518 } 519 520 /* Don't create too many P-States */ 521 npstate = obj->Package.Count; 522 if (npstate > ACPI_NPSTATE_MAX) { 523 device_printf(dev, "Too many P-States, %d->%d\n", 524 npstate, ACPI_NPSTATE_MAX); 525 npstate = ACPI_NPSTATE_MAX; 526 } 527 528 /* 529 * If we have already created P-State table, 530 * we must make sure that number of entries 531 * is consistent. 532 */ 533 if (acpi_pstates != NULL && acpi_npstates != npstate) { 534 device_printf(dev, "Inconsistent # of P-States " 535 "cross Processor objects\n"); 536 AcpiOsFree(obj); 537 return ENXIO; 538 } 539 540 /* 541 * Create a temporary P-State table 542 */ 543 pstate = kmalloc(sizeof(*pstate) * npstate, M_TEMP, M_WAITOK); 544 for (i = 0, p = pstate; i < npstate; ++i, ++p) { 545 ACPI_OBJECT *pkg; 546 uint32_t *ptr[ACPI_PSS_PX_NENTRY] = { 547 &p->st_freq, &p->st_power, &p->st_xsit_lat, 548 &p->st_bm_lat, &p->st_cval, &p->st_sval 549 }; 550 int j; 551 552 pkg = &obj->Package.Elements[i]; 553 if (!ACPI_PKG_VALID(pkg, ACPI_PSS_PX_NENTRY)) { 554 device_printf(dev, "Invalud _PSS P%d\n", i); 555 AcpiOsFree(obj); 556 kfree(pstate, M_TEMP); 557 return ENXIO; 558 } 559 for (j = 0; j < ACPI_PSS_PX_NENTRY; ++j) { 560 if (acpi_PkgInt32(pkg, j, ptr[j]) != 0) { 561 device_printf(dev, "Can't extract " 562 "_PSS P%d %dth entry\n", i, j); 563 AcpiOsFree(obj); 564 kfree(pstate, M_TEMP); 565 return ENXIO; 566 } 567 } 568 } 569 570 /* Free _PSS */ 571 AcpiOsFree(obj); 572 573 if (acpi_pstates == NULL) { 574 /* 575 * If no P-State table is created yet, 576 * save the temporary one we just created. 577 */ 578 acpi_pstates = pstate; 579 acpi_npstates = npstate; 580 pstate = NULL; 581 582 if (bootverbose) { 583 for (i = 0; i < acpi_npstates; ++i) { 584 device_printf(dev, 585 "freq %u, pwr %u, xlat %u, blat %u, " 586 "cv %08x, sv %08x\n", 587 acpi_pstates[i].st_freq, 588 acpi_pstates[i].st_power, 589 acpi_pstates[i].st_xsit_lat, 590 acpi_pstates[i].st_bm_lat, 591 acpi_pstates[i].st_cval, 592 acpi_pstates[i].st_sval); 593 } 594 } 595 } else { 596 /* 597 * Make sure that P-State tables are same 598 * for all processors. 599 */ 600 if (memcmp(pstate, acpi_pstates, 601 sizeof(*pstate) * npstate) != 0) { 602 device_printf(dev, "Inconsistent _PSS " 603 "cross Processor objects\n"); 604 kfree(pstate, M_TEMP); 605 return ENXIO; 606 } 607 kfree(pstate, M_TEMP); 608 } 609 610 fetch_ppc: 611 /* By default, we start from P-State table's first entry */ 612 sc->pst_sstart = 0; 613 614 /* 615 * Adjust the usable first entry of P-State table, 616 * if there is _PPC object. 617 */ 618 buf.Pointer = NULL; 619 buf.Length = ACPI_ALLOCATE_BUFFER; 620 status = AcpiEvaluateObject(sc->pst_handle, "_PPC", NULL, &buf); 621 if (!ACPI_FAILURE(status)) { 622 obj = (ACPI_OBJECT *)buf.Pointer; 623 if (obj->Type == ACPI_TYPE_INTEGER) { 624 if (obj->Integer.Value >= acpi_npstates) { 625 device_printf(dev, "Invalid _PPC value\n"); 626 AcpiOsFree(obj); 627 return ENXIO; 628 } 629 sc->pst_sstart = obj->Integer.Value; 630 if (bootverbose) 631 device_printf(dev, "_PPC %d\n", sc->pst_sstart); 632 633 /* TODO: Install notifiy handler */ 634 } else { 635 device_printf(dev, "Invalid _PPC object\n"); 636 AcpiOsFree(obj); 637 return ENXIO; 638 } 639 640 /* Free _PPC */ 641 AcpiOsFree(obj); 642 } 643 644 sc->pst_state = sc->pst_sstart; 645 646 /* Link us with the domain */ 647 sc->pst_domain = dom; 648 LIST_INSERT_HEAD(&dom->pd_pstlist, sc, pst_link); 649 650 if (device_get_unit(dev) == 0) 651 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_pst_postattach, NULL); 652 653 return 0; 654 } 655 656 static struct acpi_pst_domain * 657 acpi_pst_domain_create_pkg(device_t dev, ACPI_OBJECT *obj) 658 { 659 struct acpi_pst_domain *dom; 660 uint32_t val, domain, coord, nproc; 661 662 if (!ACPI_PKG_VALID_EQ(obj, 5)) { 663 device_printf(dev, "Invalid _PSD package\n"); 664 return NULL; 665 } 666 667 /* NumberOfEntries */ 668 if (acpi_PkgInt32(obj, 0, &val) != 0 || val != 5) { 669 device_printf(dev, "Invalid _PSD NumberOfEntries\n"); 670 return NULL; 671 } 672 673 /* Revision */ 674 if (acpi_PkgInt32(obj, 1, &val) != 0 || val != 0) { 675 device_printf(dev, "Invalid _PSD Revision\n"); 676 return NULL; 677 } 678 679 if (acpi_PkgInt32(obj, 2, &domain) != 0 || 680 acpi_PkgInt32(obj, 3, &coord) != 0 || 681 acpi_PkgInt32(obj, 4, &nproc) != 0) { 682 device_printf(dev, "Can't extract _PSD package\n"); 683 return NULL; 684 } 685 686 if (!ACPI_PSD_COORD_VALID(coord)) { 687 device_printf(dev, "Invalid _PSD CoordType (%#x)\n", coord); 688 return NULL; 689 } 690 691 if (nproc > MAXCPU) { 692 /* 693 * If NumProcessors is greater than MAXCPU 694 * and domain's coordination is SWALL, then 695 * we will never be able to start all CPUs 696 * within this domain, and power state 697 * transition will never be completed, so we 698 * just bail out here. 699 */ 700 if (coord == ACPI_PSD_COORD_SWALL) { 701 device_printf(dev, "Unsupported _PSD NumProcessors " 702 "(%d)\n", nproc); 703 return NULL; 704 } 705 } else if (nproc == 0) { 706 device_printf(dev, "_PSD NumProcessors are zero\n"); 707 return NULL; 708 } 709 710 dom = acpi_pst_domain_find(domain); 711 if (dom != NULL) { 712 if (dom->pd_flags & ACPI_PSTDOM_FLAG_INT) { 713 device_printf(dev, "Mixed Integer _PSD and " 714 "Package _PSD\n"); 715 return NULL; 716 } 717 if (dom->pd_coord != coord) { 718 device_printf(dev, "Inconsistent _PSD coord " 719 "information cross Processor objects\n"); 720 return NULL; 721 } 722 if (dom->pd_nproc != nproc) { 723 device_printf(dev, "Inconsistent _PSD nproc " 724 "information cross Processor objects\n"); 725 /* 726 * Some stupid BIOSes will set wrong "# of processors", 727 * e.g. 1 for CPU w/ hyperthreading; Be lenient here. 728 */ 729 } 730 return dom; 731 } 732 733 dom = acpi_pst_domain_alloc(domain, coord, nproc); 734 if (bootverbose) { 735 device_printf(dev, "create pkg domain%u, coord %#x\n", 736 dom->pd_dom, dom->pd_coord); 737 } 738 739 return dom; 740 } 741 742 static struct acpi_pst_domain * 743 acpi_pst_domain_create_int(device_t dev, uint32_t domain) 744 { 745 struct acpi_pst_domain *dom; 746 747 dom = acpi_pst_domain_find(domain); 748 if (dom != NULL) { 749 if ((dom->pd_flags & ACPI_PSTDOM_FLAG_INT) == 0) { 750 device_printf(dev, "Mixed Package _PSD and " 751 "Integer _PSD\n"); 752 return NULL; 753 } 754 KKASSERT(dom->pd_coord == ACPI_PSD_COORD_SWALL); 755 756 dom->pd_nproc++; 757 return dom; 758 } 759 760 dom = acpi_pst_domain_alloc(domain, ACPI_PSD_COORD_SWALL, 1); 761 dom->pd_flags |= ACPI_PSTDOM_FLAG_INT; 762 763 if (bootverbose) 764 device_printf(dev, "create int domain%u\n", dom->pd_dom); 765 766 return dom; 767 } 768 769 static struct acpi_pst_domain * 770 acpi_pst_domain_find(uint32_t domain) 771 { 772 struct acpi_pst_domain *dom; 773 774 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) { 775 if (dom->pd_flags & ACPI_PSTDOM_FLAG_STUB) 776 continue; 777 if (dom->pd_dom == domain) 778 return dom; 779 } 780 return NULL; 781 } 782 783 static struct acpi_pst_domain * 784 acpi_pst_domain_alloc(uint32_t domain, uint32_t coord, uint32_t nproc) 785 { 786 struct acpi_pst_domain *dom; 787 788 dom = kmalloc(sizeof(*dom), M_DEVBUF, M_WAITOK | M_ZERO); 789 dom->pd_dom = domain; 790 dom->pd_coord = coord; 791 dom->pd_nproc = nproc; 792 dom->pd_state = 0; /* XXX */ 793 dom->pd_sstart = 0; /* XXX */ 794 LIST_INIT(&dom->pd_pstlist); 795 796 LIST_INSERT_HEAD(&acpi_pst_domains, dom, pd_link); 797 798 return dom; 799 } 800 801 static int 802 acpi_pst_domain_set_pstate(struct acpi_pst_domain *dom, int i) 803 { 804 const struct acpi_pstate *pstate; 805 struct acpi_pst_softc *sc; 806 int done, error; 807 808 KKASSERT(i >= 0 && i < acpi_npstates); 809 pstate = &acpi_pstates[i]; 810 811 done = 0; 812 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) { 813 if (!done) { 814 error = acpi_pst_set_pstate(sc, pstate); 815 if (error) { 816 device_printf(sc->pst_dev, "can't set " 817 "freq %d\n", pstate->st_freq); 818 /* XXX error cleanup? */ 819 } 820 if (dom->pd_coord == ACPI_PSD_COORD_SWANY) 821 done = 1; 822 } 823 sc->pst_state = i; 824 } 825 dom->pd_state = i; 826 827 return 0; 828 } 829 830 static int 831 acpi_pst_global_set_pstate(int i) 832 { 833 struct acpi_pst_domain *dom; 834 835 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) { 836 /* Skip dead domain */ 837 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD) 838 continue; 839 acpi_pst_domain_set_pstate(dom, i); 840 } 841 acpi_pst_global_state = i; 842 843 return 0; 844 } 845 846 static void 847 acpi_pst_postattach(void *arg __unused) 848 { 849 struct acpi_pst_domain *dom; 850 struct acpi_cpu_softc *cpu; 851 device_t *devices; 852 int i, ndevices, error, has_domain, sstate; 853 854 devices = NULL; 855 ndevices = 0; 856 error = devclass_get_devices(acpi_pst_devclass, &devices, &ndevices); 857 if (error) 858 return; 859 860 if (ndevices == 0) 861 return; 862 863 cpu = NULL; 864 for (i = 0; i < ndevices; ++i) { 865 cpu = device_get_softc(device_get_parent(devices[i])); 866 if (cpu->glob_sysctl_tree != NULL) 867 break; 868 } 869 kfree(devices, M_TEMP); 870 KKASSERT(cpu != NULL); 871 872 if (acpi_pst_md == NULL) 873 kprintf("ACPI: no P-State CPU driver\n"); 874 875 sstate = 0x7fffffff; 876 has_domain = 0; 877 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) { 878 struct acpi_pst_softc *sc; 879 char buf[32]; 880 881 /* 882 * Make sure that all processors belonging to this 883 * domain are located. 884 */ 885 i = 0; 886 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) 887 ++i; 888 if (i != dom->pd_nproc) { 889 KKASSERT(i < dom->pd_nproc); 890 891 kprintf("ACPI: domain%u misses processors, " 892 "should be %d, got %d\n", dom->pd_dom, 893 dom->pd_nproc, i); 894 if (dom->pd_coord == ACPI_PSD_COORD_SWALL) { 895 /* 896 * If this domain's coordination is 897 * SWALL and we don't see all of the 898 * member CPUs of this domain, then 899 * the P-State transition will never 900 * be completed, so just leave this 901 * domain out. 902 */ 903 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD; 904 continue; 905 } 906 dom->pd_nproc = i; 907 } 908 909 /* 910 * Validate P-State configurations for this domain 911 */ 912 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) { 913 error = acpi_pst_check_csr(sc); 914 if (error) 915 break; 916 917 error = acpi_pst_check_pstates(sc); 918 if (error) 919 break; 920 } 921 if (sc != NULL) { 922 kprintf("ACPI: domain%u P-State configuration " 923 "check failed\n", dom->pd_dom); 924 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD; 925 continue; 926 } 927 928 /* 929 * Do necssary P-State initialization 930 */ 931 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) { 932 error = acpi_pst_init(sc); 933 if (error) 934 break; 935 } 936 if (sc != NULL) { 937 kprintf("ACPI: domain%u P-State initialization " 938 "check failed\n", dom->pd_dom); 939 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD; 940 continue; 941 } 942 943 has_domain = 1; 944 945 ksnprintf(buf, sizeof(buf), "px_dom%u", dom->pd_dom); 946 947 sysctl_ctx_init(&dom->pd_sysctl_ctx); 948 dom->pd_sysctl_tree = 949 SYSCTL_ADD_NODE(&dom->pd_sysctl_ctx, 950 SYSCTL_CHILDREN(cpu->glob_sysctl_tree), 951 OID_AUTO, buf, CTLFLAG_RD, 0, 952 "P-State domain"); 953 if (dom->pd_sysctl_tree == NULL) { 954 kprintf("ACPI: Can't create sysctl tree for domain%u", 955 dom->pd_dom); 956 continue; 957 } 958 959 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx, 960 SYSCTL_CHILDREN(dom->pd_sysctl_tree), 961 OID_AUTO, "available", 962 CTLTYPE_STRING | CTLFLAG_RD, 963 dom, 0, acpi_pst_sysctl_freqs, "A", 964 "available frequencies"); 965 966 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx, 967 SYSCTL_CHILDREN(dom->pd_sysctl_tree), 968 OID_AUTO, "members", 969 CTLTYPE_STRING | CTLFLAG_RD, 970 dom, 0, acpi_pst_sysctl_members, "A", 971 "member cpus"); 972 973 if (acpi_pst_md != NULL && 974 acpi_pst_md->pmd_set_pstate != NULL) { 975 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx, 976 SYSCTL_CHILDREN(dom->pd_sysctl_tree), 977 OID_AUTO, "select", 978 CTLTYPE_UINT | CTLFLAG_RW, 979 dom, 0, acpi_pst_sysctl_select, 980 "IU", "select freq"); 981 } 982 983 if (dom->pd_state < sstate) 984 sstate = dom->pd_state; 985 } 986 987 if (has_domain && acpi_pst_md != NULL && 988 acpi_pst_md->pmd_set_pstate != NULL) { 989 SYSCTL_ADD_PROC(&cpu->glob_sysctl_ctx, 990 SYSCTL_CHILDREN(cpu->glob_sysctl_tree), 991 OID_AUTO, "px_global", 992 CTLTYPE_UINT | CTLFLAG_RW, 993 NULL, 0, acpi_pst_sysctl_global, 994 "IU", "select freq for all domains"); 995 996 acpi_pst_global_set_pstate(sstate); 997 } 998 } 999 1000 static int 1001 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS) 1002 { 1003 struct acpi_pst_domain *dom = arg1; 1004 int i, error; 1005 1006 error = 0; 1007 for (i = 0; i < acpi_npstates; ++i) { 1008 if (error == 0 && i) 1009 error = SYSCTL_OUT(req, " ", 1); 1010 if (error == 0) { 1011 const char *pat; 1012 char buf[32]; 1013 1014 if (i < dom->pd_sstart) 1015 pat = "(%u)"; 1016 else 1017 pat = "%u"; 1018 1019 ksnprintf(buf, sizeof(buf), pat, 1020 acpi_pstates[i].st_freq); 1021 error = SYSCTL_OUT(req, buf, strlen(buf)); 1022 } 1023 } 1024 return error; 1025 } 1026 1027 static int 1028 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS) 1029 { 1030 struct acpi_pst_domain *dom = arg1; 1031 struct acpi_pst_softc *sc; 1032 int loop, error; 1033 1034 loop = error = 0; 1035 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) { 1036 char buf[32]; 1037 1038 if (error == 0 && loop) 1039 error = SYSCTL_OUT(req, " ", 1); 1040 if (error == 0) { 1041 ksnprintf(buf, sizeof(buf), "cpu%d", sc->pst_cpuid); 1042 error = SYSCTL_OUT(req, buf, strlen(buf)); 1043 } 1044 1045 if (error == 0 && acpi_pst_md && acpi_pst_md->pmd_get_pstate) { 1046 const struct acpi_pstate *pstate; 1047 const char *str; 1048 1049 pstate = acpi_pst_get_pstate(sc); 1050 if (pstate == NULL) { 1051 str = "(*)"; 1052 } else { 1053 ksnprintf(buf, sizeof(buf), "(%d)", 1054 pstate->st_freq); 1055 str = buf; 1056 } 1057 error = SYSCTL_OUT(req, str, strlen(str)); 1058 } 1059 ++loop; 1060 } 1061 return error; 1062 } 1063 1064 static int 1065 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS) 1066 { 1067 struct acpi_pst_domain *dom = arg1; 1068 int error, i, freq; 1069 1070 KKASSERT(dom->pd_state >= 0 && dom->pd_state < acpi_npstates); 1071 1072 freq = acpi_pstates[dom->pd_state].st_freq; 1073 1074 error = sysctl_handle_int(oidp, &freq, 0, req); 1075 if (error || req->newptr == NULL) 1076 return error; 1077 1078 i = acpi_pst_freq2index(freq); 1079 if (i < 0) 1080 return EINVAL; 1081 1082 acpi_pst_domain_set_pstate(dom, i); 1083 return 0; 1084 } 1085 1086 static int 1087 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS) 1088 { 1089 int error, i, freq; 1090 1091 KKASSERT(acpi_pst_global_state >= 0 && 1092 acpi_pst_global_state < acpi_npstates); 1093 1094 freq = acpi_pstates[acpi_pst_global_state].st_freq; 1095 1096 error = sysctl_handle_int(oidp, &freq, 0, req); 1097 if (error || req->newptr == NULL) 1098 return error; 1099 1100 i = acpi_pst_freq2index(freq); 1101 if (i < 0) 1102 return EINVAL; 1103 1104 acpi_pst_global_set_pstate(i); 1105 1106 return 0; 1107 } 1108 1109 static void 1110 acpi_pst_check_csr_handler(netmsg_t msg) 1111 { 1112 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg; 1113 int error; 1114 1115 error = acpi_pst_md->pmd_check_csr(rmsg->ctrl, rmsg->status); 1116 lwkt_replymsg(&rmsg->base.lmsg, error); 1117 } 1118 1119 static int 1120 acpi_pst_check_csr(struct acpi_pst_softc *sc) 1121 { 1122 struct netmsg_acpi_pst msg; 1123 1124 if (acpi_pst_md == NULL) 1125 return 0; 1126 1127 netmsg_init(&msg.base, NULL, &curthread->td_msgport, 1128 MSGF_PRIORITY, acpi_pst_check_csr_handler); 1129 msg.ctrl = &sc->pst_creg; 1130 msg.status = &sc->pst_sreg; 1131 1132 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0); 1133 } 1134 1135 static void 1136 acpi_pst_check_pstates_handler(netmsg_t msg) 1137 { 1138 int error; 1139 1140 error = acpi_pst_md->pmd_check_pstates(acpi_pstates, acpi_npstates); 1141 lwkt_replymsg(&msg->lmsg, error); 1142 } 1143 1144 static int 1145 acpi_pst_check_pstates(struct acpi_pst_softc *sc) 1146 { 1147 struct netmsg_base msg; 1148 1149 if (acpi_pst_md == NULL) 1150 return 0; 1151 1152 netmsg_init(&msg, NULL, &curthread->td_msgport, 1153 MSGF_PRIORITY, acpi_pst_check_pstates_handler); 1154 1155 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.lmsg, 0); 1156 } 1157 1158 static void 1159 acpi_pst_init_handler(netmsg_t msg) 1160 { 1161 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg; 1162 int error; 1163 1164 error = acpi_pst_md->pmd_init(rmsg->ctrl, rmsg->status); 1165 lwkt_replymsg(&rmsg->base.lmsg, error); 1166 } 1167 1168 static int 1169 acpi_pst_init(struct acpi_pst_softc *sc) 1170 { 1171 struct netmsg_acpi_pst msg; 1172 1173 if (acpi_pst_md == NULL) 1174 return 0; 1175 1176 netmsg_init(&msg.base, NULL, &curthread->td_msgport, 1177 MSGF_PRIORITY, acpi_pst_init_handler); 1178 msg.ctrl = &sc->pst_creg; 1179 msg.status = &sc->pst_sreg; 1180 1181 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0); 1182 } 1183 1184 static void 1185 acpi_pst_set_pstate_handler(netmsg_t msg) 1186 { 1187 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg; 1188 int error; 1189 1190 error = acpi_pst_md->pmd_set_pstate(rmsg->ctrl, rmsg->status, 1191 rmsg->base.lmsg.u.ms_resultp); 1192 lwkt_replymsg(&rmsg->base.lmsg, error); 1193 } 1194 1195 static int 1196 acpi_pst_set_pstate(struct acpi_pst_softc *sc, const struct acpi_pstate *pstate) 1197 { 1198 struct netmsg_acpi_pst msg; 1199 1200 KKASSERT(acpi_pst_md != NULL); 1201 1202 netmsg_init(&msg.base, NULL, &curthread->td_msgport, 1203 MSGF_PRIORITY, acpi_pst_set_pstate_handler); 1204 msg.base.lmsg.u.ms_resultp = __DECONST(void *, pstate); 1205 msg.ctrl = &sc->pst_creg; 1206 msg.status = &sc->pst_sreg; 1207 1208 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0); 1209 } 1210 1211 static void 1212 acpi_pst_get_pstate_handler(netmsg_t msg) 1213 { 1214 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg; 1215 const struct acpi_pstate *pstate; 1216 1217 pstate = acpi_pst_md->pmd_get_pstate(rmsg->status, acpi_pstates, 1218 acpi_npstates); 1219 rmsg->base.lmsg.u.ms_resultp = __DECONST(void *, pstate); 1220 lwkt_replymsg(&rmsg->base.lmsg, 0); 1221 } 1222 1223 static const struct acpi_pstate * 1224 acpi_pst_get_pstate(struct acpi_pst_softc *sc) 1225 { 1226 struct netmsg_acpi_pst msg; 1227 1228 if (acpi_pst_md == NULL) 1229 return 0; 1230 1231 netmsg_init(&msg.base, NULL, &curthread->td_msgport, 1232 MSGF_PRIORITY, acpi_pst_get_pstate_handler); 1233 msg.status = &sc->pst_sreg; 1234 1235 lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0); 1236 return msg.base.lmsg.u.ms_resultp; 1237 } 1238 1239 static int 1240 acpi_pst_alloc_resource(device_t dev, ACPI_OBJECT *obj, int idx, 1241 struct acpi_pst_res *res) 1242 { 1243 struct acpi_pst_softc *sc = device_get_softc(dev); 1244 int error, type; 1245 1246 /* Save GAS */ 1247 error = acpi_PkgRawGas(obj, idx, &res->pr_gas); 1248 if (error) 1249 return error; 1250 1251 /* Allocate resource, if possible */ 1252 res->pr_rid = sc->pst_parent->cpu_next_rid; 1253 acpi_bus_alloc_gas(dev, &type, &res->pr_rid, &res->pr_gas, &res->pr_res, 0); 1254 if (res->pr_res != NULL) { 1255 sc->pst_parent->cpu_next_rid++; 1256 res->pr_bt = rman_get_bustag(res->pr_res); 1257 res->pr_bh = rman_get_bushandle(res->pr_res); 1258 } else { 1259 res->pr_rid = 0; 1260 } 1261 return 0; 1262 } 1263 1264 static void 1265 acpi_pst_domain_check_nproc(device_t dev, struct acpi_pst_domain *dom) 1266 { 1267 struct acpi_pst_softc *pst; 1268 int i; 1269 1270 i = 0; 1271 LIST_FOREACH(pst, &dom->pd_pstlist, pst_link) 1272 ++i; 1273 if (i == dom->pd_nproc) { 1274 /* 1275 * Some stupid BIOSes will set wrong "# of processors", 1276 * e.g. 1 for CPU w/ hyperthreading; Be lenient here. 1277 */ 1278 if (bootverbose) { 1279 device_printf(dev, "domain%u already contains %d " 1280 "P-States\n", dom->pd_dom, dom->pd_nproc); 1281 } 1282 dom->pd_nproc++; 1283 } 1284 KKASSERT(i < dom->pd_nproc); 1285 } 1286