diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c index 762ea37cfa34..49d2bd11fdaa 100644 --- a/sys/dev/acpica/acpi_cpu.c +++ b/sys/dev/acpica/acpi_cpu.c @@ -153,6 +153,7 @@ static struct sysctl_ctx_list cpu_sysctl_ctx; static struct sysctl_oid *cpu_sysctl_tree; static int cpu_cx_generic; static int cpu_cx_lowest_lim; +static bool cppc_notify; static struct acpi_cpu_softc **cpu_softc; ACPI_SERIAL_DECL(cpu, "ACPI CPU"); @@ -396,6 +397,13 @@ acpi_cpu_attach(device_t dev) */ if (!acpi_disabled("mwait") && cpu_mwait_usable()) sc->cpu_features |= ACPI_CAP_SMP_C1_NATIVE | ACPI_CAP_SMP_C3_NATIVE; + + /* + * Work around a lingering SMM bug which leads to freezes when handling + * CPPC notifications. Tell the SMM we will handle any CPPC notifications. + */ + if ((cpu_power_eax & CPUTPM1_HWP_NOTIFICATION) && cppc_notify) + sc->cpu_features |= ACPI_CAP_INTR_CPPC; #endif if (devclass_get_drivers(device_get_devclass(dev), &drivers, @@ -977,6 +985,12 @@ acpi_cpu_startup(void *arg) NULL, 0, acpi_cpu_global_cx_lowest_sysctl, "A", "Global lowest Cx sleep state to use"); + /* Add sysctl handler to control registering for CPPC notifications */ + cppc_notify = 1; + SYSCTL_ADD_BOOL(&cpu_sysctl_ctx, SYSCTL_CHILDREN(cpu_sysctl_tree), + OID_AUTO, "cppc_notify", CTLFLAG_RDTUN | CTLFLAG_MPSAFE, + &cppc_notify, 0, "Register for CPPC Notifications"); + /* Take over idling from cpu_idle_default(). */ cpu_cx_lowest_lim = 0; CPU_FOREACH(i) {