commit 5975d2cb98a40019f84b882dd51d225713452038 Author: Andriy Gapon Date: Sun Dec 16 11:51:05 2012 +0200 x86 resume: setup bsp lapic before re-configuring i/o apics diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c index 31cc80b..8b19e2a 100644 --- a/sys/x86/x86/intr_machdep.c +++ b/sys/x86/x86/intr_machdep.c @@ -287,6 +287,7 @@ intr_resume(void) atpic_reset(); #endif mtx_lock(&intr_table_lock); + lapic_setup(0); STAILQ_FOREACH(pic, &pics, pics) { if (pic->pic_resume != NULL) pic->pic_resume(pic); diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c index 9b1e259..0df973a 100644 --- a/sys/x86/x86/local_apic.c +++ b/sys/x86/x86/local_apic.c @@ -160,7 +160,6 @@ static u_long lapic_timer_divisor; static struct eventtimer lapic_et; static void lapic_enable(void); -static void lapic_resume(struct pic *pic); static void lapic_timer_oneshot(struct lapic *, u_int count, int enable_int); static void lapic_timer_periodic(struct lapic *, @@ -172,8 +171,6 @@ static int lapic_et_start(struct eventtimer *et, struct bintime *first, struct bintime *period); static int lapic_et_stop(struct eventtimer *et); -struct pic lapic_pic = { .pic_resume = lapic_resume }; - static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value) { @@ -573,14 +570,6 @@ lapic_enable(void) lapic->svr = value; } -/* Reset the local APIC on the BSP during resume. */ -static void -lapic_resume(struct pic *pic) -{ - - lapic_setup(0); -} - int lapic_id(void) { @@ -1409,7 +1398,6 @@ apic_setup_io(void *dummy __unused) * properly program the LINT pins. */ lapic_setup(1); - intr_register_pic(&lapic_pic); if (bootverbose) lapic_dump("BSP"); commit 212c8a4a11428c3b4ad852256d479741f53c1826 Author: Andriy Gapon Date: Wed Dec 26 12:16:40 2012 +0200 cpususpend_handler: mark AP as resumed only after fully setting up lapic diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 3b9d747..af1aa5f 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -1708,11 +1708,11 @@ cpususpend_handler(void) ia32_pause(); } - CPU_CLR_ATOMIC(cpu, &started_cpus); - /* Resume MCA and local APIC */ mca_resume(); lapic_setup(0); + + CPU_CLR_ATOMIC(cpu, &started_cpus); } /* commit fa84cb3692bc275c11b0f4b8699f6e0df0540e1f Author: Andriy Gapon Date: Wed Dec 26 12:52:15 2012 +0200 acpi: clear power button status bit after waking up... so that it is not confused for a power off new request. Also, disable all GPEs before enabling interrupts as AcpiLeaveSleepState will re-enable correct GPEs later. Learned from: Linux and ACPI specification diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index b668097..ed237c6 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -2690,6 +2690,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state) { register_t intr; ACPI_STATUS status; + ACPI_EVENT_STATUS power_button_status; enum acpi_sleep_state slp_state; int sleep_result; @@ -2776,6 +2777,32 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state) sleep_result = acpi_sleep_machdep(sc, state); acpi_wakeup_machdep(sc, state, sleep_result, 0); AcpiLeaveSleepStatePrep(state); + + if (sleep_result == 1 && state == ACPI_STATE_S3) { + /* + * Prevent mis-interpretation of the wakeup by power button + * as a request for power off. + * Ideally we should post an appropriate wakeup event, + * perhaps using acpi_event_power_button_wake or alike. + * + * Clearing of power button status after wakeup is mandated + * by ACPI specification in section "Fixed Power Button". + * + * XXX As of ACPICA 20121114 AcpiGetEventStatus provides + * status as 0/1 corressponding to inactive/active despite + * its type being ACPI_EVENT_STATUS. In other words, + * we should not test for ACPI_EVENT_FLAG_SET for time being. + */ + if (ACPI_SUCCESS(AcpiGetEventStatus(ACPI_EVENT_POWER_BUTTON, + &power_button_status)) && power_button_status != 0) { + AcpiClearEvent(ACPI_EVENT_POWER_BUTTON); + device_printf(sc->acpi_dev, + "cleared fixed power button status\n"); + } + } + + AcpiDisableAllGpes(); + intr_restore(intr); /* call acpi_wakeup_machdep() again with interrupt enabled */