DF-5619 / fix.diff
diff --git a/sys/platform/pc64/acpica/acpi_cstate_machdep.c b/sys/platform/pc64/acpica/acpi_cstate_machdep.c --- a/sys/platform/pc64/acpica/acpi_cstate_machdep.c +++ b/sys/platform/pc64/acpica/acpi_cstate_machdep.c @@ -84,12 +84,24 @@ cx->gas.SpaceId); return EINVAL; } + /* + * A C2+ I/O or memory C-state is only operational when + * its register resource was allocated; the caller only + * installs the bus-space enter method in that case. + * Reject the descriptor rather than letting a state with + * no entry method into the idle loop. + */ + if (cx->type != ACPI_STATE_C1 && cx->res == NULL) + return EINVAL; return 0; } switch (cx->gas.SpaceId) { case ACPI_ADR_SPACE_SYSTEM_IO: case ACPI_ADR_SPACE_SYSTEM_MEMORY: + /* No register resource, no entry method. */ + if (cx->type != ACPI_STATE_C1 && cx->res == NULL) + return EINVAL; break; case ACPI_ADR_SPACE_FIXED_HARDWARE: diff --git a/sys/dev/acpica/acpi_cpu_cstate.c b/sys/dev/acpica/acpi_cpu_cstate.c --- a/sys/dev/acpica/acpi_cpu_cstate.c +++ b/sys/dev/acpi_cpu_cstate.c @@ -618,6 +618,18 @@ } AcpiOsFree(buf.Pointer); + /* + * An empty state table must not parse as success: idle would run on + * zeroed/rejected states whose enter method is NULL, and the NO_C3 + * quirk path in acpi_cst_postattach() would resurrect rejected + * states through cst_non_c3. + */ + if (sc->cst_cx_count == 0) { + device_printf(sc->cst_dev, "no usable Cx state in _CST\n"); + sc->cst_flags &= ~ACPI_CST_FLAG_PROBING; + return (ENXIO); + } + if (sc->cst_flags & ACPI_CST_FLAG_MATCH_HT) { cpumask_t mask; |