Index: i386/acpica/acpi_wakeup.c =================================================================== RCS file: /home/ncvs/src/sys/i386/acpica/acpi_wakeup.c,v retrieving revision 1.53.2.3 diff -u -r1.53.2.3 acpi_wakeup.c --- i386/acpica/acpi_wakeup.c 22 May 2012 17:44:01 -0000 1.53.2.3 +++ i386/acpica/acpi_wakeup.c 6 Jun 2012 12:54:37 -0000 @@ -107,7 +107,7 @@ int apic_id = cpu_apic_ids[cpu]; int ms; - WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[cpu]); + WAKECODE_FIXUP(wakeup_pcb, struct pcb *, &stoppcbs[cpu]); /* do an INIT IPI: assert RESET */ lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE | @@ -155,7 +155,7 @@ /* Wait up to 5 seconds for it to start. */ for (ms = 0; ms < 5000; ms++) { - if (susppcbs[cpu]->pcb_eip == 0) + if (stoppcbs[cpu].pcb_eip == 0) return (1); /* return SUCCESS */ DELAY(1000); } @@ -209,11 +209,42 @@ } #endif +static void +acpi_hook_suspend(void) +{ + wbinvd(); +} + +static void +acpi_hook_resume(void) +{ + int cpu; + + cpu = PCPU_GET(cpuid); + pmap_init_pat(); + PCPU_SET(switchtime, 0); + PCPU_SET(switchticks, ticks); + stoppcbs[cpu].pcb_eip = 0; +} + +static void +acpi_hook_restart(void) +{ + /* Resume MCA and local APIC */ + mca_resume(); + lapic_setup(0); +} + +DPCPU_DECLARE(void *, cpustop_hook_suspend); +DPCPU_DECLARE(void *, cpustop_hook_resume); +DPCPU_DECLARE(void *, cpustop_hook_restart); + int acpi_sleep_machdep(struct acpi_softc *sc, int state) { #ifdef SMP cpuset_t wakeup_cpus; + int i; #endif register_t cr3, rf; ACPI_STATUS status; @@ -228,6 +259,13 @@ #ifdef SMP wakeup_cpus = all_cpus; CPU_CLR(PCPU_GET(cpuid), &wakeup_cpus); + CPU_FOREACH(i) { + if (i == 0) + continue; + DPCPU_ID_SET(i, cpustop_hook_suspend, acpi_hook_suspend); + DPCPU_ID_SET(i, cpustop_hook_resume, acpi_hook_resume); + DPCPU_ID_SET(i, cpustop_hook_restart, acpi_hook_restart); + } #endif if (acpi_resume_beep != 0) @@ -251,10 +289,10 @@ load_cr3(vtophys(pm->pm_pdir)); #endif - if (suspendctx(susppcbs[0])) { + if (suspendctx(&stoppcbs[0])) { #ifdef SMP if (!CPU_EMPTY(&wakeup_cpus) && - suspend_cpus(wakeup_cpus) == 0) { + stop_cpus(wakeup_cpus) == 0) { device_printf(sc->acpi_dev, "Failed to suspend APs\n"); goto out; } @@ -263,10 +301,10 @@ WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0)); WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0)); - WAKECODE_FIXUP(wakeup_cr4, register_t, susppcbs[0]->pcb_cr4); - WAKECODE_FIXUP(wakeup_cr3, register_t, susppcbs[0]->pcb_cr3); + WAKECODE_FIXUP(wakeup_cr4, register_t, stoppcbs[0].pcb_cr4); + WAKECODE_FIXUP(wakeup_cr3, register_t, stoppcbs[0].pcb_cr3); - WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[0]); + WAKECODE_FIXUP(wakeup_pcb, struct pcb *, &stoppcbs[0]); /* Call ACPICA to enter the desired sleep state */ if (state == ACPI_STATE_S4 && sc->acpi_s4bios) Index: i386/i386/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/mp_machdep.c,v retrieving revision 1.328.2.4 diff -u -r1.328.2.4 mp_machdep.c --- i386/i386/mp_machdep.c 22 May 2012 17:44:01 -0000 1.328.2.4 +++ i386/i386/mp_machdep.c 6 Jun 2012 13:12:53 -0000 @@ -1479,6 +1479,10 @@ return (0); } +DPCPU_DECLARE(void *, cpustop_hook_suspend); +DPCPU_DECLARE(void *, cpustop_hook_resume); +DPCPU_DECLARE(void *, cpustop_hook_restart); + /* * Handle an IPI_STOP by saving our current context and spinning until we * are resumed. @@ -1487,24 +1491,38 @@ cpustop_handler(void) { u_int cpu; + void (*hook_func)(void); cpu = PCPU_GET(cpuid); - savectx(&stoppcbs[cpu]); + if (suspendctx(&stoppcbs[cpu])) { + hook_func = DPCPU_GET(cpustop_hook_suspend); + if (hook_func != NULL) { + hook_func(); + DPCPU_SET(cpustop_hook_suspend, NULL); + } - /* Indicate that we are stopped */ - CPU_SET_ATOMIC(cpu, &stopped_cpus); + /* Indicate that we are stopped */ + CPU_SET_ATOMIC(cpu, &stopped_cpus); + } else { + hook_func = DPCPU_GET(cpustop_hook_resume); + if (hook_func != NULL) { + hook_func(); + DPCPU_SET(cpustop_hook_resume, NULL); + } + } /* Wait for restart */ while (!CPU_ISSET(cpu, &started_cpus)) - ia32_pause(); + ia32_pause(); CPU_CLR_ATOMIC(cpu, &started_cpus); CPU_CLR_ATOMIC(cpu, &stopped_cpus); - if (cpu == 0 && cpustop_restartfunc != NULL) { - cpustop_restartfunc(); - cpustop_restartfunc = NULL; + hook_func = DPCPU_GET(cpustop_hook_restart); + if (hook_func != NULL) { + hook_func(); + DPCPU_SET(cpustop_hook_restart, NULL); } } Index: i386/i386/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/vm_machdep.c,v retrieving revision 1.307.2.1 diff -u -r1.307.2.1 vm_machdep.c --- i386/i386/vm_machdep.c 23 Sep 2011 00:51:37 -0000 1.307.2.1 +++ i386/i386/vm_machdep.c 6 Jun 2012 12:44:38 -0000 @@ -586,6 +586,8 @@ } #endif +DPCPU_DECLARE(void *, cpustop_hook_restart); + void cpu_reset() { @@ -602,6 +604,12 @@ u_int cnt; if (smp_active) { +#if 1 + /* XXX for testing */ + thread_lock(curthread); + sched_bind(curthread, 1); + thread_unlock(curthread); +#endif map = all_cpus; CPU_CLR(PCPU_GET(cpuid), &map); CPU_NAND(&map, &stopped_cpus); @@ -609,10 +617,16 @@ printf("cpu_reset: Stopping other CPUs\n"); stop_cpus(map); } +#if 1 + /* XXX for testing */ + thread_lock(curthread); + sched_unbind(curthread); + thread_unlock(curthread); +#endif if (PCPU_GET(cpuid) != 0) { cpu_reset_proxyid = PCPU_GET(cpuid); - cpustop_restartfunc = cpu_reset_proxy; + DPCPU_ID_SET(0, cpustop_hook_restart, cpu_reset_proxy); cpu_reset_proxy_active = 0; printf("cpu_reset: Restarting BSP\n"); Index: kern/subr_pcpu.c =================================================================== RCS file: /home/ncvs/src/sys/kern/subr_pcpu.c,v retrieving revision 1.27.2.1 diff -u -r1.27.2.1 subr_pcpu.c --- kern/subr_pcpu.c 23 Sep 2011 00:51:37 -0000 1.27.2.1 +++ kern/subr_pcpu.c 6 Jun 2012 08:04:49 -0000 @@ -76,6 +76,10 @@ struct pcpu *cpuid_to_pcpu[MAXCPU]; struct cpuhead cpuhead = STAILQ_HEAD_INITIALIZER(cpuhead); +DPCPU_DEFINE(void *, cpustop_hook_suspend); +DPCPU_DEFINE(void *, cpustop_hook_resume); +DPCPU_DEFINE(void *, cpustop_hook_restart); + /* * Initialize the MI portions of a struct pcpu. */