Index: sys/kern/kern_shutdown.c =================================================================== --- sys/kern/kern_shutdown.c (revision 227813) +++ sys/kern/kern_shutdown.c (working copy) @@ -288,17 +288,6 @@ kern_reboot(int howto) { static int first_buf_printf = 1; -#if defined(SMP) - /* - * Bind us to CPU 0 so that all shutdown code runs there. Some - * systems don't shutdown properly (i.e., ACPI power off) if we - * run on another processor. - */ - thread_lock(curthread); - sched_bind(curthread, 0); - thread_unlock(curthread); - KASSERT(PCPU_GET(cpuid) == 0, ("%s: not running on cpu 0", __func__)); -#endif /* We're in the process of rebooting. */ rebooting = 1; Index: sys/dev/acpica/acpi.c =================================================================== --- sys/dev/acpica/acpi.c (revision 227813) +++ sys/dev/acpica/acpi.c (working copy) @@ -1953,11 +1953,23 @@ acpi_shutdown_final(void *arg, int howto) struct acpi_softc *sc = (struct acpi_softc *)arg; ACPI_STATUS status; +#if defined(SMP) /* - * XXX Shutdown code should only run on the BSP (cpuid 0). + * Shutdown code should only run on the BSP (cpuid 0). * Some chipsets do not power off the system correctly if called from * an AP. */ + if (CPU_ISSET(0, &stopped_cpus)) { + device_printf(sc->acpi_dev, + "Binding to CPU0 failed - already stopped\n"); + return; + } + thread_lock(curthread); + sched_bind(curthread, 0); + thread_unlock(curthread); + KASSERT(PCPU_GET(cpuid) == 0, ("%s: not running on cpu 0", __func__)); +#endif + if ((howto & RB_POWEROFF) != 0) { status = AcpiEnterSleepStatePrep(ACPI_STATE_S5); if (ACPI_FAILURE(status)) { Index: sys/i386/i386/vm_machdep.c =================================================================== --- sys/i386/i386/vm_machdep.c (revision 227813) +++ sys/i386/i386/vm_machdep.c (working copy) @@ -602,6 +602,21 @@ cpu_reset() u_int cnt; if (smp_active) { + + /* + * BSP should be shutdown by itself and should be the last + * one. + */ + if (CPU_ISSET(0, &stopped_cpus)) + printf("%s: Binding to CPU0 failed, already stopped\n", + __func__); + else { + thread_lock(curthread); + sched_bind(curthread, 0); + thread_unlock(curthread); + KASSERT(PCPU_GET(cpuid) == 0, + ("%s: not running on cpu 0", __func__)); + } map = all_cpus; CPU_CLR(PCPU_GET(cpuid), &map); CPU_NAND(&map, &stopped_cpus); Index: sys/amd64/amd64/vm_machdep.c =================================================================== --- sys/amd64/amd64/vm_machdep.c (revision 227813) +++ sys/amd64/amd64/vm_machdep.c (working copy) @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -534,6 +535,21 @@ cpu_reset() u_int cnt; if (smp_active) { + + /* + * BSP should be shutdown by itself and should be the last + * one. + */ + if (CPU_ISSET(0, &stopped_cpus)) + printf("%s: Binding to CPU0 failed, already stopped\n", + __func__); + else { + thread_lock(curthread); + sched_bind(curthread, 0); + thread_unlock(curthread); + KASSERT(PCPU_GET(cpuid) == 0, + ("%s: not running on cpu 0", __func__)); + } map = all_cpus; CPU_CLR(PCPU_GET(cpuid), &map); CPU_NAND(&map, &stopped_cpus);