2 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Sepherosa Ziehau <sepherosa@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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
37 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/queue.h>
43 #include <sys/sysctl.h>
44 #include <sys/msgport2.h>
45 #include <sys/cpu_topology.h>
47 #include <net/netisr2.h>
48 #include <net/netmsg2.h>
49 #include <net/if_var.h>
54 #include "acpi_cpu_pstate.h"
56 #define ACPI_NPSTATE_MAX 32
58 #define ACPI_PSS_PX_NENTRY 6
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)
68 struct acpi_pst_softc;
69 LIST_HEAD(acpi_pst_list, acpi_pst_softc);
71 struct netmsg_acpi_pst {
72 struct netmsg_base base;
73 const struct acpi_pst_res *ctrl;
74 const struct acpi_pst_res *status;
77 struct acpi_pst_domain {
81 LIST_ENTRY(acpi_pst_domain) pd_link;
86 struct acpi_pst_list pd_pstlist;
88 struct sysctl_ctx_list pd_sysctl_ctx;
89 struct sysctl_oid *pd_sysctl_tree;
91 LIST_HEAD(acpi_pst_domlist, acpi_pst_domain);
93 #define ACPI_PSTDOM_FLAG_STUB 0x1 /* stub domain, no _PSD */
94 #define ACPI_PSTDOM_FLAG_DEAD 0x2 /* domain can't be started */
95 #define ACPI_PSTDOM_FLAG_INT 0x4 /* domain created from Integer _PSD */
97 struct acpi_pst_softc {
99 struct acpi_cpu_softc *pst_parent;
100 struct acpi_pst_domain *pst_domain;
101 struct acpi_pst_res pst_creg;
102 struct acpi_pst_res pst_sreg;
107 ACPI_HANDLE pst_handle;
109 LIST_ENTRY(acpi_pst_softc) pst_link;
112 static int acpi_pst_probe(device_t dev);
113 static int acpi_pst_attach(device_t dev);
115 static void acpi_pst_postattach(void *);
116 static struct acpi_pst_domain *
117 acpi_pst_domain_create_int(device_t, uint32_t);
118 static struct acpi_pst_domain *
119 acpi_pst_domain_create_pkg(device_t, ACPI_OBJECT *);
120 static struct acpi_pst_domain *
121 acpi_pst_domain_find(uint32_t);
122 static struct acpi_pst_domain *
123 acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t);
124 static int acpi_pst_domain_set_pstate(struct acpi_pst_domain *, int);
125 static void acpi_pst_domain_check_nproc(device_t, struct acpi_pst_domain *);
126 static int acpi_pst_global_set_pstate(int);
128 static int acpi_pst_check_csr(struct acpi_pst_softc *);
129 static int acpi_pst_check_pstates(struct acpi_pst_softc *);
130 static int acpi_pst_init(struct acpi_pst_softc *);
131 static int acpi_pst_set_pstate(struct acpi_pst_softc *,
132 const struct acpi_pstate *);
133 static const struct acpi_pstate *
134 acpi_pst_get_pstate(struct acpi_pst_softc *);
135 static int acpi_pst_alloc_resource(device_t, ACPI_OBJECT *, int,
136 struct acpi_pst_res *);
138 static void acpi_pst_check_csr_handler(netmsg_t);
139 static void acpi_pst_check_pstates_handler(netmsg_t);
140 static void acpi_pst_init_handler(netmsg_t);
141 static void acpi_pst_set_pstate_handler(netmsg_t);
142 static void acpi_pst_get_pstate_handler(netmsg_t);
144 static int acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS);
145 static int acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS);
146 static int acpi_pst_sysctl_power(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);
151 static struct acpi_pst_domlist acpi_pst_domains =
152 LIST_HEAD_INITIALIZER(acpi_pst_domains);
153 static int acpi_pst_domain_id;
155 static int acpi_pst_global_state;
157 static int acpi_pstate_start = -1;
158 static int acpi_pstate_count;
159 static int acpi_npstates;
160 static struct acpi_pstate *acpi_pstates;
162 static const struct acpi_pst_md *acpi_pst_md;
164 static int acpi_pst_pdl = -1;
165 TUNABLE_INT("hw.acpi.cpu.pst.pdl", &acpi_pst_pdl);
167 static int acpi_pst_ht_reuse_domain = 1;
168 TUNABLE_INT("hw.acpi.cpu.pst.ht_reuse_domain", &acpi_pst_ht_reuse_domain);
170 static int acpi_pst_force_pkg_domain = 0;
171 TUNABLE_INT("hw.acpi.cpu.pst.force_pkg_domain", &acpi_pst_force_pkg_domain);
174 * Force CPU package power domain for Intel CPUs.
176 * As of this write (14 July 2015), all Intel CPUs only have CPU package
179 static int acpi_pst_intel_pkg_domain = 1;
180 TUNABLE_INT("hw.acpi.cpu.pst.intel_pkg_domain", &acpi_pst_intel_pkg_domain);
182 static device_method_t acpi_pst_methods[] = {
183 /* Device interface */
184 DEVMETHOD(device_probe, acpi_pst_probe),
185 DEVMETHOD(device_attach, acpi_pst_attach),
186 DEVMETHOD(device_detach, bus_generic_detach),
187 DEVMETHOD(device_shutdown, bus_generic_shutdown),
188 DEVMETHOD(device_suspend, bus_generic_suspend),
189 DEVMETHOD(device_resume, bus_generic_resume),
192 DEVMETHOD(bus_add_child, bus_generic_add_child),
193 DEVMETHOD(bus_print_child, bus_generic_print_child),
194 DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
195 DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
196 DEVMETHOD(bus_get_resource_list, bus_generic_get_resource_list),
197 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
198 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
199 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
200 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
201 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
202 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
203 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
204 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
205 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
210 static driver_t acpi_pst_driver = {
213 sizeof(struct acpi_pst_softc)
216 static devclass_t acpi_pst_devclass;
217 DRIVER_MODULE(cpu_pst, cpu, acpi_pst_driver, acpi_pst_devclass, NULL, NULL);
218 MODULE_DEPEND(cpu_pst, acpi, 1, 1, 1);
221 acpi_pst_freq2index(int freq)
225 for (i = 0; i < acpi_npstates; ++i) {
226 if (acpi_pstates[i].st_freq == freq)
233 acpi_pst_probe(device_t dev)
240 if (acpi_disabled("cpu_pst") ||
241 acpi_get_type(dev) != ACPI_TYPE_PROCESSOR)
244 if (acpi_pst_md == NULL)
245 acpi_pst_md = acpi_pst_md_probe();
247 handle = acpi_get_handle(dev);
253 * Some BIOSes do not expose _PCT for the second thread of
254 * CPU cores. In this case, _PSD should be enough to get the
255 * P-state of the second thread working, since it must have
256 * the same _PCT and _PSS as the first thread in the same
260 buf.Length = ACPI_ALLOCATE_BUFFER;
261 status = AcpiEvaluateObject(handle, "_PSD", NULL, &buf);
262 if (!ACPI_FAILURE(status)) {
263 AcpiOsFree((ACPI_OBJECT *)buf.Pointer);
271 buf.Length = ACPI_ALLOCATE_BUFFER;
272 status = AcpiEvaluateObject(handle, "_PCT", NULL, &buf);
273 if (ACPI_FAILURE(status)) {
275 device_printf(dev, "Can't get _PCT package - %s\n",
276 AcpiFormatException(status));
281 obj = (ACPI_OBJECT *)buf.Pointer;
282 if (!ACPI_PKG_VALID_EQ(obj, 2)) {
283 device_printf(dev, "Invalid _PCT package\n");
293 buf.Length = ACPI_ALLOCATE_BUFFER;
294 status = AcpiEvaluateObject(handle, "_PSS", NULL, &buf);
295 if (ACPI_FAILURE(status)) {
296 device_printf(dev, "Can't get _PSS package - %s\n",
297 AcpiFormatException(status));
301 obj = (ACPI_OBJECT *)buf.Pointer;
302 if (!ACPI_PKG_VALID(obj, 1)) {
303 device_printf(dev, "Invalid _PSS package\n");
310 device_set_desc(dev, "ACPI CPU P-State");
315 acpi_pst_attach(device_t dev)
317 struct acpi_pst_softc *sc = device_get_softc(dev);
318 struct acpi_pst_domain *dom = NULL;
322 struct acpi_pstate *pstate, *p;
323 int i, npstate, error, sstart, scount;
326 sc->pst_parent = device_get_softc(device_get_parent(dev));
327 sc->pst_handle = acpi_get_handle(dev);
328 sc->pst_cpuid = acpi_get_magic(dev);
331 * If there is a _PSD, then we create procossor domain
332 * accordingly. If there is no _PSD, we just fake a
333 * default processor domain0.
336 buf.Length = ACPI_ALLOCATE_BUFFER;
337 status = AcpiEvaluateObject(sc->pst_handle, "_PSD", NULL, &buf);
338 if (!ACPI_FAILURE(status)) {
339 obj = (ACPI_OBJECT *)buf.Pointer;
341 if (acpi_pst_domain_id > 0) {
342 device_printf(dev, "Missing _PSD for certain CPUs\n");
346 acpi_pst_domain_id = -1;
348 if (ACPI_PKG_VALID_EQ(obj, 1)) {
349 dom = acpi_pst_domain_create_pkg(dev,
350 &obj->Package.Elements[0]);
356 if (obj->Type != ACPI_TYPE_INTEGER) {
358 "Invalid _PSD package, Type 0x%x\n",
363 device_printf(dev, "Integer _PSD %ju\n",
364 (uintmax_t)obj->Integer.Value);
365 dom = acpi_pst_domain_create_int(dev,
375 AcpiOsFree(buf.Pointer);
377 if (acpi_pst_domain_id < 0) {
378 device_printf(dev, "Missing _PSD for cpu%d\n",
384 * Create a stub one processor domain for each processor
386 dom = acpi_pst_domain_alloc(acpi_pst_domain_id,
387 ACPI_PSD_COORD_SWANY, 1);
388 dom->pd_flags |= ACPI_PSTDOM_FLAG_STUB;
390 ++acpi_pst_domain_id;
393 /* Make sure that adding us will not overflow our domain */
394 acpi_pst_domain_check_nproc(dev, dom);
397 * Get control/status registers from _PCT
400 buf.Length = ACPI_ALLOCATE_BUFFER;
401 status = AcpiEvaluateObject(sc->pst_handle, "_PCT", NULL, &buf);
402 if (ACPI_FAILURE(status)) {
403 struct acpi_pst_softc *pst;
406 * No _PCT. See the comment in acpi_pst_probe() near
409 * Use control/status registers of another CPU in the
410 * same domain, or in the same core, if the type of
411 * these registers are "Fixed Hardware", e.g. on most
412 * of the model Intel CPUs.
414 pst = LIST_FIRST(&dom->pd_pstlist);
418 mask = get_cpumask_from_level(sc->pst_cpuid,
420 if (CPUMASK_TESTNZERO(mask)) {
421 struct acpi_pst_domain *dom1;
423 LIST_FOREACH(dom1, &acpi_pst_domains, pd_link) {
424 LIST_FOREACH(pst, &dom1->pd_pstlist,
426 if (CPUMASK_TESTBIT(mask,
433 if (pst != NULL && acpi_pst_ht_reuse_domain) {
435 * Use the same domain for CPUs in the
438 device_printf(dev, "Destroy domain%u, "
440 dom->pd_dom, dom1->pd_dom);
441 LIST_REMOVE(dom, pd_link);
442 kfree(dom, M_DEVBUF);
445 * Make sure that adding us will not
446 * overflow the domain containing
447 * siblings in the same core.
449 acpi_pst_domain_check_nproc(dev, dom);
454 pst->pst_creg.pr_res == NULL &&
455 pst->pst_creg.pr_rid == 0 &&
456 pst->pst_creg.pr_gas.SpaceId ==
457 ACPI_ADR_SPACE_FIXED_HARDWARE &&
458 pst->pst_sreg.pr_res == NULL &&
459 pst->pst_sreg.pr_rid == 0 &&
460 pst->pst_sreg.pr_gas.SpaceId ==
461 ACPI_ADR_SPACE_FIXED_HARDWARE) {
462 sc->pst_creg = pst->pst_creg;
463 sc->pst_sreg = pst->pst_sreg;
465 "No _PCT; reuse %s control/status regs\n",
466 device_get_nameunit(pst->pst_dev));
469 device_printf(dev, "Can't get _PCT package - %s\n",
470 AcpiFormatException(status));
474 obj = (ACPI_OBJECT *)buf.Pointer;
475 if (!ACPI_PKG_VALID_EQ(obj, 2)) {
476 device_printf(dev, "Invalid _PCT package\n");
481 /* Save and try allocating control register */
482 error = acpi_pst_alloc_resource(dev, obj, 0, &sc->pst_creg);
488 device_printf(dev, "control reg %d %jx\n",
489 sc->pst_creg.pr_gas.SpaceId,
490 (uintmax_t)sc->pst_creg.pr_gas.Address);
493 /* Save and try allocating status register */
494 error = acpi_pst_alloc_resource(dev, obj, 1, &sc->pst_sreg);
500 device_printf(dev, "status reg %d %jx\n",
501 sc->pst_sreg.pr_gas.SpaceId,
502 (uintmax_t)sc->pst_sreg.pr_gas.Address);
510 * Create P-State table according to _PSS
513 buf.Length = ACPI_ALLOCATE_BUFFER;
514 status = AcpiEvaluateObject(sc->pst_handle, "_PSS", NULL, &buf);
515 if (ACPI_FAILURE(status)) {
517 * No _PSS. See the comment in acpi_pst_probe() near
520 * Assume _PSS are same across all CPUs; well, they
521 * should/have to be so.
523 if (acpi_npstates > 0 && acpi_pstates != NULL) {
524 device_printf(dev, "No _PSS\n");
527 device_printf(dev, "Can't get _PSS package - %s\n",
528 AcpiFormatException(status));
532 obj = (ACPI_OBJECT *)buf.Pointer;
533 if (!ACPI_PKG_VALID(obj, 1)) {
534 device_printf(dev, "Invalid _PSS package\n");
539 /* Don't create too many P-States */
540 npstate = obj->Package.Count;
541 if (npstate > ACPI_NPSTATE_MAX) {
542 device_printf(dev, "Too many P-States, %d->%d\n",
543 npstate, ACPI_NPSTATE_MAX);
544 npstate = ACPI_NPSTATE_MAX;
548 * If we have already created P-State table,
549 * we must make sure that number of entries
552 if (acpi_pstates != NULL && acpi_npstates != npstate) {
553 device_printf(dev, "Inconsistent # of P-States "
554 "cross Processor objects\n");
560 * Create a temporary P-State table
562 pstate = kmalloc(sizeof(*pstate) * npstate, M_TEMP, M_WAITOK);
563 for (i = 0, p = pstate; i < npstate; ++i, ++p) {
565 uint32_t *ptr[ACPI_PSS_PX_NENTRY] = {
566 &p->st_freq, &p->st_power, &p->st_xsit_lat,
567 &p->st_bm_lat, &p->st_cval, &p->st_sval
571 pkg = &obj->Package.Elements[i];
572 if (!ACPI_PKG_VALID(pkg, ACPI_PSS_PX_NENTRY)) {
573 device_printf(dev, "Invalud _PSS P%d\n", i);
575 kfree(pstate, M_TEMP);
578 for (j = 0; j < ACPI_PSS_PX_NENTRY; ++j) {
579 if (acpi_PkgInt32(pkg, j, ptr[j]) != 0) {
580 device_printf(dev, "Can't extract "
581 "_PSS P%d %dth entry\n", i, j);
583 kfree(pstate, M_TEMP);
592 if (acpi_pstates == NULL) {
594 * If no P-State table is created yet,
595 * save the temporary one we just created.
597 acpi_pstates = pstate;
598 acpi_npstates = npstate;
602 for (i = 0; i < acpi_npstates; ++i) {
604 "freq %u, pwr %u, xlat %u, blat %u, "
605 "cv %08x, sv %08x\n",
606 acpi_pstates[i].st_freq,
607 acpi_pstates[i].st_power,
608 acpi_pstates[i].st_xsit_lat,
609 acpi_pstates[i].st_bm_lat,
610 acpi_pstates[i].st_cval,
611 acpi_pstates[i].st_sval);
616 * Make sure that P-State tables are same
617 * for all processors.
619 if (memcmp(pstate, acpi_pstates,
620 sizeof(*pstate) * npstate) != 0) {
621 device_printf(dev, "Inconsistent _PSS "
622 "cross Processor objects\n");
625 * Some BIOSes create different P-State tables;
626 * just trust the one from the BSP and move on.
628 kfree(pstate, M_TEMP);
632 kfree(pstate, M_TEMP);
636 /* By default, we start from P-State table's first entry */
640 * Adjust the usable first entry of P-State table,
641 * if there is _PPC object.
644 buf.Length = ACPI_ALLOCATE_BUFFER;
645 status = AcpiEvaluateObject(sc->pst_handle, "_PPC", NULL, &buf);
646 if (!ACPI_FAILURE(status)) {
647 ACPI_OBJECT_LIST arglist;
650 obj = (ACPI_OBJECT *)buf.Pointer;
651 if (obj->Type == ACPI_TYPE_INTEGER) {
652 if (obj->Integer.Value >= acpi_npstates) {
653 device_printf(dev, "Invalid _PPC value\n");
657 sstart = obj->Integer.Value;
659 device_printf(dev, "_PPC %d\n", sstart);
661 /* TODO: Install notifiy handler */
663 device_printf(dev, "Invalid _PPC object\n");
671 /* _PPC has been successfully processed */
672 arglist.Pointer = arg;
674 arg[0].Type = ACPI_TYPE_INTEGER;
675 arg[0].Integer.Value = 0x80;
676 arg[1].Type = ACPI_TYPE_INTEGER;
677 arg[1].Integer.Value = 0;
678 AcpiEvaluateObject(sc->pst_handle, "_OST", &arglist, NULL);
680 if (acpi_pstate_start < 0) {
681 acpi_pstate_start = sstart;
682 } else if (acpi_pstate_start != sstart) {
683 device_printf(dev, "_PPC mismatch, was %d, now %d\n",
684 acpi_pstate_start, sstart);
685 if (acpi_pstate_start < sstart) {
686 device_printf(dev, "_PPC %d -> %d\n",
687 acpi_pstate_start, sstart);
688 acpi_pstate_start = sstart;
693 * By default, we assume number of usable P-States is same as
694 * number of P-States.
696 scount = acpi_npstates;
699 * Allow users to override or set _PDL
701 if (acpi_pst_pdl >= 0) {
702 if (acpi_pst_pdl < acpi_npstates) {
704 device_printf(dev, "_PDL override %d\n",
707 scount = acpi_pst_pdl + 1;
710 device_printf(dev, "Invalid _PDL override %d, "
711 "must be less than %d\n", acpi_pst_pdl,
717 * Adjust the number of usable entries in P-State table,
718 * if there is _PDL object.
721 buf.Length = ACPI_ALLOCATE_BUFFER;
722 status = AcpiEvaluateObject(sc->pst_handle, "_PDL", NULL, &buf);
723 if (!ACPI_FAILURE(status)) {
724 obj = (ACPI_OBJECT *)buf.Pointer;
725 if (obj->Type == ACPI_TYPE_INTEGER) {
726 if (obj->Integer.Value >= acpi_npstates) {
727 device_printf(dev, "Invalid _PDL value\n");
731 if (obj->Integer.Value >= acpi_pstate_start) {
732 scount = obj->Integer.Value + 1;
734 device_printf(dev, "_PDL %d\n", scount);
736 /* Prefer _PPC as stated in ACPI 5.1 8.4.4.6 */
737 device_printf(dev, "conflict _PDL %ju and "
739 (uintmax_t)obj->Integer.Value,
743 /* TODO: Install notifiy handler */
745 device_printf(dev, "Invalid _PDL object\n");
754 if (acpi_pstate_count == 0) {
755 acpi_pstate_count = scount;
756 } else if (acpi_pstate_count != scount) {
757 device_printf(dev, "_PDL mismatch, was %d, now %d\n",
758 acpi_pstate_count, scount);
759 if (acpi_pstate_count > scount) {
760 device_printf(dev, "_PDL %d -> %d\n",
761 acpi_pstate_count, scount);
762 acpi_pstate_count = scount;
767 * Some CPUs only have package P-states, but some BIOSes put each
768 * hyperthread to its own P-state domain; allow user to override.
770 if (LIST_EMPTY(&dom->pd_pstlist) &&
771 (acpi_pst_force_pkg_domain ||
772 (cpu_vendor_id == CPU_VENDOR_INTEL &&
773 acpi_pst_intel_pkg_domain))) {
776 mask = get_cpumask_from_level(sc->pst_cpuid, CHIP_LEVEL);
777 if (CPUMASK_TESTNZERO(mask)) {
778 struct acpi_pst_softc *pst = NULL;
779 struct acpi_pst_domain *dom1;
781 LIST_FOREACH(dom1, &acpi_pst_domains, pd_link) {
782 LIST_FOREACH(pst, &dom1->pd_pstlist,
784 if (CPUMASK_TESTBIT(mask,
792 memcmp(&pst->pst_creg, &sc->pst_creg,
793 sizeof(sc->pst_creg)) == 0 &&
794 memcmp(&pst->pst_sreg, &sc->pst_sreg,
795 sizeof(sc->pst_sreg)) == 0) {
797 * Use the same domain for CPUs in the
800 device_printf(dev, "Destroy domain%u, "
801 "force pkg domain%u\n",
802 dom->pd_dom, dom1->pd_dom);
803 LIST_REMOVE(dom, pd_link);
804 kfree(dom, M_DEVBUF);
807 * Make sure that adding us will not
808 * overflow the domain containing
809 * siblings in the same package.
811 acpi_pst_domain_check_nproc(dev, dom);
816 /* Link us with the domain */
817 sc->pst_domain = dom;
818 LIST_INSERT_HEAD(&dom->pd_pstlist, sc, pst_link);
820 if (device_get_unit(dev) == 0)
821 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_pst_postattach, NULL);
826 static struct acpi_pst_domain *
827 acpi_pst_domain_create_pkg(device_t dev, ACPI_OBJECT *obj)
829 struct acpi_pst_domain *dom;
830 uint32_t val, domain, coord, nproc;
832 if (!ACPI_PKG_VALID_EQ(obj, 5)) {
833 device_printf(dev, "Invalid _PSD package\n");
837 /* NumberOfEntries */
838 if (acpi_PkgInt32(obj, 0, &val) != 0 || val != 5) {
839 device_printf(dev, "Invalid _PSD NumberOfEntries\n");
844 if (acpi_PkgInt32(obj, 1, &val) != 0 || val != 0) {
845 device_printf(dev, "Invalid _PSD Revision\n");
849 if (acpi_PkgInt32(obj, 2, &domain) != 0 ||
850 acpi_PkgInt32(obj, 3, &coord) != 0 ||
851 acpi_PkgInt32(obj, 4, &nproc) != 0) {
852 device_printf(dev, "Can't extract _PSD package\n");
856 if (!ACPI_PSD_COORD_VALID(coord)) {
857 device_printf(dev, "Invalid _PSD CoordType (%#x)\n", coord);
861 if (nproc > MAXCPU) {
863 * If NumProcessors is greater than MAXCPU
864 * and domain's coordination is SWALL, then
865 * we will never be able to start all CPUs
866 * within this domain, and power state
867 * transition will never be completed, so we
868 * just bail out here.
870 if (coord == ACPI_PSD_COORD_SWALL) {
871 device_printf(dev, "Unsupported _PSD NumProcessors "
875 } else if (nproc == 0) {
876 device_printf(dev, "_PSD NumProcessors are zero\n");
880 dom = acpi_pst_domain_find(domain);
882 if (dom->pd_flags & ACPI_PSTDOM_FLAG_INT) {
883 device_printf(dev, "Mixed Integer _PSD and "
887 if (dom->pd_coord != coord) {
888 device_printf(dev, "Inconsistent _PSD coord "
889 "information cross Processor objects\n");
892 if (dom->pd_nproc != nproc) {
893 device_printf(dev, "Inconsistent _PSD nproc "
894 "information cross Processor objects\n");
896 * Some stupid BIOSes will set wrong "# of processors",
897 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
903 dom = acpi_pst_domain_alloc(domain, coord, nproc);
905 device_printf(dev, "create pkg domain%u, coord %#x\n",
906 dom->pd_dom, dom->pd_coord);
912 static struct acpi_pst_domain *
913 acpi_pst_domain_create_int(device_t dev, uint32_t domain)
915 struct acpi_pst_domain *dom;
917 dom = acpi_pst_domain_find(domain);
919 if ((dom->pd_flags & ACPI_PSTDOM_FLAG_INT) == 0) {
920 device_printf(dev, "Mixed Package _PSD and "
924 KKASSERT(dom->pd_coord == ACPI_PSD_COORD_SWALL);
930 dom = acpi_pst_domain_alloc(domain, ACPI_PSD_COORD_SWALL, 1);
931 dom->pd_flags |= ACPI_PSTDOM_FLAG_INT;
934 device_printf(dev, "create int domain%u\n", dom->pd_dom);
939 static struct acpi_pst_domain *
940 acpi_pst_domain_find(uint32_t domain)
942 struct acpi_pst_domain *dom;
944 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
945 if (dom->pd_flags & ACPI_PSTDOM_FLAG_STUB)
947 if (dom->pd_dom == domain)
953 static struct acpi_pst_domain *
954 acpi_pst_domain_alloc(uint32_t domain, uint32_t coord, uint32_t nproc)
956 struct acpi_pst_domain *dom;
958 dom = kmalloc(sizeof(*dom), M_DEVBUF, M_WAITOK | M_ZERO);
959 dom->pd_dom = domain;
960 dom->pd_coord = coord;
961 dom->pd_nproc = nproc;
962 LIST_INIT(&dom->pd_pstlist);
964 LIST_INSERT_HEAD(&acpi_pst_domains, dom, pd_link);
970 acpi_pst_domain_set_pstate(struct acpi_pst_domain *dom, int i)
972 const struct acpi_pstate *pstate;
973 struct acpi_pst_softc *sc;
976 KKASSERT(i >= 0 && i < acpi_npstates);
977 pstate = &acpi_pstates[i];
980 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
982 error = acpi_pst_set_pstate(sc, pstate);
984 device_printf(sc->pst_dev, "can't set "
985 "freq %d\n", pstate->st_freq);
986 /* XXX error cleanup? */
988 if (dom->pd_coord == ACPI_PSD_COORD_SWANY)
999 acpi_pst_global_set_pstate(int i)
1001 struct acpi_pst_domain *dom;
1003 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
1004 /* Skip dead domain */
1005 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
1007 acpi_pst_domain_set_pstate(dom, i);
1009 acpi_pst_global_state = i;
1015 acpi_pst_postattach(void *arg __unused)
1017 struct acpi_pst_domain *dom;
1018 struct acpi_cpu_softc *cpu;
1020 int i, ndevices, error, has_domain;
1024 error = devclass_get_devices(acpi_pst_devclass, &devices, &ndevices);
1032 for (i = 0; i < ndevices; ++i) {
1033 cpu = device_get_softc(device_get_parent(devices[i]));
1034 if (cpu->glob_sysctl_tree != NULL)
1037 kfree(devices, M_TEMP);
1038 KKASSERT(cpu != NULL);
1040 if (acpi_pst_md == NULL)
1041 kprintf("ACPI: no P-State CPU driver\n");
1044 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
1045 struct acpi_pst_softc *sc;
1048 dom->pd_state = acpi_pstate_start;
1051 * Make sure that all processors belonging to this
1052 * domain are located.
1055 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1056 sc->pst_state = acpi_pstate_start;
1059 if (i != dom->pd_nproc) {
1060 KKASSERT(i < dom->pd_nproc);
1062 kprintf("ACPI: domain%u misses processors, "
1063 "should be %d, got %d\n", dom->pd_dom,
1065 if (dom->pd_coord == ACPI_PSD_COORD_SWALL) {
1067 * If this domain's coordination is
1068 * SWALL and we don't see all of the
1069 * member CPUs of this domain, then
1070 * the P-State transition will never
1071 * be completed, so just leave this
1074 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1081 * Validate P-State configurations for this domain
1083 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1084 error = acpi_pst_check_csr(sc);
1088 error = acpi_pst_check_pstates(sc);
1093 kprintf("ACPI: domain%u P-State configuration "
1094 "check failed\n", dom->pd_dom);
1095 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1100 * Do necssary P-State initialization
1102 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1103 error = acpi_pst_init(sc);
1108 kprintf("ACPI: domain%u P-State initialization "
1109 "check failed\n", dom->pd_dom);
1110 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1116 ksnprintf(buf, sizeof(buf), "px_dom%u", dom->pd_dom);
1118 sysctl_ctx_init(&dom->pd_sysctl_ctx);
1119 dom->pd_sysctl_tree =
1120 SYSCTL_ADD_NODE(&dom->pd_sysctl_ctx,
1121 SYSCTL_CHILDREN(cpu->glob_sysctl_tree),
1122 OID_AUTO, buf, CTLFLAG_RD, 0,
1124 if (dom->pd_sysctl_tree == NULL) {
1125 kprintf("ACPI: Can't create sysctl tree for domain%u",
1130 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1131 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1132 OID_AUTO, "available",
1133 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP,
1134 dom, 0, acpi_pst_sysctl_freqs, "A",
1135 "available frequencies");
1137 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1138 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1140 CTLTYPE_OPAQUE | CTLFLAG_RD,
1141 dom, 0, acpi_pst_sysctl_freqs_bin, "IU",
1142 "available frequencies");
1144 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1145 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1147 CTLTYPE_OPAQUE | CTLFLAG_RD,
1148 dom, 0, acpi_pst_sysctl_power, "IU",
1149 "power of available frequencies");
1151 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1152 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1153 OID_AUTO, "members",
1154 CTLTYPE_STRING | CTLFLAG_RD,
1155 dom, 0, acpi_pst_sysctl_members, "A",
1158 if (acpi_pst_md != NULL &&
1159 acpi_pst_md->pmd_set_pstate != NULL) {
1160 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1161 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1163 CTLTYPE_UINT | CTLFLAG_RW,
1164 dom, 0, acpi_pst_sysctl_select,
1165 "IU", "select freq");
1169 if (has_domain && acpi_pst_md != NULL &&
1170 acpi_pst_md->pmd_set_pstate != NULL) {
1171 SYSCTL_ADD_PROC(&cpu->glob_sysctl_ctx,
1172 SYSCTL_CHILDREN(cpu->glob_sysctl_tree),
1173 OID_AUTO, "px_global",
1174 CTLTYPE_UINT | CTLFLAG_RW,
1175 NULL, 0, acpi_pst_sysctl_global,
1176 "IU", "select freq for all domains");
1178 acpi_pst_global_set_pstate(acpi_pstate_start);
1183 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS)
1188 for (i = 0; i < acpi_npstates; ++i) {
1189 if (error == 0 && i)
1190 error = SYSCTL_OUT(req, " ", 1);
1195 if (i < acpi_pstate_start || i >= acpi_pstate_count)
1200 ksnprintf(buf, sizeof(buf), pat,
1201 acpi_pstates[i].st_freq);
1202 error = SYSCTL_OUT(req, buf, strlen(buf));
1209 acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS)
1211 uint32_t freqs[ACPI_NPSTATE_MAX];
1214 cnt = acpi_pstate_count - acpi_pstate_start;
1215 for (i = 0; i < cnt; ++i)
1216 freqs[i] = acpi_pstates[acpi_pstate_start + i].st_freq;
1218 return sysctl_handle_opaque(oidp, freqs, cnt * sizeof(freqs[0]), req);
1222 acpi_pst_sysctl_power(SYSCTL_HANDLER_ARGS)
1224 uint32_t power[ACPI_NPSTATE_MAX];
1227 cnt = acpi_pstate_count - acpi_pstate_start;
1228 for (i = 0; i < cnt; ++i)
1229 power[i] = acpi_pstates[acpi_pstate_start + i].st_power;
1231 return sysctl_handle_opaque(oidp, power, cnt * sizeof(power[0]), req);
1235 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS)
1237 struct acpi_pst_domain *dom = arg1;
1238 struct acpi_pst_softc *sc;
1242 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1245 if (error == 0 && loop)
1246 error = SYSCTL_OUT(req, " ", 1);
1248 ksnprintf(buf, sizeof(buf), "cpu%d", sc->pst_cpuid);
1249 error = SYSCTL_OUT(req, buf, strlen(buf));
1252 if (error == 0 && acpi_pst_md && acpi_pst_md->pmd_get_pstate) {
1253 const struct acpi_pstate *pstate;
1256 pstate = acpi_pst_get_pstate(sc);
1257 if (pstate == NULL) {
1260 ksnprintf(buf, sizeof(buf), "(%d)",
1264 error = SYSCTL_OUT(req, str, strlen(str));
1272 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS)
1274 struct acpi_pst_domain *dom = arg1;
1277 KKASSERT(dom->pd_state >= 0 && dom->pd_state < acpi_npstates);
1279 freq = acpi_pstates[dom->pd_state].st_freq;
1281 error = sysctl_handle_int(oidp, &freq, 0, req);
1282 if (error || req->newptr == NULL)
1285 i = acpi_pst_freq2index(freq);
1289 acpi_pst_domain_set_pstate(dom, i);
1294 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS)
1298 KKASSERT(acpi_pst_global_state >= 0 &&
1299 acpi_pst_global_state < acpi_npstates);
1301 freq = acpi_pstates[acpi_pst_global_state].st_freq;
1303 error = sysctl_handle_int(oidp, &freq, 0, req);
1304 if (error || req->newptr == NULL)
1307 i = acpi_pst_freq2index(freq);
1311 acpi_pst_global_set_pstate(i);
1317 acpi_pst_check_csr_handler(netmsg_t msg)
1319 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1322 error = acpi_pst_md->pmd_check_csr(rmsg->ctrl, rmsg->status);
1323 lwkt_replymsg(&rmsg->base.lmsg, error);
1327 acpi_pst_check_csr(struct acpi_pst_softc *sc)
1329 struct netmsg_acpi_pst msg;
1331 if (acpi_pst_md == NULL)
1334 netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1335 MSGF_PRIORITY, acpi_pst_check_csr_handler);
1336 msg.ctrl = &sc->pst_creg;
1337 msg.status = &sc->pst_sreg;
1339 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1343 acpi_pst_check_pstates_handler(netmsg_t msg)
1347 error = acpi_pst_md->pmd_check_pstates(acpi_pstates, acpi_npstates);
1348 lwkt_replymsg(&msg->lmsg, error);
1352 acpi_pst_check_pstates(struct acpi_pst_softc *sc)
1354 struct netmsg_base msg;
1356 if (acpi_pst_md == NULL)
1359 netmsg_init(&msg, NULL, &curthread->td_msgport,
1360 MSGF_PRIORITY, acpi_pst_check_pstates_handler);
1362 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.lmsg, 0);
1366 acpi_pst_init_handler(netmsg_t msg)
1368 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1371 error = acpi_pst_md->pmd_init(rmsg->ctrl, rmsg->status);
1372 lwkt_replymsg(&rmsg->base.lmsg, error);
1376 acpi_pst_init(struct acpi_pst_softc *sc)
1378 struct netmsg_acpi_pst msg;
1380 if (acpi_pst_md == NULL)
1383 netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1384 MSGF_PRIORITY, acpi_pst_init_handler);
1385 msg.ctrl = &sc->pst_creg;
1386 msg.status = &sc->pst_sreg;
1388 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1392 acpi_pst_set_pstate_handler(netmsg_t msg)
1394 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1397 error = acpi_pst_md->pmd_set_pstate(rmsg->ctrl, rmsg->status,
1398 rmsg->base.lmsg.u.ms_resultp);
1399 lwkt_replymsg(&rmsg->base.lmsg, error);
1403 acpi_pst_set_pstate(struct acpi_pst_softc *sc, const struct acpi_pstate *pstate)
1405 struct netmsg_acpi_pst msg;
1407 KKASSERT(acpi_pst_md != NULL);
1409 netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1410 MSGF_PRIORITY, acpi_pst_set_pstate_handler);
1411 msg.base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
1412 msg.ctrl = &sc->pst_creg;
1413 msg.status = &sc->pst_sreg;
1415 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1419 acpi_pst_get_pstate_handler(netmsg_t msg)
1421 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1422 const struct acpi_pstate *pstate;
1424 pstate = acpi_pst_md->pmd_get_pstate(rmsg->status, acpi_pstates,
1426 rmsg->base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
1427 lwkt_replymsg(&rmsg->base.lmsg, 0);
1430 static const struct acpi_pstate *
1431 acpi_pst_get_pstate(struct acpi_pst_softc *sc)
1433 struct netmsg_acpi_pst msg;
1435 if (acpi_pst_md == NULL)
1438 netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1439 MSGF_PRIORITY, acpi_pst_get_pstate_handler);
1440 msg.status = &sc->pst_sreg;
1442 lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1443 return msg.base.lmsg.u.ms_resultp;
1447 acpi_pst_alloc_resource(device_t dev, ACPI_OBJECT *obj, int idx,
1448 struct acpi_pst_res *res)
1450 struct acpi_pst_softc *sc = device_get_softc(dev);
1454 error = acpi_PkgRawGas(obj, idx, &res->pr_gas);
1458 /* Allocate resource, if possible */
1459 res->pr_rid = sc->pst_parent->cpu_next_rid;
1460 acpi_bus_alloc_gas(dev, &type, &res->pr_rid, &res->pr_gas, &res->pr_res, 0);
1461 if (res->pr_res != NULL) {
1462 sc->pst_parent->cpu_next_rid++;
1463 res->pr_bt = rman_get_bustag(res->pr_res);
1464 res->pr_bh = rman_get_bushandle(res->pr_res);
1472 acpi_pst_domain_check_nproc(device_t dev, struct acpi_pst_domain *dom)
1474 struct acpi_pst_softc *pst;
1478 LIST_FOREACH(pst, &dom->pd_pstlist, pst_link)
1480 if (i == dom->pd_nproc) {
1482 * Some stupid BIOSes will set wrong "# of processors",
1483 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
1486 device_printf(dev, "domain%u already contains %d "
1487 "P-States\n", dom->pd_dom, dom->pd_nproc);
1491 KKASSERT(i < dom->pd_nproc);