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