1 /* $OpenBSD: acpicpu.c,v 1.95 2024/10/22 21:50:02 jsg Exp $ */
2 /*
3 * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
4 * Copyright (c) 2015 Philip Guenther <guenther@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/kernel.h> /* for tick */
21 #include <sys/signalvar.h>
22 #include <sys/sysctl.h>
23 #include <sys/systm.h>
24 #include <sys/device.h>
25 #include <sys/malloc.h>
26 #include <sys/queue.h>
27 #include <sys/atomic.h>
28
29 #include <machine/bus.h>
30 #include <machine/cpu.h>
31 #include <machine/cpufunc.h>
32 #include <machine/specialreg.h>
33
34 #include <dev/acpi/acpireg.h>
35 #include <dev/acpi/acpivar.h>
36 #include <dev/acpi/acpidev.h>
37 #include <dev/acpi/amltypes.h>
38 #include <dev/acpi/dsdt.h>
39
40 #include <sys/sensors.h>
41
42 int acpicpu_match(struct device *, void *, void *);
43 void acpicpu_attach(struct device *, struct device *, void *);
44 int acpicpu_notify(struct aml_node *, int, void *);
45 void acpicpu_setperf(int);
46 void acpicpu_setperf_ppc_change(struct acpicpu_pss *, int);
47
48 #define ACPI_STATE_C0 0x00
49 #define ACPI_STATE_C1 0x01
50 #define ACPI_STATE_C2 0x02
51 #define ACPI_STATE_C3 0x03
52
53 #define ACPI_PDC_REVID 0x1
54 #define ACPI_PDC_SMP 0xa
55 #define ACPI_PDC_MSR 0x1
56
57 /* _PDC/_OSC Intel capabilities flags */
58 #define ACPI_PDC_P_FFH 0x0001
59 #define ACPI_PDC_C_C1_HALT 0x0002
60 #define ACPI_PDC_T_FFH 0x0004
61 #define ACPI_PDC_SMP_C1PT 0x0008
62 #define ACPI_PDC_SMP_C2C3 0x0010
63 #define ACPI_PDC_SMP_P_SWCOORD 0x0020
64 #define ACPI_PDC_SMP_C_SWCOORD 0x0040
65 #define ACPI_PDC_SMP_T_SWCOORD 0x0080
66 #define ACPI_PDC_C_C1_FFH 0x0100
67 #define ACPI_PDC_C_C2C3_FFH 0x0200
68 /* reserved 0x0400 */
69 #define ACPI_PDC_P_HWCOORD 0x0800
70 #define ACPI_PDC_PPC_NOTIFY 0x1000
71
72 #define CST_METH_HALT 0
73 #define CST_METH_IO_HALT 1
74 #define CST_METH_MWAIT 2
75 #define CST_METH_GAS_IO 3
76
77 /* flags on Intel's FFH mwait method */
78 #define CST_FLAG_MWAIT_HW_COORD 0x1
79 #define CST_FLAG_MWAIT_BM_AVOIDANCE 0x2
80 #define CST_FLAG_FALLBACK 0x4000 /* fallback for broken _CST */
81 #define CST_FLAG_SKIP 0x8000 /* state is worse choice */
82
83 #define FLAGS_MWAIT_ONLY 0x02
84 #define FLAGS_BMCHECK 0x04
85 #define FLAGS_NOTHROTTLE 0x08
86 #define FLAGS_NOPSS 0x10
87 #define FLAGS_NOPCT 0x20
88
89 #define CPU_THT_EN (1L << 4)
90 #define CPU_MAXSTATE(sc) (1L << (sc)->sc_duty_wid)
91 #define CPU_STATE(sc,pct) ((pct * CPU_MAXSTATE(sc) / 100) << (sc)->sc_duty_off)
92 #define CPU_STATEMASK(sc) ((CPU_MAXSTATE(sc) - 1) << (sc)->sc_duty_off)
93
94 #define ACPI_MAX_C2_LATENCY 100
95 #define ACPI_MAX_C3_LATENCY 1000
96
97 #define CSD_COORD_SW_ALL 0xFC
98 #define CSD_COORD_SW_ANY 0xFD
99 #define CSD_COORD_HW_ALL 0xFE
100
101 /* Make sure throttling bits are valid,a=addr,o=offset,w=width */
102 #define valid_throttle(o,w,a) (a && w && (o+w)<=31 && (o>4 || (o+w)<=4))
103
104 struct acpi_cstate {
105 SLIST_ENTRY(acpi_cstate) link;
106
107 u_short state;
108 short method; /* CST_METH_* */
109 u_short flags; /* CST_FLAG_* */
110 u_short latency;
111 int power;
112 uint64_t address; /* or mwait hint */
113 };
114
115 unsigned long cst_stats[4] = { 0 };
116
117 struct acpicpu_softc {
118 struct device sc_dev;
119 int sc_cpu;
120
121 int sc_duty_wid;
122 int sc_duty_off;
123 uint32_t sc_pblk_addr;
124 int sc_pblk_len;
125 int sc_flags;
126 unsigned long sc_prev_sleep;
127 unsigned long sc_last_itime;
128
129 struct cpu_info *sc_ci;
130 SLIST_HEAD(,acpi_cstate) sc_cstates;
131
132 bus_space_tag_t sc_iot;
133 bus_space_handle_t sc_ioh;
134
135 struct acpi_softc *sc_acpi;
136 struct aml_node *sc_devnode;
137
138 int sc_pss_len; /* XXX */
139 int sc_ppc;
140 int sc_level;
141 struct acpicpu_pss *sc_pss;
142 size_t sc_pssfulllen;
143
144 struct acpicpu_pct sc_pct;
145 /* save compensation for pct access for lying bios' */
146 uint32_t sc_pct_stat_as;
147 uint32_t sc_pct_ctrl_as;
148 uint32_t sc_pct_stat_len;
149 uint32_t sc_pct_ctrl_len;
150 /*
151 * XXX: _PPC Change listener
152 * PPC changes can occur when for example a machine is disconnected
153 * from AC power and can no longer support the highest frequency or
154 * voltage when driven from the battery.
155 * Should probably be reimplemented as a list for now we assume only
156 * one listener
157 */
158 void (*sc_notify)(struct acpicpu_pss *, int);
159 };
160
161 void acpicpu_add_cstatepkg(struct aml_value *, void *);
162 void acpicpu_add_cdeppkg(struct aml_value *, void *);
163 int acpicpu_getppc(struct acpicpu_softc *);
164 int acpicpu_getpct(struct acpicpu_softc *);
165 int acpicpu_getpss(struct acpicpu_softc *);
166 int acpicpu_getcst(struct acpicpu_softc *);
167 void acpicpu_getcst_from_fadt(struct acpicpu_softc *);
168 void acpicpu_print_one_cst(struct acpi_cstate *_cx);
169 void acpicpu_print_cst(struct acpicpu_softc *_sc);
170 void acpicpu_add_cstate(struct acpicpu_softc *_sc, int _state, int _method,
171 int _flags, int _latency, int _power, uint64_t _address);
172 void acpicpu_set_pdc(struct acpicpu_softc *);
173 void acpicpu_idle(void);
174 void acpicpu_suspend(void);
175
176 #if 0
177 void acpicpu_set_throttle(struct acpicpu_softc *, int);
178 struct acpi_cstate *acpicpu_find_cstate(struct acpicpu_softc *, int);
179 #endif
180
181 const struct cfattach acpicpu_ca = {
182 sizeof(struct acpicpu_softc), acpicpu_match, acpicpu_attach
183 };
184
185 struct cfdriver acpicpu_cd = {
186 NULL, "acpicpu", DV_DULL
187 };
188
189 const char *acpicpu_hids[] = {
190 "ACPI0007",
191 NULL
192 };
193
194 extern int setperf_prio;
195
196 #if 0
197 void
198 acpicpu_set_throttle(struct acpicpu_softc *sc, int level)
199 {
200 uint32_t pbval;
201
202 if (sc->sc_flags & FLAGS_NOTHROTTLE)
203 return;
204
205 /* Disable throttling control */
206 pbval = inl(sc->sc_pblk_addr);
207 outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN);
208 if (level < 100) {
209 pbval &= ~CPU_STATEMASK(sc);
210 pbval |= CPU_STATE(sc, level);
211 outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN);
212 outl(sc->sc_pblk_addr, pbval | CPU_THT_EN);
213 }
214 }
215
216 struct acpi_cstate *
217 acpicpu_find_cstate(struct acpicpu_softc *sc, int state)
218 {
219 struct acpi_cstate *cx;
220
221 SLIST_FOREACH(cx, &sc->sc_cstates, link)
222 if (cx->state == state)
223 return cx;
224 return (NULL);
225 }
226 #endif
227
228
229 void
acpicpu_set_pdc(struct acpicpu_softc * sc)230 acpicpu_set_pdc(struct acpicpu_softc *sc)
231 {
232 struct aml_value cmd, osc_cmd[4];
233 struct aml_value res;
234 uint32_t cap;
235 uint32_t buf[3];
236
237 /* 4077A616-290C-47BE-9EBD-D87058713953 */
238 static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29,
239 0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70,
240 0x58, 0x71, 0x39, 0x53 };
241 cap = ACPI_PDC_C_C1_HALT | ACPI_PDC_P_FFH | ACPI_PDC_C_C1_FFH
242 | ACPI_PDC_C_C2C3_FFH | ACPI_PDC_SMP_P_SWCOORD | ACPI_PDC_SMP_C2C3
243 | ACPI_PDC_SMP_C1PT;
244
245 if (aml_searchname(sc->sc_devnode, "_OSC")) {
246 /* Query _OSC */
247 memset(&osc_cmd, 0, sizeof(osc_cmd));
248 osc_cmd[0].type = AML_OBJTYPE_BUFFER;
249 osc_cmd[0].v_buffer = (uint8_t *)&cpu_oscuuid;
250 osc_cmd[0].length = sizeof(cpu_oscuuid);
251
252 osc_cmd[1].type = AML_OBJTYPE_INTEGER;
253 osc_cmd[1].v_integer = 1;
254 osc_cmd[1].length = 1;
255
256 osc_cmd[2].type = AML_OBJTYPE_INTEGER;
257 osc_cmd[2].v_integer = 2;
258 osc_cmd[2].length = 1;
259
260 buf[0] = 1;
261 buf[1] = cap;
262 osc_cmd[3].type = AML_OBJTYPE_BUFFER;
263 osc_cmd[3].v_buffer = (int8_t *)&buf;
264 osc_cmd[3].length = sizeof(buf);
265
266 aml_evalname(sc->sc_acpi, sc->sc_devnode, "_OSC",
267 4, osc_cmd, &res);
268
269 if (res.type != AML_OBJTYPE_BUFFER || res.length < 8) {
270 printf(": unable to query capabilities\n");
271 aml_freevalue(&res);
272 return;
273 }
274
275 /* Evaluate _OSC */
276 memset(&osc_cmd, 0, sizeof(osc_cmd));
277 osc_cmd[0].type = AML_OBJTYPE_BUFFER;
278 osc_cmd[0].v_buffer = (uint8_t *)&cpu_oscuuid;
279 osc_cmd[0].length = sizeof(cpu_oscuuid);
280
281 osc_cmd[1].type = AML_OBJTYPE_INTEGER;
282 osc_cmd[1].v_integer = 1;
283 osc_cmd[1].length = 1;
284
285 osc_cmd[2].type = AML_OBJTYPE_INTEGER;
286 osc_cmd[2].v_integer = 2;
287 osc_cmd[2].length = 1;
288
289 buf[0] = 0;
290 buf[1] = (*(uint32_t *)&res.v_buffer[4]) & cap;
291 osc_cmd[3].type = AML_OBJTYPE_BUFFER;
292 osc_cmd[3].v_buffer = (int8_t *)&buf;
293 osc_cmd[3].length = sizeof(buf);
294
295 aml_freevalue(&res);
296
297 aml_evalname(sc->sc_acpi, sc->sc_devnode, "_OSC",
298 4, osc_cmd, NULL);
299 } else {
300 /* Evaluate _PDC */
301 memset(&cmd, 0, sizeof(cmd));
302 cmd.type = AML_OBJTYPE_BUFFER;
303 cmd.v_buffer = (uint8_t *)&buf;
304 cmd.length = sizeof(buf);
305
306 buf[0] = ACPI_PDC_REVID;
307 buf[1] = 1;
308 buf[2] = cap;
309
310 aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PDC",
311 1, &cmd, NULL);
312 }
313 }
314
315 /*
316 * sanity check mwait hints against what cpuid told us
317 * ...but because intel screwed up, just check whether cpuid says
318 * the given state has _any_ substates.
319 */
320 static int
check_mwait_hints(int state,int hints)321 check_mwait_hints(int state, int hints)
322 {
323 int cstate;
324 int num_substates;
325
326 if (cpu_mwait_size == 0)
327 return (0);
328 cstate = ((hints >> 4) & 0xf) + 1;
329 if (cstate == 16)
330 cstate = 0;
331 else if (cstate > 7) {
332 /* out of range of test against CPUID; just trust'em */
333 return (1);
334 }
335 num_substates = (cpu_mwait_states >> (4 * cstate)) & 0xf;
336 if (num_substates == 0) {
337 printf(": C%d bad (state %d has no substates)", state, cstate);
338 return (0);
339 }
340 return (1);
341 }
342
343 void
acpicpu_add_cstate(struct acpicpu_softc * sc,int state,int method,int flags,int latency,int power,uint64_t address)344 acpicpu_add_cstate(struct acpicpu_softc *sc, int state, int method,
345 int flags, int latency, int power, uint64_t address)
346 {
347 struct acpi_cstate *cx;
348
349 dnprintf(10," C%d: latency:.%4x power:%.4x addr:%.16llx\n",
350 state, latency, power, address);
351
352 /* add a new state, or overwrite the fallback C1 state? */
353 if (state != ACPI_STATE_C1 ||
354 (cx = SLIST_FIRST(&sc->sc_cstates)) == NULL ||
355 (cx->flags & CST_FLAG_FALLBACK) == 0) {
356 cx = malloc(sizeof(*cx), M_DEVBUF, M_WAITOK);
357 SLIST_INSERT_HEAD(&sc->sc_cstates, cx, link);
358 }
359
360 cx->state = state;
361 cx->method = method;
362 cx->flags = flags;
363 cx->latency = latency;
364 cx->power = power;
365 cx->address = address;
366 }
367
368 /* Found a _CST object, add new cstate for each entry */
369 void
acpicpu_add_cstatepkg(struct aml_value * val,void * arg)370 acpicpu_add_cstatepkg(struct aml_value *val, void *arg)
371 {
372 struct acpicpu_softc *sc = arg;
373 uint64_t addr;
374 struct acpi_grd *grd;
375 int state, method, flags;
376
377 #if defined(ACPI_DEBUG) && !defined(SMALL_KERNEL)
378 aml_showvalue(val);
379 #endif
380 if (val->type != AML_OBJTYPE_PACKAGE || val->length != 4)
381 return;
382
383 /* range and sanity checks */
384 state = val->v_package[1]->v_integer;
385 if (state < 0 || state > 4)
386 return;
387 if (val->v_package[0]->type != AML_OBJTYPE_BUFFER) {
388 printf(": C%d (unexpected ACPI object type %d)",
389 state, val->v_package[0]->type);
390 return;
391 }
392 grd = (struct acpi_grd *)val->v_package[0]->v_buffer;
393 if (val->v_package[0]->length != sizeof(*grd) + 2 ||
394 grd->grd_descriptor != LR_GENREGISTER ||
395 grd->grd_length != sizeof(grd->grd_gas) ||
396 val->v_package[0]->v_buffer[sizeof(*grd)] != SRT_ENDTAG) {
397 printf(": C%d (bogo buffer)", state);
398 return;
399 }
400
401 flags = 0;
402 switch (grd->grd_gas.address_space_id) {
403 case GAS_FUNCTIONAL_FIXED:
404 if (grd->grd_gas.register_bit_width == 0) {
405 method = CST_METH_HALT;
406 addr = 0;
407 } else {
408 /*
409 * In theory we should only do this for
410 * vendor 1 == Intel but other values crop up,
411 * presumably due to the normal ACPI spec confusion.
412 */
413 switch (grd->grd_gas.register_bit_offset) {
414 case 0x1:
415 method = CST_METH_IO_HALT;
416 addr = grd->grd_gas.address;
417
418 /* i386 and amd64 I/O space is 16bits */
419 if (addr > 0xffff) {
420 printf(": C%d (bogo I/O addr %llx)",
421 state, addr);
422 return;
423 }
424 break;
425 case 0x2:
426 addr = grd->grd_gas.address;
427 if (!check_mwait_hints(state, addr))
428 return;
429 method = CST_METH_MWAIT;
430 flags = grd->grd_gas.access_size;
431 break;
432 default:
433 printf(": C%d (unknown FFH class %d)",
434 state, grd->grd_gas.register_bit_offset);
435 return;
436 }
437 }
438 break;
439
440 case GAS_SYSTEM_IOSPACE:
441 addr = grd->grd_gas.address;
442 if (grd->grd_gas.register_bit_width != 8 ||
443 grd->grd_gas.register_bit_offset != 0) {
444 printf(": C%d (unhandled %s spec: %d/%d)", state,
445 "I/O", grd->grd_gas.register_bit_width,
446 grd->grd_gas.register_bit_offset);
447 return;
448 }
449 method = CST_METH_GAS_IO;
450 break;
451
452 default:
453 /* dump the GAS for analysis */
454 {
455 int i;
456 printf(": C%d (unhandled GAS:", state);
457 for (i = 0; i < sizeof(grd->grd_gas); i++)
458 printf(" %#x", ((u_char *)&grd->grd_gas)[i]);
459 printf(")");
460
461 }
462 return;
463 }
464
465 acpicpu_add_cstate(sc, state, method, flags,
466 val->v_package[2]->v_integer, val->v_package[3]->v_integer, addr);
467 }
468
469
470 /* Found a _CSD object, print the dependency */
471 void
acpicpu_add_cdeppkg(struct aml_value * val,void * arg)472 acpicpu_add_cdeppkg(struct aml_value *val, void *arg)
473 {
474 int64_t num_proc, coord_type, domain, cindex;
475
476 /*
477 * errors: unexpected object type, bad length, mismatched length,
478 * and bad CSD revision
479 */
480 if (val->type != AML_OBJTYPE_PACKAGE || val->length < 6 ||
481 val->length != val->v_package[0]->v_integer ||
482 val->v_package[1]->v_integer != 0) {
483 #if 1 || defined(ACPI_DEBUG) && !defined(SMALL_KERNEL)
484 aml_showvalue(val);
485 #endif
486 printf("bogus CSD\n");
487 return;
488 }
489
490 /* coordinating 'among' one CPU is trivial, ignore */
491 num_proc = val->v_package[4]->v_integer;
492 if (num_proc == 1)
493 return;
494
495 /* we practically assume the hardware will coordinate, so ignore */
496 coord_type = val->v_package[3]->v_integer;
497 if (coord_type == CSD_COORD_HW_ALL)
498 return;
499
500 domain = val->v_package[2]->v_integer;
501 cindex = val->v_package[5]->v_integer;
502 printf(": CSD (c=%#llx d=%lld n=%lld i=%lli)",
503 coord_type, domain, num_proc, cindex);
504 }
505
506 int
acpicpu_getcst(struct acpicpu_softc * sc)507 acpicpu_getcst(struct acpicpu_softc *sc)
508 {
509 struct aml_value res;
510 struct acpi_cstate *cx, *next_cx;
511 int use_nonmwait;
512
513 /* delete the existing list */
514 while ((cx = SLIST_FIRST(&sc->sc_cstates)) != NULL) {
515 SLIST_REMOVE_HEAD(&sc->sc_cstates, link);
516 free(cx, M_DEVBUF, sizeof(*cx));
517 }
518
519 /* provide a fallback C1-via-halt in case _CST's C1 is bogus */
520 acpicpu_add_cstate(sc, ACPI_STATE_C1, CST_METH_HALT,
521 CST_FLAG_FALLBACK, 1, -1, 0);
522
523 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CST", 0, NULL, &res))
524 return (1);
525
526 aml_foreachpkg(&res, 1, acpicpu_add_cstatepkg, sc);
527 aml_freevalue(&res);
528
529 /* only have fallback state? then no _CST objects were understood */
530 cx = SLIST_FIRST(&sc->sc_cstates);
531 if (cx->flags & CST_FLAG_FALLBACK)
532 return (1);
533
534 /*
535 * Skip states >= C2 if the CPU's LAPIC timer stops in deep
536 * states (i.e., it doesn't have the 'ARAT' bit set).
537 * Also keep track if all the states we'll use use mwait.
538 */
539 use_nonmwait = 0;
540 while ((next_cx = SLIST_NEXT(cx, link)) != NULL) {
541 if (cx->state > 1 &&
542 (sc->sc_ci->ci_feature_tpmflags & TPM_ARAT) == 0)
543 cx->flags |= CST_FLAG_SKIP;
544 else if (cx->method != CST_METH_MWAIT)
545 use_nonmwait = 1;
546 cx = next_cx;
547 }
548 if (use_nonmwait)
549 sc->sc_flags &= ~FLAGS_MWAIT_ONLY;
550 else
551 sc->sc_flags |= FLAGS_MWAIT_ONLY;
552
553 if (!aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CSD", 0, NULL, &res)) {
554 aml_foreachpkg(&res, 1, acpicpu_add_cdeppkg, sc);
555 aml_freevalue(&res);
556 }
557
558 return (0);
559 }
560
561 /*
562 * old-style fixed C-state info in the FADT.
563 * Note that this has extra restrictions on values and flags.
564 */
565 void
acpicpu_getcst_from_fadt(struct acpicpu_softc * sc)566 acpicpu_getcst_from_fadt(struct acpicpu_softc *sc)
567 {
568 struct acpi_fadt *fadt = sc->sc_acpi->sc_fadt;
569 int flags;
570
571 /* FADT has to set flag to do C2 and higher on MP */
572 if ((fadt->flags & FADT_P_LVL2_UP) == 0 && ncpus > 1)
573 return;
574
575 /* skip these C2 and C3 states if the CPU doesn't have ARAT */
576 flags = (sc->sc_ci->ci_feature_tpmflags & TPM_ARAT)
577 ? 0 : CST_FLAG_SKIP;
578
579 /* Some systems don't export a full PBLK; reduce functionality */
580 if (sc->sc_pblk_len >= 5 && fadt->p_lvl2_lat <= ACPI_MAX_C2_LATENCY) {
581 acpicpu_add_cstate(sc, ACPI_STATE_C2, CST_METH_GAS_IO, flags,
582 fadt->p_lvl2_lat, -1, sc->sc_pblk_addr + 4);
583 }
584 if (sc->sc_pblk_len >= 6 && fadt->p_lvl3_lat <= ACPI_MAX_C3_LATENCY)
585 acpicpu_add_cstate(sc, ACPI_STATE_C3, CST_METH_GAS_IO, flags,
586 fadt->p_lvl3_lat, -1, sc->sc_pblk_addr + 5);
587 }
588
589
590 void
acpicpu_print_one_cst(struct acpi_cstate * cx)591 acpicpu_print_one_cst(struct acpi_cstate *cx)
592 {
593 const char *meth = "";
594 int show_addr = 0;
595
596 switch (cx->method) {
597 case CST_METH_IO_HALT:
598 show_addr = 1;
599 /* fallthrough */
600 case CST_METH_HALT:
601 meth = " halt";
602 break;
603
604 case CST_METH_MWAIT:
605 meth = " mwait";
606 show_addr = cx->address != 0;
607 break;
608
609 case CST_METH_GAS_IO:
610 meth = " io";
611 show_addr = 1;
612 break;
613
614 }
615
616 printf(" %sC%d(", (cx->flags & CST_FLAG_SKIP ? "!" : ""), cx->state);
617 if (cx->power != -1)
618 printf("%d", cx->power);
619 printf("@%d%s", cx->latency, meth);
620 if (cx->flags & ~CST_FLAG_SKIP) {
621 if (cx->flags & CST_FLAG_FALLBACK)
622 printf("!");
623 else
624 printf(".%x", (cx->flags & ~CST_FLAG_SKIP));
625 }
626 if (show_addr)
627 printf("@0x%llx", cx->address);
628 printf(")");
629 }
630
631 void
acpicpu_print_cst(struct acpicpu_softc * sc)632 acpicpu_print_cst(struct acpicpu_softc *sc)
633 {
634 struct acpi_cstate *cx;
635 int i;
636
637 if (!SLIST_EMPTY(&sc->sc_cstates)) {
638 printf(":");
639
640 i = 0;
641 SLIST_FOREACH(cx, &sc->sc_cstates, link) {
642 if (i++)
643 printf(",");
644 acpicpu_print_one_cst(cx);
645 }
646 }
647 }
648
649
650 int
acpicpu_match(struct device * parent,void * match,void * aux)651 acpicpu_match(struct device *parent, void *match, void *aux)
652 {
653 struct acpi_attach_args *aa = aux;
654 struct cfdata *cf = match;
655 struct acpi_softc *acpi = (struct acpi_softc *)parent;
656 CPU_INFO_ITERATOR cii;
657 struct cpu_info *ci;
658 int64_t uid;
659
660 if (acpi_matchhids(aa, acpicpu_hids, cf->cf_driver->cd_name) &&
661 aa->aaa_node && aa->aaa_node->value &&
662 aa->aaa_node->value->type == AML_OBJTYPE_DEVICE) {
663 /*
664 * Record that we've seen a Device() CPU object,
665 * so we won't attach any Processor() nodes.
666 */
667 acpi->sc_skip_processor = 1;
668
669 /* Only match if we can find a CPU with the right ID */
670 if (aml_evalinteger(acpi, aa->aaa_node, "_UID", 0,
671 NULL, &uid) == 0)
672 CPU_INFO_FOREACH(cii, ci)
673 if (ci->ci_acpi_proc_id == uid)
674 return (1);
675
676 return (0);
677 }
678
679 /* sanity */
680 if (aa->aaa_name == NULL ||
681 strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
682 aa->aaa_table != NULL)
683 return (0);
684
685 return (1);
686 }
687
688 void
acpicpu_attach(struct device * parent,struct device * self,void * aux)689 acpicpu_attach(struct device *parent, struct device *self, void *aux)
690 {
691 struct acpicpu_softc *sc = (struct acpicpu_softc *)self;
692 struct acpi_attach_args *aa = aux;
693 struct aml_value res;
694 int64_t uid;
695 int i;
696 uint32_t status = 0;
697 CPU_INFO_ITERATOR cii;
698 struct cpu_info *ci;
699
700 sc->sc_acpi = (struct acpi_softc *)parent;
701 sc->sc_devnode = aa->aaa_node;
702
703 SLIST_INIT(&sc->sc_cstates);
704
705 if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode,
706 "_UID", 0, NULL, &uid) == 0)
707 sc->sc_cpu = uid;
708
709 if (aml_evalnode(sc->sc_acpi, sc->sc_devnode, 0, NULL, &res) == 0) {
710 if (res.type == AML_OBJTYPE_PROCESSOR) {
711 sc->sc_cpu = res.v_processor.proc_id;
712 sc->sc_pblk_addr = res.v_processor.proc_addr;
713 sc->sc_pblk_len = res.v_processor.proc_len;
714 }
715 aml_freevalue(&res);
716 }
717 sc->sc_duty_off = sc->sc_acpi->sc_fadt->duty_offset;
718 sc->sc_duty_wid = sc->sc_acpi->sc_fadt->duty_width;
719
720 /* link in the matching cpu_info */
721 CPU_INFO_FOREACH(cii, ci)
722 if (ci->ci_acpi_proc_id == sc->sc_cpu) {
723 ci->ci_acpicpudev = self;
724 sc->sc_ci = ci;
725 break;
726 }
727 if (ci == NULL) {
728 printf(": no cpu matching ACPI ID %d\n", sc->sc_cpu);
729 return;
730 }
731
732 sc->sc_prev_sleep = 1000000;
733
734 acpicpu_set_pdc(sc);
735
736 if (!valid_throttle(sc->sc_duty_off, sc->sc_duty_wid, sc->sc_pblk_addr))
737 sc->sc_flags |= FLAGS_NOTHROTTLE;
738 #ifdef ACPI_DEBUG
739 printf(": %s: ", sc->sc_devnode->name);
740 printf("\n: hdr:%x pblk:%x,%x duty:%x,%x pstate:%x "
741 "(%ld throttling states)\n", sc->sc_acpi->sc_fadt->hdr_revision,
742 sc->sc_pblk_addr, sc->sc_pblk_len, sc->sc_duty_off,
743 sc->sc_duty_wid, sc->sc_acpi->sc_fadt->pstate_cnt,
744 CPU_MAXSTATE(sc));
745 #endif
746
747 /* Get C-States from _CST or FADT */
748 if (acpicpu_getcst(sc) || SLIST_EMPTY(&sc->sc_cstates))
749 acpicpu_getcst_from_fadt(sc);
750 else {
751 /* Notify BIOS we use _CST objects */
752 if (sc->sc_acpi->sc_fadt->cst_cnt) {
753 acpi_write_pmreg(sc->sc_acpi, ACPIREG_SMICMD, 0,
754 sc->sc_acpi->sc_fadt->cst_cnt);
755 }
756 }
757 if (!SLIST_EMPTY(&sc->sc_cstates)) {
758 extern uint32_t acpi_force_bm;
759
760 cpu_idle_cycle_fcn = &acpicpu_idle;
761 cpu_suspend_cycle_fcn = &acpicpu_suspend;
762
763 /*
764 * C3 (and maybe C2?) needs BM_RLD to be set to
765 * wake the system
766 */
767 if (SLIST_FIRST(&sc->sc_cstates)->state > 1 && acpi_force_bm == 0) {
768 uint16_t en = acpi_read_pmreg(sc->sc_acpi,
769 ACPIREG_PM1_CNT, 0);
770 if ((en & ACPI_PM1_BM_RLD) == 0) {
771 acpi_write_pmreg(sc->sc_acpi, ACPIREG_PM1_CNT,
772 0, en | ACPI_PM1_BM_RLD);
773 acpi_force_bm = ACPI_PM1_BM_RLD;
774 }
775 }
776 }
777
778 if (acpicpu_getpss(sc)) {
779 sc->sc_flags |= FLAGS_NOPSS;
780 } else {
781 #ifdef ACPI_DEBUG
782 for (i = 0; i < sc->sc_pss_len; i++) {
783 dnprintf(20, "%d %d %d %d %d %d\n",
784 sc->sc_pss[i].pss_core_freq,
785 sc->sc_pss[i].pss_power,
786 sc->sc_pss[i].pss_trans_latency,
787 sc->sc_pss[i].pss_bus_latency,
788 sc->sc_pss[i].pss_ctrl,
789 sc->sc_pss[i].pss_status);
790 }
791 dnprintf(20, "\n");
792 #endif
793 if (sc->sc_pss_len == 0) {
794 /* this should never happen */
795 printf("%s: invalid _PSS length\n", DEVNAME(sc));
796 sc->sc_flags |= FLAGS_NOPSS;
797 }
798
799 acpicpu_getppc(sc);
800 if (acpicpu_getpct(sc))
801 sc->sc_flags |= FLAGS_NOPCT;
802 else if (sc->sc_pss_len > 0) {
803 /* Notify BIOS we are handling p-states */
804 if (sc->sc_acpi->sc_fadt->pstate_cnt) {
805 acpi_write_pmreg(sc->sc_acpi, ACPIREG_SMICMD,
806 0, sc->sc_acpi->sc_fadt->pstate_cnt);
807 }
808
809 aml_register_notify(sc->sc_devnode, NULL,
810 acpicpu_notify, sc, ACPIDEV_NOPOLL);
811
812 acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
813 sc->sc_pct.pct_status.grd_gas.address_space_id,
814 sc->sc_pct.pct_status.grd_gas.address,
815 sc->sc_pct_stat_as, sc->sc_pct_stat_as, &status);
816 sc->sc_level = (100 / sc->sc_pss_len) *
817 (sc->sc_pss_len - status);
818 dnprintf(20, "%s: cpu index %d, percentage %d\n",
819 DEVNAME(sc), status, sc->sc_level);
820 if (setperf_prio < 30) {
821 cpu_setperf = acpicpu_setperf;
822 acpicpu_set_notify(acpicpu_setperf_ppc_change);
823 setperf_prio = 30;
824 acpi_hasprocfvs = 1;
825 }
826 }
827 }
828
829 /*
830 * Nicely enumerate what power management capabilities
831 * ACPI CPU provides.
832 */
833 acpicpu_print_cst(sc);
834 if (!(sc->sc_flags & (FLAGS_NOPSS | FLAGS_NOPCT)) ||
835 !(sc->sc_flags & FLAGS_NOPSS)) {
836 printf("%c ", SLIST_EMPTY(&sc->sc_cstates) ? ':' : ',');
837
838 /*
839 * If acpicpu is itself providing the capability to transition
840 * states, enumerate them in the fashion that est and powernow
841 * would.
842 */
843 if (!(sc->sc_flags & (FLAGS_NOPSS | FLAGS_NOPCT))) {
844 printf("FVS, ");
845 for (i = 0; i < sc->sc_pss_len - 1; i++)
846 printf("%d, ", sc->sc_pss[i].pss_core_freq);
847 printf("%d MHz", sc->sc_pss[i].pss_core_freq);
848 } else
849 printf("PSS");
850 }
851
852 printf("\n");
853 }
854
855 int
acpicpu_getppc(struct acpicpu_softc * sc)856 acpicpu_getppc(struct acpicpu_softc *sc)
857 {
858 struct aml_value res;
859
860 sc->sc_ppc = 0;
861
862 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PPC", 0, NULL, &res)) {
863 dnprintf(10, "%s: no _PPC\n", DEVNAME(sc));
864 return (1);
865 }
866
867 sc->sc_ppc = aml_val2int(&res);
868 dnprintf(10, "%s: _PPC: %d\n", DEVNAME(sc), sc->sc_ppc);
869 aml_freevalue(&res);
870
871 return (0);
872 }
873
874 int
acpicpu_getpct(struct acpicpu_softc * sc)875 acpicpu_getpct(struct acpicpu_softc *sc)
876 {
877 struct aml_value res;
878 int rv = 1;
879
880 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PCT", 0, NULL, &res)) {
881 dnprintf(20, "%s: no _PCT\n", DEVNAME(sc));
882 return (1);
883 }
884
885 if (res.length != 2) {
886 dnprintf(20, "%s: %s: invalid _PCT length\n", DEVNAME(sc),
887 sc->sc_devnode->name);
888 return (1);
889 }
890
891 memcpy(&sc->sc_pct.pct_ctrl, res.v_package[0]->v_buffer,
892 sizeof sc->sc_pct.pct_ctrl);
893 if (sc->sc_pct.pct_ctrl.grd_gas.address_space_id ==
894 GAS_FUNCTIONAL_FIXED) {
895 dnprintf(20, "CTRL GASIO is functional fixed hardware.\n");
896 goto ffh;
897 }
898
899 memcpy(&sc->sc_pct.pct_status, res.v_package[1]->v_buffer,
900 sizeof sc->sc_pct.pct_status);
901 if (sc->sc_pct.pct_status.grd_gas.address_space_id ==
902 GAS_FUNCTIONAL_FIXED) {
903 dnprintf(20, "CTRL GASIO is functional fixed hardware.\n");
904 goto ffh;
905 }
906
907 dnprintf(10, "_PCT(ctrl) : %02x %04x %02x %02x %02x %02x %016llx\n",
908 sc->sc_pct.pct_ctrl.grd_descriptor,
909 sc->sc_pct.pct_ctrl.grd_length,
910 sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
911 sc->sc_pct.pct_ctrl.grd_gas.register_bit_width,
912 sc->sc_pct.pct_ctrl.grd_gas.register_bit_offset,
913 sc->sc_pct.pct_ctrl.grd_gas.access_size,
914 sc->sc_pct.pct_ctrl.grd_gas.address);
915
916 dnprintf(10, "_PCT(status): %02x %04x %02x %02x %02x %02x %016llx\n",
917 sc->sc_pct.pct_status.grd_descriptor,
918 sc->sc_pct.pct_status.grd_length,
919 sc->sc_pct.pct_status.grd_gas.address_space_id,
920 sc->sc_pct.pct_status.grd_gas.register_bit_width,
921 sc->sc_pct.pct_status.grd_gas.register_bit_offset,
922 sc->sc_pct.pct_status.grd_gas.access_size,
923 sc->sc_pct.pct_status.grd_gas.address);
924
925 /* if not set assume single 32 bit access */
926 sc->sc_pct_stat_as = sc->sc_pct.pct_status.grd_gas.register_bit_width
927 / 8;
928 if (sc->sc_pct_stat_as == 0)
929 sc->sc_pct_stat_as = 4;
930 sc->sc_pct_ctrl_as = sc->sc_pct.pct_ctrl.grd_gas.register_bit_width / 8;
931 if (sc->sc_pct_ctrl_as == 0)
932 sc->sc_pct_ctrl_as = 4;
933 sc->sc_pct_stat_len = sc->sc_pct.pct_status.grd_gas.access_size;
934 if (sc->sc_pct_stat_len == 0)
935 sc->sc_pct_stat_len = sc->sc_pct_stat_as;
936 sc->sc_pct_ctrl_len = sc->sc_pct.pct_ctrl.grd_gas.access_size;
937 if (sc->sc_pct_ctrl_len == 0)
938 sc->sc_pct_ctrl_len = sc->sc_pct_ctrl_as;
939
940 rv = 0;
941 ffh:
942 aml_freevalue(&res);
943 return (rv);
944 }
945
946 int
acpicpu_getpss(struct acpicpu_softc * sc)947 acpicpu_getpss(struct acpicpu_softc *sc)
948 {
949 struct aml_value res;
950 int i, c, cf;
951
952 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSS", 0, NULL, &res)) {
953 dprintf("%s: no _PSS\n", DEVNAME(sc));
954 return (1);
955 }
956
957 free(sc->sc_pss, M_DEVBUF, sc->sc_pssfulllen);
958
959 sc->sc_pss = mallocarray(res.length, sizeof(*sc->sc_pss), M_DEVBUF,
960 M_WAITOK | M_ZERO);
961 sc->sc_pssfulllen = res.length * sizeof(*sc->sc_pss);
962
963 c = 0;
964 for (i = 0; i < res.length; i++) {
965 cf = aml_val2int(res.v_package[i]->v_package[0]);
966
967 /* This heuristic comes from FreeBSDs
968 * dev/acpica/acpi_perf.c to weed out invalid PSS entries.
969 */
970 if (cf == sc->sc_pss[c].pss_core_freq) {
971 printf("%s: struck PSS entry, core frequency equals "
972 " last\n", sc->sc_dev.dv_xname);
973 continue;
974 }
975
976 if (cf == 0xFFFF || cf == 0x9999 || cf == 99999 || cf == 0) {
977 printf("%s: struck PSS entry, inappropriate core "
978 "frequency value\n", sc->sc_dev.dv_xname);
979 continue;
980 }
981
982 sc->sc_pss[c].pss_core_freq = cf;
983 sc->sc_pss[c].pss_power = aml_val2int(
984 res.v_package[i]->v_package[1]);
985 sc->sc_pss[c].pss_trans_latency = aml_val2int(
986 res.v_package[i]->v_package[2]);
987 sc->sc_pss[c].pss_bus_latency = aml_val2int(
988 res.v_package[i]->v_package[3]);
989 sc->sc_pss[c].pss_ctrl = aml_val2int(
990 res.v_package[i]->v_package[4]);
991 sc->sc_pss[c].pss_status = aml_val2int(
992 res.v_package[i]->v_package[5]);
993 c++;
994 }
995 sc->sc_pss_len = c;
996
997 aml_freevalue(&res);
998
999 return (0);
1000 }
1001
1002 int
acpicpu_fetch_pss(struct acpicpu_pss ** pss)1003 acpicpu_fetch_pss(struct acpicpu_pss **pss)
1004 {
1005 struct acpicpu_softc *sc;
1006
1007 /*
1008 * XXX: According to the ACPI spec in an SMP system all processors
1009 * are supposed to support the same states. For now we pray
1010 * the bios ensures this...
1011 */
1012
1013 sc = (struct acpicpu_softc *)cpu_info_primary.ci_acpicpudev;
1014 if (!sc)
1015 return 0;
1016 *pss = sc->sc_pss;
1017
1018 return (sc->sc_pss_len);
1019 }
1020
1021 int
acpicpu_notify(struct aml_node * node,int notify_type,void * arg)1022 acpicpu_notify(struct aml_node *node, int notify_type, void *arg)
1023 {
1024 struct acpicpu_softc *sc = arg;
1025
1026 dnprintf(10, "acpicpu_notify: %.2x %s\n", notify_type,
1027 sc->sc_devnode->name);
1028
1029 switch (notify_type) {
1030 case 0x80: /* _PPC changed, retrieve new values */
1031 acpicpu_getppc(sc);
1032 acpicpu_getpss(sc);
1033 if (sc->sc_notify)
1034 sc->sc_notify(sc->sc_pss, sc->sc_pss_len);
1035 break;
1036
1037 case 0x81: /* _CST changed, retrieve new values */
1038 acpicpu_getcst(sc);
1039 printf("%s: notify", DEVNAME(sc));
1040 acpicpu_print_cst(sc);
1041 printf("\n");
1042 break;
1043
1044 default:
1045 printf("%s: unhandled cpu event %x\n", DEVNAME(sc),
1046 notify_type);
1047 break;
1048 }
1049
1050 return (0);
1051 }
1052
1053 void
acpicpu_set_notify(void (* func)(struct acpicpu_pss *,int))1054 acpicpu_set_notify(void (*func)(struct acpicpu_pss *, int))
1055 {
1056 struct acpicpu_softc *sc;
1057
1058 sc = (struct acpicpu_softc *)cpu_info_primary.ci_acpicpudev;
1059 if (sc != NULL)
1060 sc->sc_notify = func;
1061 }
1062
1063 void
acpicpu_setperf_ppc_change(struct acpicpu_pss * pss,int npss)1064 acpicpu_setperf_ppc_change(struct acpicpu_pss *pss, int npss)
1065 {
1066 struct acpicpu_softc *sc;
1067
1068 sc = (struct acpicpu_softc *)cpu_info_primary.ci_acpicpudev;
1069
1070 if (sc != NULL)
1071 cpu_setperf(sc->sc_level);
1072 }
1073
1074 void
acpicpu_setperf(int level)1075 acpicpu_setperf(int level)
1076 {
1077 struct acpicpu_softc *sc;
1078 struct acpicpu_pss *pss = NULL;
1079 int idx, len;
1080 uint32_t status = 0;
1081
1082 sc = (struct acpicpu_softc *)curcpu()->ci_acpicpudev;
1083
1084 dnprintf(10, "%s: acpicpu setperf level %d\n",
1085 sc->sc_devnode->name, level);
1086
1087 if (level < 0 || level > 100) {
1088 dnprintf(10, "%s: acpicpu setperf illegal percentage\n",
1089 sc->sc_devnode->name);
1090 return;
1091 }
1092
1093 /*
1094 * XXX this should be handled more gracefully and it needs to also do
1095 * the duty cycle method instead of pss exclusively
1096 */
1097 if (sc->sc_flags & FLAGS_NOPSS || sc->sc_flags & FLAGS_NOPCT) {
1098 dnprintf(10, "%s: acpicpu no _PSS or _PCT\n",
1099 sc->sc_devnode->name);
1100 return;
1101 }
1102
1103 if (sc->sc_ppc)
1104 len = sc->sc_ppc;
1105 else
1106 len = sc->sc_pss_len;
1107 idx = (len - 1) - (level / (100 / len));
1108 if (idx < 0)
1109 idx = 0;
1110
1111 if (sc->sc_ppc)
1112 idx += sc->sc_pss_len - sc->sc_ppc;
1113
1114 if (idx > sc->sc_pss_len)
1115 idx = sc->sc_pss_len - 1;
1116
1117 dnprintf(10, "%s: acpicpu setperf index %d pss_len %d ppc %d\n",
1118 sc->sc_devnode->name, idx, sc->sc_pss_len, sc->sc_ppc);
1119
1120 pss = &sc->sc_pss[idx];
1121
1122 #ifdef ACPI_DEBUG
1123 /* keep this for now since we will need this for debug in the field */
1124 printf("0 status: %x %llx %u %u ctrl: %x %llx %u %u\n",
1125 sc->sc_pct.pct_status.grd_gas.address_space_id,
1126 sc->sc_pct.pct_status.grd_gas.address,
1127 sc->sc_pct_stat_as, sc->sc_pct_stat_len,
1128 sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
1129 sc->sc_pct.pct_ctrl.grd_gas.address,
1130 sc->sc_pct_ctrl_as, sc->sc_pct_ctrl_len);
1131 #endif
1132 acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
1133 sc->sc_pct.pct_status.grd_gas.address_space_id,
1134 sc->sc_pct.pct_status.grd_gas.address, sc->sc_pct_stat_as,
1135 sc->sc_pct_stat_len, &status);
1136 dnprintf(20, "1 status: %u <- %u\n", status, pss->pss_status);
1137
1138 /* Are we already at the requested frequency? */
1139 if (status == pss->pss_status)
1140 return;
1141
1142 acpi_gasio(sc->sc_acpi, ACPI_IOWRITE,
1143 sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
1144 sc->sc_pct.pct_ctrl.grd_gas.address, sc->sc_pct_ctrl_as,
1145 sc->sc_pct_ctrl_len, &pss->pss_ctrl);
1146 dnprintf(20, "pss_ctrl: %x\n", pss->pss_ctrl);
1147
1148 acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
1149 sc->sc_pct.pct_status.grd_gas.address_space_id,
1150 sc->sc_pct.pct_status.grd_gas.address, sc->sc_pct_stat_as,
1151 sc->sc_pct_stat_as, &status);
1152 dnprintf(20, "2 status: %d\n", status);
1153
1154 /* Did the transition succeed? */
1155 if (status == pss->pss_status) {
1156 cpuspeed = pss->pss_core_freq;
1157 sc->sc_level = level;
1158 } else
1159 printf("%s: acpicpu setperf failed to alter frequency\n",
1160 sc->sc_devnode->name);
1161 }
1162
1163 void
acpicpu_idle(void)1164 acpicpu_idle(void)
1165 {
1166 struct cpu_info *ci = curcpu();
1167 struct acpicpu_softc *sc = (struct acpicpu_softc *)ci->ci_acpicpudev;
1168 struct acpi_cstate *best, *cx;
1169 unsigned long itime;
1170
1171 if (sc == NULL) {
1172 __asm volatile("sti");
1173 panic("null acpicpu");
1174 }
1175
1176 /* possibly update the MWAIT_ONLY flag in cpu_info */
1177 if (sc->sc_flags & FLAGS_MWAIT_ONLY) {
1178 if ((ci->ci_mwait & MWAIT_ONLY) == 0)
1179 atomic_setbits_int(&ci->ci_mwait, MWAIT_ONLY);
1180 } else if (ci->ci_mwait & MWAIT_ONLY)
1181 atomic_clearbits_int(&ci->ci_mwait, MWAIT_ONLY);
1182
1183 /*
1184 * Find the first state with a latency we'll accept, ignoring
1185 * states marked skippable
1186 */
1187 best = cx = SLIST_FIRST(&sc->sc_cstates);
1188 while ((cx->flags & CST_FLAG_SKIP) ||
1189 cx->latency * 3 > sc->sc_prev_sleep) {
1190 if ((cx = SLIST_NEXT(cx, link)) == NULL)
1191 break;
1192 best = cx;
1193 }
1194
1195 if (best->state >= 3 &&
1196 (best->flags & CST_FLAG_MWAIT_BM_AVOIDANCE) &&
1197 acpi_read_pmreg(acpi_softc, ACPIREG_PM1_STS, 0) & ACPI_PM1_BM_STS) {
1198 /* clear it and back off */
1199 acpi_write_pmreg(acpi_softc, ACPIREG_PM1_STS, 0,
1200 ACPI_PM1_BM_STS);
1201 while ((cx = SLIST_NEXT(cx, link)) != NULL) {
1202 if (cx->flags & CST_FLAG_SKIP)
1203 continue;
1204 if (cx->state < 3 ||
1205 (cx->flags & CST_FLAG_MWAIT_BM_AVOIDANCE) == 0)
1206 break;
1207 }
1208 best = cx;
1209 }
1210
1211
1212 atomic_inc_long(&cst_stats[best->state]);
1213
1214 itime = tick / 2;
1215 switch (best->method) {
1216 default:
1217 case CST_METH_HALT:
1218 __asm volatile("sti; hlt");
1219 break;
1220
1221 case CST_METH_IO_HALT:
1222 inb((u_short)best->address);
1223 __asm volatile("sti; hlt");
1224 break;
1225
1226 case CST_METH_MWAIT:
1227 {
1228 struct timeval start, stop;
1229 unsigned int hints;
1230
1231 #ifdef __LP64__
1232 if ((read_rflags() & PSL_I) == 0)
1233 panic("idle with interrupts blocked!");
1234 #else
1235 if ((read_eflags() & PSL_I) == 0)
1236 panic("idle with interrupts blocked!");
1237 #endif
1238
1239 /* something already queued? */
1240 if (!cpu_is_idle(ci))
1241 return;
1242
1243 /*
1244 * About to idle; setting the MWAIT_IN_IDLE bit tells
1245 * cpu_unidle() that it can't be a no-op and tells cpu_kick()
1246 * that it doesn't need to use an IPI. We also set the
1247 * MWAIT_KEEP_IDLING bit: those routines clear it to stop
1248 * the mwait. Once they're set, we do a final check of the
1249 * queue, in case another cpu called setrunqueue() and added
1250 * something to the queue and called cpu_unidle() between
1251 * the check in sched_idle() and here.
1252 */
1253 hints = (unsigned)best->address;
1254 microuptime(&start);
1255 atomic_setbits_int(&ci->ci_mwait, MWAIT_IDLING);
1256 if (cpu_is_idle(ci)) {
1257 /* intel errata AAI65: cflush before monitor */
1258 if (ci->ci_cflushsz != 0 &&
1259 strcmp(cpu_vendor, "GenuineIntel") == 0) {
1260 membar_sync();
1261 clflush((unsigned long)&ci->ci_mwait);
1262 membar_sync();
1263 }
1264
1265 monitor(&ci->ci_mwait, 0, 0);
1266 if ((ci->ci_mwait & MWAIT_IDLING) == MWAIT_IDLING)
1267 mwait(0, hints);
1268 }
1269
1270 microuptime(&stop);
1271 timersub(&stop, &start, &stop);
1272 itime = stop.tv_sec * 1000000 + stop.tv_usec;
1273
1274 /* done idling; let cpu_kick() know that an IPI is required */
1275 atomic_clearbits_int(&ci->ci_mwait, MWAIT_IDLING);
1276 break;
1277 }
1278
1279 case CST_METH_GAS_IO:
1280 inb((u_short)best->address);
1281 /* something harmless to give system time to change state */
1282 acpi_read_pmreg(acpi_softc, ACPIREG_PM1_STS, 0);
1283 break;
1284
1285 }
1286
1287 sc->sc_last_itime = itime;
1288 itime >>= 1;
1289 sc->sc_prev_sleep = (sc->sc_prev_sleep + (sc->sc_prev_sleep >> 1)
1290 + itime) >> 1;
1291 }
1292
1293 void
acpicpu_suspend(void)1294 acpicpu_suspend(void)
1295 {
1296 extern int cpu_suspended;
1297 struct cpu_info *ci = curcpu();
1298 struct acpicpu_softc *sc = (struct acpicpu_softc *)ci->ci_acpicpudev;
1299 struct acpi_cstate *best, *cx;
1300
1301 if (sc == NULL) {
1302 __asm volatile("sti");
1303 panic("null acpicpu");
1304 }
1305
1306 /*
1307 * Find the lowest usable state.
1308 */
1309 best = cx = SLIST_FIRST(&sc->sc_cstates);
1310 while ((cx->flags & CST_FLAG_SKIP)) {
1311 if ((cx = SLIST_NEXT(cx, link)) == NULL)
1312 break;
1313 best = cx;
1314 }
1315
1316 switch (best->method) {
1317 default:
1318 case CST_METH_HALT:
1319 __asm volatile("sti; hlt");
1320 break;
1321
1322 case CST_METH_IO_HALT:
1323 inb((u_short)best->address);
1324 __asm volatile("sti; hlt");
1325 break;
1326
1327 case CST_METH_MWAIT:
1328 {
1329 unsigned int hints;
1330
1331 hints = (unsigned)best->address;
1332 /* intel errata AAI65: cflush before monitor */
1333 if (ci->ci_cflushsz != 0 &&
1334 strcmp(cpu_vendor, "GenuineIntel") == 0) {
1335 membar_sync();
1336 clflush((unsigned long)&cpu_suspended);
1337 membar_sync();
1338 }
1339
1340 monitor(&cpu_suspended, 0, 0);
1341 if (cpu_suspended || !CPU_IS_PRIMARY(ci))
1342 mwait(0, hints);
1343
1344 break;
1345 }
1346
1347 case CST_METH_GAS_IO:
1348 inb((u_short)best->address);
1349 /* something harmless to give system time to change state */
1350 acpi_read_pmreg(acpi_softc, ACPIREG_PM1_STS, 0);
1351 break;
1352
1353 }
1354 }
1355