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