On Fri, 27 May 2022, Jan Stary wrote: > ... and with the latest snapshot, they are back. ... > acpicpu0 at acpi0: C3(350@96 mwait.1@0x20), C2(500@64 mwait.1@0x10), > C1(1000@1 mwait.1), PSS > acpicpu1 at acpi0: C3(350@96 mwait.1@0x20), C2(500@64 mwait.1@0x10), > C1(1000@1 mwait.1), PSS > acpicpu2 at acpi0: C3(350@96 mwait.1@0x20), C2(500@64 mwait.1@0x10), > C1(1000@1 mwait.1), PSS > acpicpu3 at acpi0: C3(350@96 mwait.1@0x20), C2(500@64 mwait.1@0x10), > C1(1000@1 mwait.1), PSS > > On May 26 14:34:43, h...@stare.cz wrote: > > This is current/adm64, dmesgs below. > > With the current snapshot, the C states are gone: > > > > -acpicpu0 at acpi0: C3(350@96 mwait.1@0x20), C2(500@64 mwait.1@0x10), > > C1(1000@1 mwait.1), PSS > > -acpicpu1 at acpi0: C3(350@96 mwait.1@0x20), C2(500@64 mwait.1@0x10), > > C1(1000@1 mwait.1), PSS > > -acpicpu2 at acpi0: C3(350@96 mwait.1@0x20), C2(500@64 mwait.1@0x10), > > C1(1000@1 mwait.1), PSS > > -acpicpu3 at acpi0: C3(350@96 mwait.1@0x20), C2(500@64 mwait.1@0x10), > > C1(1000@1 mwait.1), PSS > > +acpicpu0 at acpi0: C1(@1 halt!), PSS > > +acpicpu1 at acpi0: C1(@1 halt!), PSS > > +acpicpu2 at acpi0: C1(@1 halt!), PSS > > +acpicpu3 at acpi0: C1(@1 halt!), PSS > > > > Is this expected? > > Is it related to the recent apmd -A change?
Not really. Well, unless your box is one where the states change depending on, say, whether the box is plugged in. You could give this diff a shot. It enables processing of CST change notifications. No committers have a (working) box that does that, so I couldn't get any interest and I have no idea when--or even if--it might go in. Philip Guenther Index: sys/dev/acpi/acpicpu.c =================================================================== RCS file: /data/src/openbsd/src/sys/dev/acpi/acpicpu.c,v retrieving revision 1.92 diff -u -p -r1.92 acpicpu.c --- sys/dev/acpi/acpicpu.c 6 Apr 2022 18:59:27 -0000 1.92 +++ sys/dev/acpi/acpicpu.c 12 Apr 2022 06:13:55 -0000 @@ -25,6 +25,7 @@ #include <sys/malloc.h> #include <sys/queue.h> #include <sys/atomic.h> +#include <sys/mutex.h> #include <machine/bus.h> #include <machine/cpu.h> @@ -80,6 +81,7 @@ void acpicpu_setperf_ppc_change(struct a #define CST_FLAG_FALLBACK 0x4000 /* fallback for broken _CST */ #define CST_FLAG_SKIP 0x8000 /* state is worse choice */ +#define FLAGS_NOCST 0x01 #define FLAGS_MWAIT_ONLY 0x02 #define FLAGS_BMCHECK 0x04 #define FLAGS_NOTHROTTLE 0x08 @@ -113,8 +115,10 @@ struct acpi_cstate uint64_t address; /* or mwait hint */ }; -unsigned long cst_stats[4] = { 0 }; - +/* + * Locking: + * m sc_mtx + */ struct acpicpu_softc { struct device sc_dev; int sc_cpu; @@ -130,6 +134,10 @@ struct acpicpu_softc { struct cpu_info *sc_ci; SLIST_HEAD(,acpi_cstate) sc_cstates; + struct mutex sc_mtx; + struct acpi_cstate *sc_cstates_active; /* [m] */ + int sc_mwait_only; /* [m] */ + bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; @@ -161,10 +169,13 @@ struct acpicpu_softc { void acpicpu_add_cstatepkg(struct aml_value *, void *); void acpicpu_add_cdeppkg(struct aml_value *, void *); +void acpicpu_cst_activate(struct acpicpu_softc *); int acpicpu_getppc(struct acpicpu_softc *); int acpicpu_getpct(struct acpicpu_softc *); int acpicpu_getpss(struct acpicpu_softc *); int acpicpu_getcst(struct acpicpu_softc *); +int acpicpu_cst_changed(struct acpicpu_softc *); +void acpicpu_free_states(struct acpi_cstate *); void acpicpu_getcst_from_fadt(struct acpicpu_softc *); void acpicpu_print_one_cst(struct acpi_cstate *_cx); void acpicpu_print_cst(struct acpicpu_softc *_sc); @@ -510,11 +521,11 @@ acpicpu_getcst(struct acpicpu_softc *sc) struct acpi_cstate *cx, *next_cx; int use_nonmwait; - /* delete the existing list */ - while ((cx = SLIST_FIRST(&sc->sc_cstates)) != NULL) { - SLIST_REMOVE_HEAD(&sc->sc_cstates, link); - free(cx, M_DEVBUF, sizeof(*cx)); - } + /* set aside the existing list and free it if not active */ + cx = SLIST_FIRST(&sc->sc_cstates); + SLIST_INIT(&sc->sc_cstates); + if (cx != sc->sc_cstates_active) + acpicpu_free_states(cx); /* provide a fallback C1-via-halt in case _CST's C1 is bogus */ acpicpu_add_cstate(sc, ACPI_STATE_C1, CST_METH_HALT, @@ -528,8 +539,10 @@ acpicpu_getcst(struct acpicpu_softc *sc) /* only have fallback state? then no _CST objects were understood */ cx = SLIST_FIRST(&sc->sc_cstates); - if (cx->flags & CST_FLAG_FALLBACK) + if (cx->flags & CST_FLAG_FALLBACK) { + sc->sc_flags &= ~FLAGS_MWAIT_ONLY; return (1); + } /* * Skip states >= C2 if the CPU's LAPIC timer stops in deep @@ -558,6 +571,38 @@ acpicpu_getcst(struct acpicpu_softc *sc) return (0); } +int +acpicpu_cst_changed(struct acpicpu_softc *sc) +{ + struct acpi_cstate *active, *new; + + active = sc->sc_cstates_active; + new = SLIST_FIRST(&sc->sc_cstates); + + while (active != NULL && new != NULL) { + if (active->state != new->state || + active->method != new->method || + active->flags != new->flags || + active->latency != new->latency || + active->address != new->address) + return 1; + active = SLIST_NEXT(active, link); + new = SLIST_NEXT(new, link); + } + + return active != NULL || new != NULL; +} + +void +acpicpu_free_states(struct acpi_cstate *cx) +{ + while (cx != NULL) { + struct acpi_cstate *next_cx = SLIST_NEXT(cx, link); + free(cx, M_DEVBUF, sizeof(*cx)); + cx = next_cx; + } +} + /* * old-style fixed C-state info in the FADT. * Note that this has extra restrictions on values and flags. @@ -689,7 +734,9 @@ acpicpu_attach(struct device *parent, st sc->sc_acpi = (struct acpi_softc *)parent; sc->sc_devnode = aa->aaa_node; + mtx_init(&sc->sc_mtx, IPL_NONE); SLIST_INIT(&sc->sc_cstates); + sc->sc_cstates_active = NULL; if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_UID", 0, NULL, &uid) == 0) @@ -734,9 +781,10 @@ acpicpu_attach(struct device *parent, st #endif /* Get C-States from _CST or FADT */ - if (acpicpu_getcst(sc) || SLIST_EMPTY(&sc->sc_cstates)) + if (acpicpu_getcst(sc) || SLIST_EMPTY(&sc->sc_cstates)) { acpicpu_getcst_from_fadt(sc); - else { + sc->sc_flags |= FLAGS_NOCST; + } else { /* Notify BIOS we use _CST objects */ if (sc->sc_acpi->sc_fadt->cst_cnt) { acpi_write_pmreg(sc->sc_acpi, ACPIREG_SMICMD, 0, @@ -794,9 +842,6 @@ acpicpu_attach(struct device *parent, st 0, sc->sc_acpi->sc_fadt->pstate_cnt); } - aml_register_notify(sc->sc_devnode, NULL, - acpicpu_notify, sc, ACPIDEV_NOPOLL); - acpi_gasio(sc->sc_acpi, ACPI_IOREAD, sc->sc_pct.pct_status.grd_gas.address_space_id, sc->sc_pct.pct_status.grd_gas.address, @@ -838,6 +883,39 @@ acpicpu_attach(struct device *parent, st } printf("\n"); + acpicpu_cst_activate(sc); + + /* + * If we understood either the provided _CST or _PPC + * resources, register for notification of changes. + */ + if ((sc->sc_flags & FLAGS_NOCST) == 0 || + (sc->sc_flags & (FLAGS_NOPSS | FLAGS_NOPCT)) == 0) + { +#ifdef ACPI_DEBUG + printf(": %s: enabling notification\n", sc->sc_devnode->name); +#endif + aml_register_notify(sc->sc_devnode, NULL, + acpicpu_notify, sc, ACPIDEV_NOPOLL); + } +} + +void +acpicpu_cst_activate(struct acpicpu_softc *sc) +{ + struct acpi_cstate *cx, *old_states; + + mtx_enter(&sc->sc_mtx); + cx = SLIST_FIRST(&sc->sc_cstates); + old_states = sc->sc_cstates_active; + if (cx != old_states) + sc->sc_cstates_active = cx; + else + old_states = NULL; + sc->sc_mwait_only = (sc->sc_flags & FLAGS_MWAIT_ONLY) != 0; + mtx_leave(&sc->sc_mtx); + + acpicpu_free_states(old_states); } int @@ -1016,6 +1094,8 @@ acpicpu_notify(struct aml_node *node, in switch (notify_type) { case 0x80: /* _PPC changed, retrieve new values */ + if (sc->sc_flags & (FLAGS_NOPSS | FLAGS_NOPCT)) + break; acpicpu_getppc(sc); acpicpu_getpss(sc); if (sc->sc_notify) @@ -1023,10 +1103,15 @@ acpicpu_notify(struct aml_node *node, in break; case 0x81: /* _CST changed, retrieve new values */ + if (sc->sc_flags & FLAGS_NOCST) + break; acpicpu_getcst(sc); - printf("%s: notify", DEVNAME(sc)); - acpicpu_print_cst(sc); - printf("\n"); + if (acpicpu_cst_changed(sc)) { + printf("%s: notify", DEVNAME(sc)); + acpicpu_print_cst(sc); + printf("\n"); + acpicpu_cst_activate(sc); + } break; default: @@ -1151,18 +1236,22 @@ acpicpu_setperf(int level) void acpicpu_idle(void) { - struct cpu_info *ci = curcpu(); - struct acpicpu_softc *sc = (struct acpicpu_softc *)ci->ci_acpicpudev; - struct acpi_cstate *best, *cx; - unsigned long itime; + struct cpu_info *ci = curcpu(); + struct acpicpu_softc *sc = (struct acpicpu_softc *)ci->ci_acpicpudev; + struct acpi_cstate *best, *cx; + unsigned long itime; + short method; + u_int address; if (sc == NULL) { __asm volatile("sti"); panic("null acpicpu"); } + mtx_enter(&sc->sc_mtx); + /* possibly update the MWAIT_ONLY flag in cpu_info */ - if (sc->sc_flags & FLAGS_MWAIT_ONLY) { + if (sc->sc_mwait_only) { if ((ci->ci_mwait & MWAIT_ONLY) == 0) atomic_setbits_int(&ci->ci_mwait, MWAIT_ONLY); } else if (ci->ci_mwait & MWAIT_ONLY) @@ -1172,7 +1261,7 @@ acpicpu_idle(void) * Find the first state with a latency we'll accept, ignoring * states marked skippable */ - best = cx = SLIST_FIRST(&sc->sc_cstates); + best = cx = sc->sc_cstates_active; while ((cx->flags & CST_FLAG_SKIP) || cx->latency * 3 > sc->sc_prev_sleep) { if ((cx = SLIST_NEXT(cx, link)) == NULL) @@ -1196,18 +1285,20 @@ acpicpu_idle(void) best = cx; } - - atomic_inc_long(&cst_stats[best->state]); + /* made our choice; save the values we need and unlock */ + method = best->method; + address = best->address; + mtx_leave(&sc->sc_mtx); itime = tick / 2; - switch (best->method) { + switch (method) { default: case CST_METH_HALT: __asm volatile("sti; hlt"); break; case CST_METH_IO_HALT: - inb((u_short)best->address); + inb((u_short)address); __asm volatile("sti; hlt"); break; @@ -1238,7 +1329,7 @@ acpicpu_idle(void) * something to the queue and called cpu_unidle() between * the check in sched_idle() and here. */ - hints = (unsigned)best->address; + hints = (unsigned)address; microuptime(&start); atomic_setbits_int(&ci->ci_mwait, MWAIT_IDLING); if (cpu_is_idle(ci)) { @@ -1265,7 +1356,7 @@ acpicpu_idle(void) } case CST_METH_GAS_IO: - inb((u_short)best->address); + inb((u_short)address); /* something harmless to give system time to change state */ acpi_read_pmreg(acpi_softc, ACPIREG_PM1_STS, 0); break;