nrelease - fix/improve livecd
[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/cpuhelper.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/queue.h>
43 #include <sys/rman.h>
44 #include <sys/sysctl.h>
45 #include <sys/msgport2.h>
46 #include <sys/cpu_topology.h>
47
48 #include "acpi.h"
49 #include "acpivar.h"
50 #include "acpi_cpu.h"
51 #include "acpi_cpu_pstate.h"
52
53 #define ACPI_NPSTATE_MAX        32
54
55 #define ACPI_PSS_PX_NENTRY      6
56
57 #define ACPI_PSD_COORD_SWALL    0xfc
58 #define ACPI_PSD_COORD_SWANY    0xfd
59 #define ACPI_PSD_COORD_HWALL    0xfe
60 #define ACPI_PSD_COORD_VALID(coord) \
61         ((coord) == ACPI_PSD_COORD_SWALL || \
62          (coord) == ACPI_PSD_COORD_SWANY || \
63          (coord) == ACPI_PSD_COORD_HWALL)
64
65 struct acpi_pst_softc;
66 LIST_HEAD(acpi_pst_list, acpi_pst_softc);
67
68 struct acpi_pst_chmsg {
69         struct cpuhelper_msg    ch_msg;
70         const struct acpi_pst_res *ch_ctrl;
71         const struct acpi_pst_res *ch_status;
72 };
73
74 struct acpi_pst_domain {
75         uint32_t                pd_dom;
76         uint32_t                pd_coord;
77         uint32_t                pd_nproc;
78         LIST_ENTRY(acpi_pst_domain) pd_link;
79
80         uint32_t                pd_flags;
81
82         struct lwkt_serialize   pd_serialize;
83
84         int                     pd_state;
85         struct acpi_pst_list    pd_pstlist;
86
87         struct sysctl_ctx_list  pd_sysctl_ctx;
88         struct sysctl_oid       *pd_sysctl_tree;
89 };
90 LIST_HEAD(acpi_pst_domlist, acpi_pst_domain);
91
92 #define ACPI_PSTDOM_FLAG_STUB   0x1     /* stub domain, no _PSD */
93 #define ACPI_PSTDOM_FLAG_DEAD   0x2     /* domain can't be started */
94 #define ACPI_PSTDOM_FLAG_INT    0x4     /* domain created from Integer _PSD */
95
96 struct acpi_pst_softc {
97         device_t                pst_dev;
98         struct acpi_cpu_softc   *pst_parent;
99         struct acpi_pst_domain  *pst_domain;
100         struct acpi_pst_res     pst_creg;
101         struct acpi_pst_res     pst_sreg;
102
103         int                     pst_state;
104         int                     pst_cpuid;
105
106         uint32_t                pst_flags;
107
108         ACPI_HANDLE             pst_handle;
109
110         LIST_ENTRY(acpi_pst_softc) pst_link;
111 };
112
113 #define ACPI_PST_FLAG_PPC       0x1
114 #define ACPI_PST_FLAG_PDL       0x2
115
116 static int      acpi_pst_probe(device_t dev);
117 static int      acpi_pst_attach(device_t dev);
118 static void     acpi_pst_notify(device_t dev);
119
120 static void     acpi_pst_postattach(void *);
121 static struct acpi_pst_domain *
122                 acpi_pst_domain_create_int(device_t, uint32_t);
123 static struct acpi_pst_domain *
124                 acpi_pst_domain_create_pkg(device_t, ACPI_OBJECT *);
125 static struct acpi_pst_domain *
126                 acpi_pst_domain_find(uint32_t);
127 static struct acpi_pst_domain *
128                 acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t);
129 static void     acpi_pst_domain_set_pstate_locked(struct acpi_pst_domain *,
130                     int, int *);
131 static void     acpi_pst_domain_set_pstate(struct acpi_pst_domain *, int,
132                     int *);
133 static void     acpi_pst_domain_check_nproc(device_t, struct acpi_pst_domain *);
134 static void     acpi_pst_global_set_pstate(int);
135 static void     acpi_pst_global_fixup_pstate(void);
136
137 static int      acpi_pst_check_csr(struct acpi_pst_softc *);
138 static int      acpi_pst_check_pstates(struct acpi_pst_softc *);
139 static int      acpi_pst_init(struct acpi_pst_softc *);
140 static int      acpi_pst_set_pstate(struct acpi_pst_softc *,
141                     const struct acpi_pstate *);
142 static const struct acpi_pstate *
143                 acpi_pst_get_pstate(struct acpi_pst_softc *);
144 static int      acpi_pst_alloc_resource(device_t, ACPI_OBJECT *, int,
145                     struct acpi_pst_res *);
146 static int      acpi_pst_eval_ppc(struct acpi_pst_softc *, int *);
147 static int      acpi_pst_eval_pdl(struct acpi_pst_softc *, int *);
148
149 static void     acpi_pst_check_csr_handler(struct cpuhelper_msg *);
150 static void     acpi_pst_check_pstates_handler(struct cpuhelper_msg *);
151 static void     acpi_pst_init_handler(struct cpuhelper_msg *);
152 static void     acpi_pst_set_pstate_handler(struct cpuhelper_msg *);
153 static void     acpi_pst_get_pstate_handler(struct cpuhelper_msg *);
154
155 static int      acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS);
156 static int      acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS);
157 static int      acpi_pst_sysctl_power(SYSCTL_HANDLER_ARGS);
158 static int      acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS);
159 static int      acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS);
160 static int      acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS);
161
162 static struct acpi_pst_domlist  acpi_pst_domains =
163         LIST_HEAD_INITIALIZER(acpi_pst_domains);
164 static int                      acpi_pst_domain_id;
165
166 static int                      acpi_pst_global_state;
167
168 static int                      acpi_pstate_start = -1;
169 static int                      acpi_pstate_count;
170 static int                      acpi_npstates;
171 static struct acpi_pstate       *acpi_pstates;
172
173 static const struct acpi_pst_md *acpi_pst_md;
174
175 static int                      acpi_pst_pdl = -1;
176 TUNABLE_INT("hw.acpi.cpu.pst.pdl", &acpi_pst_pdl);
177
178 static int                      acpi_pst_ht_reuse_domain = 1;
179 TUNABLE_INT("hw.acpi.cpu.pst.ht_reuse_domain", &acpi_pst_ht_reuse_domain);
180
181 static int                      acpi_pst_force_pkg_domain = 0;
182 TUNABLE_INT("hw.acpi.cpu.pst.force_pkg_domain", &acpi_pst_force_pkg_domain);
183
184 static int                      acpi_pst_handle_notify = 1;
185 TUNABLE_INT("hw.acpi.cpu.pst.handle_notify", &acpi_pst_handle_notify);
186
187 /*
188  * Force CPU package power domain for Intel CPUs.
189  *
190  * As of this write (14 July 2015), all Intel CPUs only have CPU package
191  * power domain.
192  */
193 static int                      acpi_pst_intel_pkg_domain = 1;
194 TUNABLE_INT("hw.acpi.cpu.pst.intel_pkg_domain", &acpi_pst_intel_pkg_domain);
195
196 static device_method_t acpi_pst_methods[] = {
197         /* Device interface */
198         DEVMETHOD(device_probe,                 acpi_pst_probe),
199         DEVMETHOD(device_attach,                acpi_pst_attach),
200         DEVMETHOD(device_detach,                bus_generic_detach),
201         DEVMETHOD(device_shutdown,              bus_generic_shutdown),
202         DEVMETHOD(device_suspend,               bus_generic_suspend),
203         DEVMETHOD(device_resume,                bus_generic_resume),
204
205         /* Bus interface */
206         DEVMETHOD(bus_add_child,                bus_generic_add_child),
207         DEVMETHOD(bus_print_child,              bus_generic_print_child),
208         DEVMETHOD(bus_read_ivar,                bus_generic_read_ivar),
209         DEVMETHOD(bus_write_ivar,               bus_generic_write_ivar),
210         DEVMETHOD(bus_get_resource_list,        bus_generic_get_resource_list),
211         DEVMETHOD(bus_set_resource,             bus_generic_rl_set_resource),
212         DEVMETHOD(bus_get_resource,             bus_generic_rl_get_resource),
213         DEVMETHOD(bus_alloc_resource,           bus_generic_alloc_resource),
214         DEVMETHOD(bus_release_resource,         bus_generic_release_resource),
215         DEVMETHOD(bus_driver_added,             bus_generic_driver_added),
216         DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
217         DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
218         DEVMETHOD(bus_setup_intr,               bus_generic_setup_intr),
219         DEVMETHOD(bus_teardown_intr,            bus_generic_teardown_intr),
220
221         DEVMETHOD_END
222 };
223
224 static driver_t acpi_pst_driver = {
225         "cpu_pst",
226         acpi_pst_methods,
227         sizeof(struct acpi_pst_softc),
228         .gpri = KOBJ_GPRI_ACPI+2
229 };
230
231 static devclass_t acpi_pst_devclass;
232 DRIVER_MODULE(cpu_pst, cpu, acpi_pst_driver, acpi_pst_devclass, NULL, NULL);
233 MODULE_DEPEND(cpu_pst, acpi, 1, 1, 1);
234
235 static __inline int
236 acpi_pst_freq2index(int freq)
237 {
238         int i;
239
240         for (i = 0; i < acpi_npstates; ++i) {
241                 if (acpi_pstates[i].st_freq == freq)
242                         return i;
243         }
244         return -1;
245 }
246
247 static int
248 acpi_pst_probe(device_t dev)
249 {
250         ACPI_BUFFER buf;
251         ACPI_HANDLE handle;
252         ACPI_STATUS status;
253         ACPI_OBJECT *obj;
254
255         if (acpi_disabled("cpu_pst") ||
256             acpi_get_type(dev) != ACPI_TYPE_PROCESSOR)
257                 return ENXIO;
258
259         if (acpi_pst_md == NULL)
260                 acpi_pst_md = acpi_pst_md_probe();
261
262         handle = acpi_get_handle(dev);
263
264         /*
265          * Check _PSD package
266          *
267          * NOTE:
268          * Some BIOSes do not expose _PCT for the second thread of
269          * CPU cores.  In this case, _PSD should be enough to get the
270          * P-state of the second thread working, since it must have
271          * the same _PCT and _PSS as the first thread in the same
272          * core.
273          */
274         buf.Pointer = NULL;
275         buf.Length = ACPI_ALLOCATE_BUFFER;
276         status = AcpiEvaluateObject(handle, "_PSD", NULL, &buf);
277         if (!ACPI_FAILURE(status)) {
278                 AcpiOsFree((ACPI_OBJECT *)buf.Pointer);
279                 goto done;
280         }
281
282         /*
283          * Check _PCT package
284          */
285         buf.Pointer = NULL;
286         buf.Length = ACPI_ALLOCATE_BUFFER;
287         status = AcpiEvaluateObject(handle, "_PCT", NULL, &buf);
288         if (ACPI_FAILURE(status)) {
289                 if (bootverbose) {
290                         device_printf(dev, "Can't get _PCT package - %s\n",
291                                       AcpiFormatException(status));
292                 }
293                 return ENXIO;
294         }
295
296         obj = (ACPI_OBJECT *)buf.Pointer;
297         if (!ACPI_PKG_VALID_EQ(obj, 2)) {
298                 device_printf(dev, "Invalid _PCT package\n");
299                 AcpiOsFree(obj);
300                 return ENXIO;
301         }
302         AcpiOsFree(obj);
303
304         /*
305          * Check _PSS package
306          */
307         buf.Pointer = NULL;
308         buf.Length = ACPI_ALLOCATE_BUFFER;
309         status = AcpiEvaluateObject(handle, "_PSS", NULL, &buf);
310         if (ACPI_FAILURE(status)) {
311                 device_printf(dev, "Can't get _PSS package - %s\n",
312                               AcpiFormatException(status));
313                 return ENXIO;
314         }
315
316         obj = (ACPI_OBJECT *)buf.Pointer;
317         if (!ACPI_PKG_VALID(obj, 1)) {
318                 device_printf(dev, "Invalid _PSS package\n");
319                 AcpiOsFree(obj);
320                 return ENXIO;
321         }
322         AcpiOsFree(obj);
323
324 done:
325         device_set_desc(dev, "ACPI CPU P-State");
326         return 0;
327 }
328
329 static int
330 acpi_pst_attach(device_t dev)
331 {
332         struct acpi_pst_softc *sc = device_get_softc(dev);
333         struct acpi_pst_domain *dom = NULL;
334         ACPI_BUFFER buf;
335         ACPI_STATUS status;
336         ACPI_OBJECT *obj;
337         struct acpi_pstate *pstate, *p;
338         int i, npstate, error, sstart, scount;
339
340         sc->pst_dev = dev;
341         sc->pst_parent = device_get_softc(device_get_parent(dev));
342         sc->pst_handle = acpi_get_handle(dev);
343         sc->pst_cpuid = acpi_get_magic(dev);
344
345         /*
346          * If there is a _PSD, then we create procossor domain
347          * accordingly.  If there is no _PSD, we just fake a
348          * default processor domain0.
349          */
350         buf.Pointer = NULL;
351         buf.Length = ACPI_ALLOCATE_BUFFER;
352         status = AcpiEvaluateObject(sc->pst_handle, "_PSD", NULL, &buf);
353         if (!ACPI_FAILURE(status)) {
354                 obj = (ACPI_OBJECT *)buf.Pointer;
355
356                 if (acpi_pst_domain_id > 0) {
357                         device_printf(dev, "Missing _PSD for certain CPUs\n");
358                         AcpiOsFree(obj);
359                         return ENXIO;
360                 }
361                 acpi_pst_domain_id = -1;
362
363                 if (ACPI_PKG_VALID_EQ(obj, 1)) {
364                         dom = acpi_pst_domain_create_pkg(dev,
365                                 &obj->Package.Elements[0]);
366                         if (dom == NULL) {
367                                 AcpiOsFree(obj);
368                                 return ENXIO;
369                         }
370                 } else {
371                         if (obj->Type != ACPI_TYPE_INTEGER) {
372                                 device_printf(dev,
373                                     "Invalid _PSD package, Type 0x%x\n",
374                                     obj->Type);
375                                 AcpiOsFree(obj);
376                                 return ENXIO;
377                         } else {
378                                 device_printf(dev, "Integer _PSD %ju\n",
379                                     (uintmax_t)obj->Integer.Value);
380                                 dom = acpi_pst_domain_create_int(dev,
381                                     obj->Integer.Value);
382                                 if (dom == NULL) {
383                                         AcpiOsFree(obj);
384                                         return ENXIO;
385                                 }
386                         }
387                 }
388
389                 /* Free _PSD */
390                 AcpiOsFree(buf.Pointer);
391         } else {
392                 if (acpi_pst_domain_id < 0) {
393                         device_printf(dev, "Missing _PSD for cpu%d\n",
394                             sc->pst_cpuid);
395                         return ENXIO;
396                 }
397
398                 /*
399                  * Create a stub one processor domain for each processor
400                  */
401                 dom = acpi_pst_domain_alloc(acpi_pst_domain_id,
402                         ACPI_PSD_COORD_SWANY, 1);
403                 dom->pd_flags |= ACPI_PSTDOM_FLAG_STUB;
404
405                 ++acpi_pst_domain_id;
406         }
407
408         /* Make sure that adding us will not overflow our domain */
409         acpi_pst_domain_check_nproc(dev, dom);
410
411         /*
412          * Get control/status registers from _PCT
413          */
414         buf.Pointer = NULL;
415         buf.Length = ACPI_ALLOCATE_BUFFER;
416         status = AcpiEvaluateObject(sc->pst_handle, "_PCT", NULL, &buf);
417         if (ACPI_FAILURE(status)) {
418                 struct acpi_pst_softc *pst;
419
420                 /*
421                  * No _PCT.  See the comment in acpi_pst_probe() near
422                  * _PSD check.
423                  *
424                  * Use control/status registers of another CPU in the
425                  * same domain, or in the same core, if the type of
426                  * these registers are "Fixed Hardware", e.g. on most
427                  * of the model Intel CPUs.
428                  */
429                 pst = LIST_FIRST(&dom->pd_pstlist);
430                 if (pst == NULL) {
431                         cpumask_t mask;
432
433                         mask = get_cpumask_from_level(sc->pst_cpuid,
434                             CORE_LEVEL);
435                         if (CPUMASK_TESTNZERO(mask)) {
436                                 struct acpi_pst_domain *dom1;
437
438                                 LIST_FOREACH(dom1, &acpi_pst_domains, pd_link) {
439                                         LIST_FOREACH(pst, &dom1->pd_pstlist,
440                                             pst_link) {
441                                                 if (CPUMASK_TESTBIT(mask,
442                                                     pst->pst_cpuid))
443                                                         break;
444                                         }
445                                         if (pst != NULL)
446                                                 break;
447                                 }
448                                 if (pst != NULL && acpi_pst_ht_reuse_domain) {
449                                         /*
450                                          * Use the same domain for CPUs in the
451                                          * same core.
452                                          */
453                                         device_printf(dev, "Destroy domain%u, "
454                                             "reuse domain%u\n",
455                                             dom->pd_dom, dom1->pd_dom);
456                                         LIST_REMOVE(dom, pd_link);
457                                         kfree(dom, M_DEVBUF);
458                                         dom = dom1;
459                                         /*
460                                          * Make sure that adding us will not
461                                          * overflow the domain containing
462                                          * siblings in the same core.
463                                          */
464                                         acpi_pst_domain_check_nproc(dev, dom);
465                                 }
466                         }
467                 }
468                 if (pst != NULL &&
469                     pst->pst_creg.pr_res == NULL &&
470                     pst->pst_creg.pr_rid == 0 &&
471                     pst->pst_creg.pr_gas.SpaceId ==
472                     ACPI_ADR_SPACE_FIXED_HARDWARE &&
473                     pst->pst_sreg.pr_res == NULL &&
474                     pst->pst_sreg.pr_rid == 0 &&
475                     pst->pst_sreg.pr_gas.SpaceId ==
476                     ACPI_ADR_SPACE_FIXED_HARDWARE) {
477                         sc->pst_creg = pst->pst_creg;
478                         sc->pst_sreg = pst->pst_sreg;
479                         device_printf(dev,
480                             "No _PCT; reuse %s control/status regs\n",
481                             device_get_nameunit(pst->pst_dev));
482                         goto fetch_pss;
483                 }
484                 device_printf(dev, "Can't get _PCT package - %s\n",
485                               AcpiFormatException(status));
486                 return ENXIO;
487         }
488
489         obj = (ACPI_OBJECT *)buf.Pointer;
490         if (!ACPI_PKG_VALID_EQ(obj, 2)) {
491                 device_printf(dev, "Invalid _PCT package\n");
492                 AcpiOsFree(obj);
493                 return ENXIO;
494         }
495
496         /* Save and try allocating control register */
497         error = acpi_pst_alloc_resource(dev, obj, 0, &sc->pst_creg);
498         if (error) {
499                 AcpiOsFree(obj);
500                 return error;
501         }
502         if (bootverbose) {
503                 device_printf(dev, "control reg %d %jx\n",
504                               sc->pst_creg.pr_gas.SpaceId,
505                               (uintmax_t)sc->pst_creg.pr_gas.Address);
506         }
507
508         /* Save and try allocating status register */
509         error = acpi_pst_alloc_resource(dev, obj, 1, &sc->pst_sreg);
510         if (error) {
511                 AcpiOsFree(obj);
512                 return error;
513         }
514         if (bootverbose) {
515                 device_printf(dev, "status reg %d %jx\n",
516                               sc->pst_sreg.pr_gas.SpaceId,
517                               (uintmax_t)sc->pst_sreg.pr_gas.Address);
518         }
519
520         /* Free _PCT */
521         AcpiOsFree(obj);
522
523 fetch_pss:
524         /*
525          * Create P-State table according to _PSS
526          */
527         buf.Pointer = NULL;
528         buf.Length = ACPI_ALLOCATE_BUFFER;
529         status = AcpiEvaluateObject(sc->pst_handle, "_PSS", NULL, &buf);
530         if (ACPI_FAILURE(status)) {
531                 /*
532                  * No _PSS.  See the comment in acpi_pst_probe() near
533                  * _PSD check.
534                  *
535                  * Assume _PSS are same across all CPUs; well, they
536                  * should/have to be so.
537                  */
538                 if (acpi_npstates > 0 && acpi_pstates != NULL) {
539                         device_printf(dev, "No _PSS\n");
540                         goto fetch_ppc;
541                 }
542                 device_printf(dev, "Can't get _PSS package - %s\n",
543                               AcpiFormatException(status));
544                 return ENXIO;
545         }
546
547         obj = (ACPI_OBJECT *)buf.Pointer;
548         if (!ACPI_PKG_VALID(obj, 1)) {
549                 device_printf(dev, "Invalid _PSS package\n");
550                 AcpiOsFree(obj);
551                 return ENXIO;
552         }
553
554         /* Don't create too many P-States */
555         npstate = obj->Package.Count;
556         if (npstate > ACPI_NPSTATE_MAX) {
557                 device_printf(dev, "Too many P-States, %d->%d\n",
558                               npstate, ACPI_NPSTATE_MAX);
559                 npstate = ACPI_NPSTATE_MAX;
560         }
561
562         /*
563          * If we have already created P-State table,
564          * we must make sure that number of entries
565          * is consistent.
566          */
567         if (acpi_pstates != NULL && acpi_npstates != npstate) {
568                 device_printf(dev, "Inconsistent # of P-States "
569                               "cross Processor objects\n");
570                 AcpiOsFree(obj);
571                 return ENXIO;
572         }
573
574         /*
575          * Create a temporary P-State table
576          */
577         pstate = kmalloc(sizeof(*pstate) * npstate, M_TEMP, M_WAITOK);
578         for (i = 0, p = pstate; i < npstate; ++i, ++p) {
579                 ACPI_OBJECT *pkg;
580                 uint32_t *ptr[ACPI_PSS_PX_NENTRY] = {
581                         &p->st_freq, &p->st_power, &p->st_xsit_lat,
582                         &p->st_bm_lat, &p->st_cval, &p->st_sval
583                 };
584                 int j;
585
586                 pkg = &obj->Package.Elements[i];
587                 if (!ACPI_PKG_VALID(pkg, ACPI_PSS_PX_NENTRY)) {
588                         device_printf(dev, "Invalud _PSS P%d\n", i);
589                         AcpiOsFree(obj);
590                         kfree(pstate, M_TEMP);
591                         return ENXIO;
592                 }
593                 for (j = 0; j < ACPI_PSS_PX_NENTRY; ++j) {
594                         if (acpi_PkgInt32(pkg, j, ptr[j]) != 0) {
595                                 device_printf(dev, "Can't extract "
596                                               "_PSS P%d %dth entry\n", i, j);
597                                 AcpiOsFree(obj);
598                                 kfree(pstate, M_TEMP);
599                                 return ENXIO;
600                         }
601                 }
602                 if (p->st_freq & 0x80000000) {
603                         device_printf(dev, "Invalid _PSS P%d freq: 0x%08x\n",
604                             i, p->st_freq);
605                         AcpiOsFree(obj);
606                         kfree(pstate, M_TEMP);
607                         return ENXIO;
608                 }
609         }
610
611         /* Free _PSS */
612         AcpiOsFree(obj);
613
614         if (acpi_pstates == NULL) {
615                 /*
616                  * If no P-State table is created yet,
617                  * save the temporary one we just created.
618                  */
619                 acpi_pstates = pstate;
620                 acpi_npstates = npstate;
621                 pstate = NULL;
622
623                 if (bootverbose) {
624                         for (i = 0; i < acpi_npstates; ++i) {
625                                 device_printf(dev,
626                                 "freq %u, pwr %u, xlat %u, blat %u, "
627                                 "cv %08x, sv %08x\n",
628                                 acpi_pstates[i].st_freq,
629                                 acpi_pstates[i].st_power,
630                                 acpi_pstates[i].st_xsit_lat,
631                                 acpi_pstates[i].st_bm_lat,
632                                 acpi_pstates[i].st_cval,
633                                 acpi_pstates[i].st_sval);
634                         }
635                 }
636         } else {
637                 /*
638                  * Make sure that P-State tables are same
639                  * for all processors.
640                  */
641                 if (memcmp(pstate, acpi_pstates,
642                            sizeof(*pstate) * npstate) != 0) {
643                         device_printf(dev, "Inconsistent _PSS "
644                                       "cross Processor objects\n");
645 #if 0
646                         /*
647                          * Some BIOSes create different P-State tables;
648                          * just trust the one from the BSP and move on.
649                          */
650                         kfree(pstate, M_TEMP);
651                         return ENXIO;
652 #endif
653                 }
654                 kfree(pstate, M_TEMP);
655         }
656
657 fetch_ppc:
658         /* By default, we start from P-State table's first entry */
659         sstart = 0;
660
661         /*
662          * Adjust the usable first entry of P-State table,
663          * if there is _PPC object.
664          */
665         error = acpi_pst_eval_ppc(sc, &sstart);
666         if (error && error != ENOENT)
667                 return error;
668         else if (!error)
669                 sc->pst_flags |= ACPI_PST_FLAG_PPC;
670         if (acpi_pstate_start < 0) {
671                 acpi_pstate_start = sstart;
672         } else if (acpi_pstate_start != sstart) {
673                 device_printf(dev, "_PPC mismatch, was %d, now %d\n",
674                     acpi_pstate_start, sstart);
675                 if (acpi_pstate_start < sstart) {
676                         device_printf(dev, "_PPC %d -> %d\n",
677                             acpi_pstate_start, sstart);
678                         acpi_pstate_start = sstart;
679                 }
680         }
681
682         /*
683          * By default, we assume number of usable P-States is same as
684          * number of P-States.
685          */
686         scount = acpi_npstates;
687
688         /*
689          * Allow users to override or set _PDL
690          */
691         if (acpi_pst_pdl >= 0) {
692                 if (acpi_pst_pdl < acpi_npstates) {
693                         if (bootverbose) {
694                                 device_printf(dev, "_PDL override %d\n",
695                                     acpi_pst_pdl);
696                         }
697                         scount = acpi_pst_pdl + 1;
698                         goto proc_pdl;
699                 } else {
700                         device_printf(dev, "Invalid _PDL override %d, "
701                             "must be less than %d\n", acpi_pst_pdl,
702                             acpi_npstates);
703                 }
704         }
705
706         /*
707          * Adjust the number of usable entries in P-State table,
708          * if there is _PDL object.
709          */
710         error = acpi_pst_eval_pdl(sc, &scount);
711         if (error && error != ENOENT)
712                 return error;
713         else if (!error)
714                 sc->pst_flags |= ACPI_PST_FLAG_PDL;
715 proc_pdl:
716         if (acpi_pstate_count == 0) {
717                 acpi_pstate_count = scount;
718         } else if (acpi_pstate_count != scount) {
719                 device_printf(dev, "_PDL mismatch, was %d, now %d\n",
720                     acpi_pstate_count, scount);
721                 if (acpi_pstate_count > scount) {
722                         device_printf(dev, "_PDL %d -> %d\n",
723                             acpi_pstate_count, scount);
724                         acpi_pstate_count = scount;
725                 }
726         }
727
728         /*
729          * Some CPUs only have package P-states, but some BIOSes put each
730          * hyperthread to its own P-state domain; allow user to override.
731          */
732         if (LIST_EMPTY(&dom->pd_pstlist) &&
733             (acpi_pst_force_pkg_domain ||
734              (cpu_vendor_id == CPU_VENDOR_INTEL &&
735               acpi_pst_intel_pkg_domain))) {
736                 cpumask_t mask;
737
738                 mask = get_cpumask_from_level(sc->pst_cpuid, CHIP_LEVEL);
739                 if (CPUMASK_TESTNZERO(mask)) {
740                         struct acpi_pst_softc *pst = NULL;
741                         struct acpi_pst_domain *dom1;
742
743                         LIST_FOREACH(dom1, &acpi_pst_domains, pd_link) {
744                                 LIST_FOREACH(pst, &dom1->pd_pstlist,
745                                     pst_link) {
746                                         if (CPUMASK_TESTBIT(mask,
747                                             pst->pst_cpuid))
748                                                 break;
749                                 }
750                                 if (pst != NULL)
751                                         break;
752                         }
753                         if (pst != NULL &&
754                             memcmp(&pst->pst_creg, &sc->pst_creg,
755                                 sizeof(sc->pst_creg)) == 0 &&
756                             memcmp(&pst->pst_sreg, &sc->pst_sreg,
757                                 sizeof(sc->pst_sreg)) == 0) {
758                                 /*
759                                  * Use the same domain for CPUs in the
760                                  * same package.
761                                  */
762                                 device_printf(dev, "Destroy domain%u, "
763                                     "force pkg domain%u\n",
764                                     dom->pd_dom, dom1->pd_dom);
765                                 LIST_REMOVE(dom, pd_link);
766                                 kfree(dom, M_DEVBUF);
767                                 dom = dom1;
768                                 /*
769                                  * Make sure that adding us will not
770                                  * overflow the domain containing
771                                  * siblings in the same package.
772                                  */
773                                 acpi_pst_domain_check_nproc(dev, dom);
774                         }
775                 }
776         }
777
778         /* Link us with the domain */
779         sc->pst_domain = dom;
780         LIST_INSERT_HEAD(&dom->pd_pstlist, sc, pst_link);
781
782         if (device_get_unit(dev) == 0)
783                 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_pst_postattach, NULL);
784
785         if (sc->pst_flags & (ACPI_PST_FLAG_PPC | ACPI_PST_FLAG_PDL))
786                 sc->pst_parent->cpu_pst_notify = acpi_pst_notify;
787
788         return 0;
789 }
790
791 static struct acpi_pst_domain *
792 acpi_pst_domain_create_pkg(device_t dev, ACPI_OBJECT *obj)
793 {
794         struct acpi_pst_domain *dom;
795         uint32_t val, domain, coord, nproc;
796
797         if (!ACPI_PKG_VALID_EQ(obj, 5)) {
798                 device_printf(dev, "Invalid _PSD package\n");
799                 return NULL;
800         }
801
802         /* NumberOfEntries */
803         if (acpi_PkgInt32(obj, 0, &val) != 0 || val != 5) {
804                 device_printf(dev, "Invalid _PSD NumberOfEntries\n");
805                 return NULL;
806         }
807
808         /* Revision */
809         if (acpi_PkgInt32(obj, 1, &val) != 0 || val != 0) {
810                 device_printf(dev, "Invalid _PSD Revision\n");
811                 return NULL;
812         }
813
814         if (acpi_PkgInt32(obj, 2, &domain) != 0 ||
815             acpi_PkgInt32(obj, 3, &coord) != 0 ||
816             acpi_PkgInt32(obj, 4, &nproc) != 0) {
817                 device_printf(dev, "Can't extract _PSD package\n");
818                 return NULL;
819         }
820
821         if (!ACPI_PSD_COORD_VALID(coord)) {
822                 device_printf(dev, "Invalid _PSD CoordType (%#x)\n", coord);
823                 return NULL;
824         }
825
826         if (nproc > MAXCPU) {
827                 /*
828                  * If NumProcessors is greater than MAXCPU
829                  * and domain's coordination is SWALL, then
830                  * we will never be able to start all CPUs
831                  * within this domain, and power state
832                  * transition will never be completed, so we
833                  * just bail out here.
834                  */
835                 if (coord == ACPI_PSD_COORD_SWALL) {
836                         device_printf(dev, "Unsupported _PSD NumProcessors "
837                                       "(%d)\n", nproc);
838                         return NULL;
839                 }
840         } else if (nproc == 0) {
841                 device_printf(dev, "_PSD NumProcessors are zero\n");
842                 return NULL;
843         }
844
845         dom = acpi_pst_domain_find(domain);
846         if (dom != NULL) {
847                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_INT) {
848                         device_printf(dev, "Mixed Integer _PSD and "
849                             "Package _PSD\n");
850                         return NULL;
851                 }
852                 if (dom->pd_coord != coord) {
853                         device_printf(dev, "Inconsistent _PSD coord "
854                             "information cross Processor objects\n");
855                         return NULL;
856                 }
857                 if (dom->pd_nproc != nproc) {
858                         device_printf(dev, "Inconsistent _PSD nproc "
859                             "information cross Processor objects\n");
860                         /*
861                          * Some stupid BIOSes will set wrong "# of processors",
862                          * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
863                          */
864                 }
865                 return dom;
866         }
867
868         dom = acpi_pst_domain_alloc(domain, coord, nproc);
869         if (bootverbose) {
870                 device_printf(dev, "create pkg domain%u, coord %#x\n",
871                     dom->pd_dom, dom->pd_coord);
872         }
873
874         return dom;
875 }
876
877 static struct acpi_pst_domain *
878 acpi_pst_domain_create_int(device_t dev, uint32_t domain)
879 {
880         struct acpi_pst_domain *dom;
881
882         dom = acpi_pst_domain_find(domain);
883         if (dom != NULL) {
884                 if ((dom->pd_flags & ACPI_PSTDOM_FLAG_INT) == 0) {
885                         device_printf(dev, "Mixed Package _PSD and "
886                             "Integer _PSD\n");
887                         return NULL;
888                 }
889                 KKASSERT(dom->pd_coord == ACPI_PSD_COORD_SWALL);
890
891                 dom->pd_nproc++;
892                 return dom;
893         }
894
895         dom = acpi_pst_domain_alloc(domain, ACPI_PSD_COORD_SWALL, 1);
896         dom->pd_flags |= ACPI_PSTDOM_FLAG_INT;
897
898         if (bootverbose)
899                 device_printf(dev, "create int domain%u\n", dom->pd_dom);
900
901         return dom;
902 }
903
904 static struct acpi_pst_domain *
905 acpi_pst_domain_find(uint32_t domain)
906 {
907         struct acpi_pst_domain *dom;
908
909         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
910                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_STUB)
911                         continue;
912                 if (dom->pd_dom == domain)
913                         return dom;
914         }
915         return NULL;
916 }
917
918 static struct acpi_pst_domain *
919 acpi_pst_domain_alloc(uint32_t domain, uint32_t coord, uint32_t nproc)
920 {
921         struct acpi_pst_domain *dom;
922
923         dom = kmalloc(sizeof(*dom), M_DEVBUF, M_WAITOK | M_ZERO);
924         dom->pd_dom = domain;
925         dom->pd_coord = coord;
926         dom->pd_nproc = nproc;
927         LIST_INIT(&dom->pd_pstlist);
928         lwkt_serialize_init(&dom->pd_serialize);
929
930         LIST_INSERT_HEAD(&acpi_pst_domains, dom, pd_link);
931
932         return dom;
933 }
934
935 static void
936 acpi_pst_domain_set_pstate_locked(struct acpi_pst_domain *dom, int i, int *global)
937 {
938         const struct acpi_pstate *pstate;
939         struct acpi_pst_softc *sc;
940         int done, error;
941
942         ASSERT_SERIALIZED(&dom->pd_serialize);
943
944         KKASSERT(i >= 0 && i < acpi_npstates);
945         pstate = &acpi_pstates[i];
946
947         done = 0;
948         LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
949                 if (!done) {
950                         error = acpi_pst_set_pstate(sc, pstate);
951                         if (error) {
952                                 device_printf(sc->pst_dev, "can't set "
953                                               "freq %d\n", pstate->st_freq);
954                                 /* XXX error cleanup? */
955                         }
956                         if (dom->pd_coord == ACPI_PSD_COORD_SWANY)
957                                 done = 1;
958                 }
959                 sc->pst_state = i;
960         }
961         dom->pd_state = i;
962
963         if (global != NULL)
964                 *global = i;
965 }
966
967 static void
968 acpi_pst_domain_set_pstate(struct acpi_pst_domain *dom, int i, int *global)
969 {
970         lwkt_serialize_enter(&dom->pd_serialize);
971         acpi_pst_domain_set_pstate_locked(dom, i, global);
972         lwkt_serialize_exit(&dom->pd_serialize);
973 }
974
975 static void
976 acpi_pst_global_set_pstate(int i)
977 {
978         struct acpi_pst_domain *dom;
979         int *global = &acpi_pst_global_state;
980
981         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
982                 /* Skip dead domain */
983                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
984                         continue;
985                 acpi_pst_domain_set_pstate(dom, i, global);
986                 global = NULL;
987         }
988 }
989
990 static void
991 acpi_pst_global_fixup_pstate(void)
992 {
993         struct acpi_pst_domain *dom;
994         int *global = &acpi_pst_global_state;
995         int sstart, scount;
996
997         sstart = acpi_pstate_start;
998         scount = acpi_pstate_count;
999
1000         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
1001                 int i = -1;
1002
1003                 /* Skip dead domain */
1004                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
1005                         continue;
1006
1007                 lwkt_serialize_enter(&dom->pd_serialize);
1008
1009                 if (global != NULL) {
1010                         if (*global < sstart)
1011                                 *global = sstart;
1012                         else if (*global >= scount)
1013                                 *global = scount - 1;
1014                         global = NULL;
1015                 }
1016                 if (dom->pd_state < sstart)
1017                         i = sstart;
1018                 else if (dom->pd_state >= scount)
1019                         i = scount - 1;
1020                 if (i >= 0)
1021                         acpi_pst_domain_set_pstate_locked(dom, i, NULL);
1022
1023                 lwkt_serialize_exit(&dom->pd_serialize);
1024         }
1025 }
1026
1027 static void
1028 acpi_pst_postattach(void *arg __unused)
1029 {
1030         struct acpi_pst_domain *dom;
1031         struct acpi_cpu_softc *cpu;
1032         device_t *devices;
1033         int i, ndevices, error, has_domain;
1034
1035         devices = NULL;
1036         ndevices = 0;
1037         error = devclass_get_devices(acpi_pst_devclass, &devices, &ndevices);
1038         if (error)
1039                 return;
1040
1041         if (ndevices == 0)
1042                 return;
1043
1044         cpu = NULL;
1045         for (i = 0; i < ndevices; ++i) {
1046                 cpu = device_get_softc(device_get_parent(devices[i]));
1047                 if (cpu->glob_sysctl_tree != NULL)
1048                         break;
1049         }
1050         kfree(devices, M_TEMP);
1051         KKASSERT(cpu != NULL);
1052
1053         if (acpi_pst_md == NULL)
1054                 kprintf("ACPI: no P-State CPU driver\n");
1055
1056         has_domain = 0;
1057         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
1058                 struct acpi_pst_softc *sc;
1059                 char buf[32];
1060
1061                 dom->pd_state = acpi_pstate_start;
1062
1063                 /*
1064                  * Make sure that all processors belonging to this
1065                  * domain are located.
1066                  */
1067                 i = 0;
1068                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1069                         sc->pst_state = acpi_pstate_start;
1070                         ++i;
1071                 }
1072                 if (i != dom->pd_nproc) {
1073                         KKASSERT(i < dom->pd_nproc);
1074
1075                         kprintf("ACPI: domain%u misses processors, "
1076                                 "should be %d, got %d\n", dom->pd_dom,
1077                                 dom->pd_nproc, i);
1078                         if (dom->pd_coord == ACPI_PSD_COORD_SWALL) {
1079                                 /*
1080                                  * If this domain's coordination is
1081                                  * SWALL and we don't see all of the
1082                                  * member CPUs of this domain, then
1083                                  * the P-State transition will never
1084                                  * be completed, so just leave this
1085                                  * domain out.
1086                                  */
1087                                 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1088                                 continue;
1089                         }
1090                         dom->pd_nproc = i;
1091                 }
1092
1093                 /*
1094                  * Validate P-State configurations for this domain
1095                  */
1096                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1097                         error = acpi_pst_check_csr(sc);
1098                         if (error)
1099                                 break;
1100
1101                         error = acpi_pst_check_pstates(sc);
1102                         if (error)
1103                                 break;
1104                 }
1105                 if (sc != NULL) {
1106                         kprintf("ACPI: domain%u P-State configuration "
1107                                 "check failed\n", dom->pd_dom);
1108                         dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1109                         continue;
1110                 }
1111
1112                 /*
1113                  * Do necssary P-State initialization
1114                  */
1115                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1116                         error = acpi_pst_init(sc);
1117                         if (error)
1118                                 break;
1119                 }
1120                 if (sc != NULL) {
1121                         kprintf("ACPI: domain%u P-State initialization "
1122                                 "check failed\n", dom->pd_dom);
1123                         dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1124                         continue;
1125                 }
1126
1127                 has_domain = 1;
1128
1129                 ksnprintf(buf, sizeof(buf), "px_dom%u", dom->pd_dom);
1130
1131                 sysctl_ctx_init(&dom->pd_sysctl_ctx);
1132                 dom->pd_sysctl_tree =
1133                 SYSCTL_ADD_NODE(&dom->pd_sysctl_ctx,
1134                         SYSCTL_CHILDREN(cpu->glob_sysctl_tree),
1135                         OID_AUTO, buf, CTLFLAG_RD, 0,
1136                         "P-State domain");
1137                 if (dom->pd_sysctl_tree == NULL) {
1138                         kprintf("ACPI: Can't create sysctl tree for domain%u",
1139                                 dom->pd_dom);
1140                         continue;
1141                 }
1142
1143                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1144                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1145                                 OID_AUTO, "available",
1146                                 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP,
1147                                 dom, 0, acpi_pst_sysctl_freqs, "A",
1148                                 "available frequencies");
1149
1150                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1151                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1152                                 OID_AUTO, "avail",
1153                                 CTLTYPE_OPAQUE | CTLFLAG_RD,
1154                                 dom, 0, acpi_pst_sysctl_freqs_bin, "IU",
1155                                 "available frequencies");
1156
1157                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1158                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1159                                 OID_AUTO, "power",
1160                                 CTLTYPE_OPAQUE | CTLFLAG_RD,
1161                                 dom, 0, acpi_pst_sysctl_power, "IU",
1162                                 "power of available frequencies");
1163
1164                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1165                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1166                                 OID_AUTO, "members",
1167                                 CTLTYPE_STRING | CTLFLAG_RD,
1168                                 dom, 0, acpi_pst_sysctl_members, "A",
1169                                 "member cpus");
1170
1171                 if (acpi_pst_md != NULL &&
1172                     acpi_pst_md->pmd_set_pstate != NULL) {
1173                         SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1174                                         SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1175                                         OID_AUTO, "select",
1176                                         CTLTYPE_UINT | CTLFLAG_RW,
1177                                         dom, 0, acpi_pst_sysctl_select,
1178                                         "IU", "select freq");
1179                 }
1180         }
1181
1182         if (has_domain && acpi_pst_md != NULL &&
1183             acpi_pst_md->pmd_set_pstate != NULL) {
1184                 SYSCTL_ADD_PROC(&cpu->glob_sysctl_ctx,
1185                                 SYSCTL_CHILDREN(cpu->glob_sysctl_tree),
1186                                 OID_AUTO, "px_global",
1187                                 CTLTYPE_UINT | CTLFLAG_RW,
1188                                 NULL, 0, acpi_pst_sysctl_global,
1189                                 "IU", "select freq for all domains");
1190                 SYSCTL_ADD_INT(&cpu->glob_sysctl_ctx,
1191                                SYSCTL_CHILDREN(cpu->glob_sysctl_tree),
1192                                OID_AUTO, "px_handle_notify", CTLFLAG_RW,
1193                                &acpi_pst_handle_notify, 0,
1194                                "handle type 0x80 notify");
1195
1196                 acpi_pst_global_set_pstate(acpi_pstate_start);
1197         }
1198 }
1199
1200 static int
1201 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS)
1202 {
1203         int i, error, sstart, scount;
1204
1205         error = 0;
1206         sstart = acpi_pstate_start;
1207         scount = acpi_pstate_count;
1208         for (i = 0; i < acpi_npstates; ++i) {
1209                 if (error == 0 && i)
1210                         error = SYSCTL_OUT(req, " ", 1);
1211                 if (error == 0) {
1212                         const char *pat;
1213                         char buf[32];
1214
1215                         if (i < sstart || i >= scount)
1216                                 pat = "(%u)";
1217                         else
1218                                 pat = "%u";
1219
1220                         ksnprintf(buf, sizeof(buf), pat,
1221                                   acpi_pstates[i].st_freq);
1222                         error = SYSCTL_OUT(req, buf, strlen(buf));
1223                 }
1224         }
1225         return error;
1226 }
1227
1228 static int
1229 acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS)
1230 {
1231         uint32_t freqs[ACPI_NPSTATE_MAX];
1232         int cnt, i, sstart, scount;
1233
1234         sstart = acpi_pstate_start;
1235         scount = acpi_pstate_count;
1236
1237         cnt = scount - sstart;
1238         for (i = 0; i < cnt; ++i)
1239                 freqs[i] = acpi_pstates[sstart + i].st_freq;
1240
1241         return sysctl_handle_opaque(oidp, freqs, cnt * sizeof(freqs[0]), req);
1242 }
1243
1244 static int
1245 acpi_pst_sysctl_power(SYSCTL_HANDLER_ARGS)
1246 {
1247         uint32_t power[ACPI_NPSTATE_MAX];
1248         int cnt, i, sstart, scount;
1249
1250         sstart = acpi_pstate_start;
1251         scount = acpi_pstate_count;
1252
1253         cnt = scount - sstart;
1254         for (i = 0; i < cnt; ++i)
1255                 power[i] = acpi_pstates[sstart + i].st_power;
1256
1257         return sysctl_handle_opaque(oidp, power, cnt * sizeof(power[0]), req);
1258 }
1259
1260 static int
1261 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS)
1262 {
1263         struct acpi_pst_domain *dom = arg1;
1264         struct acpi_pst_softc *sc;
1265         int loop, error;
1266
1267         loop = error = 0;
1268         LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1269                 char buf[32];
1270
1271                 if (error == 0 && loop)
1272                         error = SYSCTL_OUT(req, " ", 1);
1273                 if (error == 0) {
1274                         ksnprintf(buf, sizeof(buf), "cpu%d", sc->pst_cpuid);
1275                         error = SYSCTL_OUT(req, buf, strlen(buf));
1276                 }
1277
1278                 if (error == 0 && acpi_pst_md && acpi_pst_md->pmd_get_pstate) {
1279                         const struct acpi_pstate *pstate;
1280                         const char *str;
1281
1282                         pstate = acpi_pst_get_pstate(sc);
1283                         if (pstate == NULL) {
1284                                 str = "(*)";
1285                         } else {
1286                                 ksnprintf(buf, sizeof(buf), "(%d)",
1287                                           pstate->st_freq);
1288                                 str = buf;
1289                         }
1290                         error = SYSCTL_OUT(req, str, strlen(str));
1291                 }
1292                 ++loop;
1293         }
1294         return error;
1295 }
1296
1297 static int
1298 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS)
1299 {
1300         struct acpi_pst_domain *dom = arg1;
1301         int error, i, freq;
1302
1303         KKASSERT(dom->pd_state >= 0 && dom->pd_state < acpi_npstates);
1304
1305         freq = acpi_pstates[dom->pd_state].st_freq;
1306
1307         error = sysctl_handle_int(oidp, &freq, 0, req);
1308         if (error || req->newptr == NULL)
1309                 return error;
1310
1311         i = acpi_pst_freq2index(freq);
1312         if (i < 0)
1313                 return EINVAL;
1314
1315         acpi_pst_domain_set_pstate(dom, i, NULL);
1316         return 0;
1317 }
1318
1319 static int
1320 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS)
1321 {
1322         int error, i, freq;
1323
1324         KKASSERT(acpi_pst_global_state >= 0 &&
1325                  acpi_pst_global_state < acpi_npstates);
1326
1327         freq = acpi_pstates[acpi_pst_global_state].st_freq;
1328
1329         error = sysctl_handle_int(oidp, &freq, 0, req);
1330         if (error || req->newptr == NULL)
1331                 return error;
1332
1333         i = acpi_pst_freq2index(freq);
1334         if (i < 0)
1335                 return EINVAL;
1336
1337         acpi_pst_global_set_pstate(i);
1338
1339         return 0;
1340 }
1341
1342 static void
1343 acpi_pst_check_csr_handler(struct cpuhelper_msg *msg)
1344 {
1345         struct acpi_pst_chmsg *pmsg = (struct acpi_pst_chmsg *)msg;
1346         int error;
1347
1348         error = acpi_pst_md->pmd_check_csr(pmsg->ch_ctrl, pmsg->ch_status);
1349         cpuhelper_replymsg(msg, error);
1350 }
1351
1352 static int
1353 acpi_pst_check_csr(struct acpi_pst_softc *sc)
1354 {
1355         struct acpi_pst_chmsg msg;
1356
1357         if (acpi_pst_md == NULL)
1358                 return 0;
1359
1360         cpuhelper_initmsg(&msg.ch_msg, &curthread->td_msgport,
1361             acpi_pst_check_csr_handler, NULL, MSGF_PRIORITY);
1362         msg.ch_ctrl = &sc->pst_creg;
1363         msg.ch_status = &sc->pst_sreg;
1364
1365         return (cpuhelper_domsg(&msg.ch_msg, sc->pst_cpuid));
1366 }
1367
1368 static void
1369 acpi_pst_check_pstates_handler(struct cpuhelper_msg *msg)
1370 {
1371         int error;
1372
1373         error = acpi_pst_md->pmd_check_pstates(acpi_pstates, acpi_npstates);
1374         cpuhelper_replymsg(msg, error);
1375 }
1376
1377 static int
1378 acpi_pst_check_pstates(struct acpi_pst_softc *sc)
1379 {
1380         struct cpuhelper_msg msg;
1381
1382         if (acpi_pst_md == NULL)
1383                 return 0;
1384
1385         cpuhelper_initmsg(&msg, &curthread->td_msgport,
1386             acpi_pst_check_pstates_handler, NULL, MSGF_PRIORITY);
1387         return (cpuhelper_domsg(&msg, sc->pst_cpuid));
1388 }
1389
1390 static void
1391 acpi_pst_init_handler(struct cpuhelper_msg *msg)
1392 {
1393         struct acpi_pst_chmsg *pmsg = (struct acpi_pst_chmsg *)msg;
1394         int error;
1395
1396         error = acpi_pst_md->pmd_init(pmsg->ch_ctrl, pmsg->ch_status);
1397         cpuhelper_replymsg(msg, error);
1398 }
1399
1400 static int
1401 acpi_pst_init(struct acpi_pst_softc *sc)
1402 {
1403         struct acpi_pst_chmsg msg;
1404
1405         if (acpi_pst_md == NULL)
1406                 return 0;
1407
1408         cpuhelper_initmsg(&msg.ch_msg, &curthread->td_msgport,
1409             acpi_pst_init_handler, NULL, MSGF_PRIORITY);
1410         msg.ch_ctrl = &sc->pst_creg;
1411         msg.ch_status = &sc->pst_sreg;
1412
1413         return (cpuhelper_domsg(&msg.ch_msg, sc->pst_cpuid));
1414 }
1415
1416 static void
1417 acpi_pst_set_pstate_handler(struct cpuhelper_msg *msg)
1418 {
1419         struct acpi_pst_chmsg *pmsg = (struct acpi_pst_chmsg *)msg;
1420         int error;
1421
1422         error = acpi_pst_md->pmd_set_pstate(pmsg->ch_ctrl, pmsg->ch_status,
1423             msg->ch_cbarg);
1424         cpuhelper_replymsg(msg, error);
1425 }
1426
1427 static int
1428 acpi_pst_set_pstate(struct acpi_pst_softc *sc, const struct acpi_pstate *pstate)
1429 {
1430         struct acpi_pst_chmsg msg;
1431
1432         KKASSERT(acpi_pst_md != NULL);
1433
1434         cpuhelper_initmsg(&msg.ch_msg, &curthread->td_msgport,
1435             acpi_pst_set_pstate_handler, __DECONST(void *, pstate),
1436             MSGF_PRIORITY);
1437         msg.ch_ctrl = &sc->pst_creg;
1438         msg.ch_status = &sc->pst_sreg;
1439
1440         return (cpuhelper_domsg(&msg.ch_msg, sc->pst_cpuid));
1441 }
1442
1443 static void
1444 acpi_pst_get_pstate_handler(struct cpuhelper_msg *msg)
1445 {
1446         struct acpi_pst_chmsg *pmsg = (struct acpi_pst_chmsg *)msg;
1447         const struct acpi_pstate *pstate;
1448
1449         pstate = acpi_pst_md->pmd_get_pstate(pmsg->ch_status, acpi_pstates,
1450             acpi_npstates);
1451         msg->ch_cbarg = __DECONST(void *, pstate);
1452         cpuhelper_replymsg(msg, 0);
1453 }
1454
1455 static const struct acpi_pstate *
1456 acpi_pst_get_pstate(struct acpi_pst_softc *sc)
1457 {
1458         struct acpi_pst_chmsg msg;
1459
1460         if (acpi_pst_md == NULL)
1461                 return 0;
1462
1463         cpuhelper_initmsg(&msg.ch_msg, &curthread->td_msgport,
1464             acpi_pst_get_pstate_handler, NULL, MSGF_PRIORITY);
1465         msg.ch_status = &sc->pst_sreg;
1466
1467         cpuhelper_domsg(&msg.ch_msg, sc->pst_cpuid);
1468         return (msg.ch_msg.ch_cbarg);
1469 }
1470
1471 static int
1472 acpi_pst_alloc_resource(device_t dev, ACPI_OBJECT *obj, int idx,
1473                         struct acpi_pst_res *res)
1474 {
1475         struct acpi_pst_softc *sc = device_get_softc(dev);
1476         int error, type;
1477
1478         /* Save GAS */
1479         error = acpi_PkgRawGas(obj, idx, &res->pr_gas);
1480         if (error)
1481                 return error;
1482
1483         /* Allocate resource, if possible */
1484         res->pr_rid = sc->pst_parent->cpu_next_rid;
1485         acpi_bus_alloc_gas(dev, &type, &res->pr_rid, &res->pr_gas, &res->pr_res, 0);
1486         if (res->pr_res != NULL) {
1487                 sc->pst_parent->cpu_next_rid++;
1488                 res->pr_bt = rman_get_bustag(res->pr_res);
1489                 res->pr_bh = rman_get_bushandle(res->pr_res);
1490         } else {
1491                 res->pr_rid = 0;
1492         }
1493         return 0;
1494 }
1495
1496 static void
1497 acpi_pst_domain_check_nproc(device_t dev, struct acpi_pst_domain *dom)
1498 {
1499         struct acpi_pst_softc *pst;
1500         int i;
1501
1502         i = 0;
1503         LIST_FOREACH(pst, &dom->pd_pstlist, pst_link)
1504                 ++i;
1505         if (i == dom->pd_nproc) {
1506                 /*
1507                  * Some stupid BIOSes will set wrong "# of processors",
1508                  * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
1509                  */
1510                 if (bootverbose) {
1511                         device_printf(dev, "domain%u already contains %d "
1512                             "P-States\n", dom->pd_dom, dom->pd_nproc);
1513                 }
1514                 dom->pd_nproc++;
1515         }
1516         KKASSERT(i < dom->pd_nproc);
1517 }
1518
1519 static int
1520 acpi_pst_eval_ppc(struct acpi_pst_softc *sc, int *sstart)
1521 {
1522         ACPI_BUFFER buf;
1523         ACPI_STATUS status;
1524         ACPI_OBJECT *obj;
1525
1526         buf.Pointer = NULL;
1527         buf.Length = ACPI_ALLOCATE_BUFFER;
1528         status = AcpiEvaluateObject(sc->pst_handle, "_PPC", NULL, &buf);
1529         if (!ACPI_FAILURE(status)) {
1530                 ACPI_OBJECT_LIST arglist;
1531                 ACPI_OBJECT arg[2];
1532
1533                 obj = (ACPI_OBJECT *)buf.Pointer;
1534                 if (obj->Type == ACPI_TYPE_INTEGER) {
1535                         if (obj->Integer.Value >= acpi_npstates) {
1536                                 /*
1537                                  * Some broken BIOSes can set this
1538                                  * to any values; let's simply start
1539                                  * from the first P-state, which
1540                                  * should be the highest frequency
1541                                  * available.
1542                                  */
1543                                 if (bootverbose) {
1544                                         device_printf(sc->pst_dev,
1545                                             "Invalid _PPC value %ju, "
1546                                             "npstates %d\n",
1547                                             (uintmax_t)obj->Integer.Value,
1548                                             acpi_npstates);
1549                                 }
1550                                 *sstart = 0;
1551                         } else {
1552                                 *sstart = obj->Integer.Value;
1553                                 if (bootverbose) {
1554                                         device_printf(sc->pst_dev, "_PPC %d\n",
1555                                             *sstart);
1556                                 }
1557                         }
1558                 } else {
1559                         device_printf(sc->pst_dev, "Invalid _PPC object\n");
1560                         AcpiOsFree(obj);
1561                         return ENXIO;
1562                 }
1563
1564                 /* Free _PPC */
1565                 AcpiOsFree(obj);
1566
1567                 /* _PPC has been successfully processed */
1568                 arglist.Pointer = arg;
1569                 arglist.Count = 2;
1570                 arg[0].Type = ACPI_TYPE_INTEGER;
1571                 arg[0].Integer.Value = 0x80;
1572                 arg[1].Type = ACPI_TYPE_INTEGER;
1573                 arg[1].Integer.Value = 0;
1574                 AcpiEvaluateObject(sc->pst_handle, "_OST", &arglist, NULL);
1575
1576                 return 0;
1577         }
1578         return ENOENT;
1579 }
1580
1581 static int
1582 acpi_pst_eval_pdl(struct acpi_pst_softc *sc, int *scount)
1583 {
1584         ACPI_BUFFER buf;
1585         ACPI_STATUS status;
1586         ACPI_OBJECT *obj;
1587
1588         buf.Pointer = NULL;
1589         buf.Length = ACPI_ALLOCATE_BUFFER;
1590         status = AcpiEvaluateObject(sc->pst_handle, "_PDL", NULL, &buf);
1591         if (!ACPI_FAILURE(status)) {
1592                 obj = (ACPI_OBJECT *)buf.Pointer;
1593                 if (obj->Type == ACPI_TYPE_INTEGER) {
1594                         if (obj->Integer.Value >= acpi_npstates) {
1595                                 device_printf(sc->pst_dev,
1596                                     "Invalid _PDL value\n");
1597                                 AcpiOsFree(obj);
1598                                 return ENXIO;
1599                         }
1600                         if (obj->Integer.Value >= acpi_pstate_start) {
1601                                 *scount = obj->Integer.Value + 1;
1602                                 if (bootverbose) {
1603                                         device_printf(sc->pst_dev, "_PDL %d\n",
1604                                             *scount);
1605                                 }
1606                         } else {
1607                                 /* Prefer _PPC as stated in ACPI 5.1 8.4.4.6 */
1608                                 device_printf(sc->pst_dev, "conflict _PDL %ju "
1609                                     "and _PPC %d, ignore\n",
1610                                     (uintmax_t)obj->Integer.Value,
1611                                     acpi_pstate_start);
1612                         }
1613                 } else {
1614                         device_printf(sc->pst_dev, "Invalid _PDL object\n");
1615                         AcpiOsFree(obj);
1616                         return ENXIO;
1617                 }
1618
1619                 /* Free _PDL */
1620                 AcpiOsFree(obj);
1621
1622                 return 0;
1623         }
1624         return ENOENT;
1625 }
1626
1627 /*
1628  * Notify is serialized by acpi task thread.
1629  */
1630 static void
1631 acpi_pst_notify(device_t dev)
1632 {
1633         struct acpi_pst_softc *sc = device_get_softc(dev);
1634         boolean_t fixup = FALSE;
1635
1636         if (!acpi_pst_handle_notify)
1637                 return;
1638
1639         /*
1640          * NOTE:
1641          * _PPC and _PDL evaluation order is critical.  _PDL
1642          * evaluation depends on _PPC evaluation.
1643          */
1644         if (sc->pst_flags & ACPI_PST_FLAG_PPC) {
1645                 int sstart = acpi_pstate_start;
1646
1647                 acpi_pst_eval_ppc(sc, &sstart);
1648                 if (acpi_pstate_start != sstart && sc->pst_cpuid == 0) {
1649                         acpi_pstate_start = sstart;
1650                         fixup = TRUE;
1651                 }
1652         }
1653         if (sc->pst_flags & ACPI_PST_FLAG_PDL) {
1654                 int scount = acpi_pstate_count;
1655
1656                 acpi_pst_eval_pdl(sc, &scount);
1657                 if (acpi_pstate_count != scount && sc->pst_cpuid == 0) {
1658                         acpi_pstate_count = scount;
1659                         fixup = TRUE;
1660                 }
1661         }
1662
1663         if (fixup && acpi_pst_md != NULL &&
1664             acpi_pst_md->pmd_set_pstate != NULL)
1665                 acpi_pst_global_fixup_pstate();
1666 }