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