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