-/* $OpenBSD: acpi_machdep.c,v 1.109 2024/05/26 13:37:31 kettenis Exp $ */
+/* $OpenBSD: acpi_machdep.c,v 1.110 2024/05/29 12:21:33 kettenis Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
*
int
acpi_sleep_cpu(struct acpi_softc *sc, int state)
{
+ if (state == ACPI_STATE_S0)
+ return cpu_suspend_primary();
+
rtcstop();
#if NLAPIC > 0
lapic_disable();
void
acpi_resume_cpu(struct acpi_softc *sc, int state)
{
+ if (state == ACPI_STATE_S0)
+ return;
+
cpu_init_msrs(&cpu_info_primary);
cpu_fix_msrs(&cpu_info_primary);
-/* $OpenBSD: cpu.c,v 1.188 2024/05/14 01:42:07 guenther Exp $ */
+/* $OpenBSD: cpu.c,v 1.189 2024/05/29 12:21:33 kettenis Exp $ */
/* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
/*-
return 0;
}
#endif
+
+int cpu_suspended;
+
+#ifdef SUSPEND
+
+void
+cpu_suspend_cycle(void)
+{
+ cpu_idle_cycle_fcn();
+}
+
+int
+cpu_suspend_primary(void)
+{
+ struct cpu_info *ci = curcpu();
+ int count = 0;
+
+ printf("suspend\n");
+
+ /* Mask clock interrupts. */
+ local_pic.pic_hwmask(&local_pic, 0);
+
+ /*
+ * All non-wakeup interrupts should be masked at this point;
+ * re-enable interrupts such that wakeup interrupts actually
+ * wake us up. Set a flag such that drivers can tell we're
+ * suspended and change their behaviour accordingly. They can
+ * wake us up by clearing the flag.
+ */
+ cpu_suspended = 1;
+ ci->ci_ilevel = IPL_NONE;
+ intr_enable();
+
+ while (cpu_suspended) {
+ cpu_suspend_cycle();
+ count++;
+ }
+
+ intr_disable();
+ ci->ci_ilevel = IPL_HIGH;
+
+ /* Unmask clock interrupts. */
+ local_pic.pic_hwunmask(&local_pic, 0);
+
+ printf("resume %d\n", count);
+ return 0;
+}
+
+#endif
-/* $OpenBSD: intr.c,v 1.57 2024/05/26 13:37:31 kettenis Exp $ */
+/* $OpenBSD: intr.c,v 1.58 2024/05/29 12:21:33 kettenis Exp $ */
/* $NetBSD: intr.c,v 1.3 2003/03/03 22:16:20 fvdl Exp $ */
/*
int
intr_handler(struct intrframe *frame, struct intrhand *ih)
{
+ extern int cpu_suspended;
struct cpu_info *ci = curcpu();
int floor;
int rc;
#ifdef MULTIPROCESSOR
int need_lock;
+#endif
+ /*
+ * We may not be able to mask MSIs, so block non-wakeup
+ * interrupts while we're suspended.
+ */
+ if (cpu_suspended && (ih->ih_flags & IPL_WAKEUP) == 0)
+ return 0;
+
+#ifdef MULTIPROCESSOR
if (ih->ih_flags & IPL_MPSAFE)
need_lock = 0;
else
-/* $OpenBSD: cpu.h,v 1.170 2024/05/21 23:16:06 jsg Exp $ */
+/* $OpenBSD: cpu.h,v 1.171 2024/05/29 12:21:33 kettenis Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
extern u_int cpu_mwait_size;
extern u_int cpu_mwait_states;
+int cpu_suspend_primary(void);
+
/* cacheinfo.c */
void x86_print_cacheinfo(struct cpu_info *);
-/* $OpenBSD: cpu.c,v 1.114 2023/10/24 13:20:10 claudio Exp $ */
+/* $OpenBSD: cpu.c,v 1.115 2024/05/29 12:21:33 kettenis Exp $ */
/* $NetBSD: cpu.c,v 1.1.2.7 2000/06/26 02:04:05 sommerfeld Exp $ */
/*-
return 0;
}
#endif
+
+int cpu_suspended;
-/* $OpenBSD: acpi.c,v 1.428 2024/05/13 19:56:37 kettenis Exp $ */
+/* $OpenBSD: acpi.c,v 1.429 2024/05/29 12:21:33 kettenis Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
int
acpi_interrupt(void *arg)
{
+ extern int cpu_suspended;
struct acpi_softc *sc = (struct acpi_softc *)arg;
uint32_t processed = 0, idx, jdx;
uint16_t sts, en;
ACPI_PM1_PWRBTN_STS);
sts &= ~ACPI_PM1_PWRBTN_STS;
+ if (cpu_suspended)
+ cpu_suspended = 0;
+
acpi_addtask(sc, acpi_pbtn_task, sc, 0);
}
if (sts & ACPI_PM1_SLPBTN_STS) {
-/* $OpenBSD: acpi_x86.c,v 1.20 2024/05/28 09:40:40 kettenis Exp $ */
+/* $OpenBSD: acpi_x86.c,v 1.21 2024/05/29 12:21:33 kettenis Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
sleep_showstate(void *v, int sleepmode)
{
struct acpi_softc *sc = v;
+ int fallback_state = -1;
switch (sleepmode) {
case SLEEP_SUSPEND:
sc->sc_state = ACPI_STATE_S3;
+#ifdef __amd64__
+ fallback_state = ACPI_STATE_S0; /* No S3, use S0 */
+#endif
break;
case SLEEP_HIBERNATE:
sc->sc_state = ACPI_STATE_S4;
+ fallback_state = ACPI_STATE_S5; /* No S4, use S5 */
break;
default:
return (EOPNOTSUPP);
if (sc->sc_sleeptype[sc->sc_state].slp_typa == -1 ||
sc->sc_sleeptype[sc->sc_state].slp_typb == -1) {
- if (sc->sc_state == ACPI_STATE_S4) {
- sc->sc_state = ACPI_STATE_S5; /* No S4, use S5 */
- printf("%s: S4 unavailable, using S5\n",
- sc->sc_dev.dv_xname);
+ if (fallback_state != -1) {
+ printf("%s: S%d unavailable, using S%d\n",
+ sc->sc_dev.dv_xname, sc->sc_state, fallback_state);
+ sc->sc_state = fallback_state;
} else {
printf("%s: state S%d unavailable\n",
sc->sc_dev.dv_xname, sc->sc_state);
}
/* 1st suspend AML step: _TTS(tostate) */
- if (aml_node_setval(sc, sc->sc_tts, sc->sc_state) != 0)
- return (EINVAL);
+ if (sc->sc_state != ACPI_STATE_S0) {
+ if (aml_node_setval(sc, sc->sc_tts, sc->sc_state) != 0)
+ return (EINVAL);
+ }
acpi_indicator(sc, ACPI_SST_WAKING); /* blink */
return 0;
}
struct acpi_softc *sc = v;
/* 2nd suspend AML step: _PTS(tostate) */
- if (aml_node_setval(sc, sc->sc_pts, sc->sc_state) != 0)
- return (EINVAL);
+ if (sc->sc_state != ACPI_STATE_S0) {
+ if (aml_node_setval(sc, sc->sc_pts, sc->sc_state) != 0)
+ return (EINVAL);
+ }
acpi_indicator(sc, ACPI_SST_WAKING); /* blink */
return 0;
}
acpi_indicator(sc, ACPI_SST_SLEEPING);
/* 3rd suspend AML step: _GTS(tostate) */
- aml_node_setval(sc, sc->sc_gts, sc->sc_state);
+ if (sc->sc_state != ACPI_STATE_S0)
+ aml_node_setval(sc, sc->sc_gts, sc->sc_state);
/* Clear fixed event status */
acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS);
acpibtn_disable_psw(); /* disable _LID for wakeup */
/* 3rd resume AML step: _TTS(runstate) */
- if (aml_node_setval(sc, sc->sc_tts, ACPI_STATE_S0) != 0)
- return (EINVAL);
+ if (sc->sc_state != ACPI_STATE_S0) {
+ if (aml_node_setval(sc, sc->sc_tts, ACPI_STATE_S0) != 0)
+ return (EINVAL);
+ }
acpi_indicator(sc, ACPI_SST_WAKING); /* blink */
return 0;
}
-/* $OpenBSD: tpm.c,v 1.19 2024/05/13 01:15:50 jsg Exp $ */
+/* $OpenBSD: tpm.c,v 1.20 2024/05/29 12:21:33 kettenis Exp $ */
/*
* Minimal interface to Trusted Platform Module chips implementing the
uint8_t *command;
size_t commandlen;
+ if (sc->sc_acpi->sc_state == ACPI_STATE_S0)
+ return 0;
+
DPRINTF(("%s: saving state preparing for suspend\n",
sc->sc_dev.dv_xname));