-/* $OpenBSD: cpu.c,v 1.189 2024/05/29 12:21:33 kettenis Exp $ */
+/* $OpenBSD: cpu.c,v 1.190 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
/*-
void
cpu_suspend_cycle(void)
{
- cpu_idle_cycle_fcn();
+ if (cpu_suspend_cycle_fcn)
+ cpu_suspend_cycle_fcn();
+ else
+ cpu_idle_cycle_fcn();
}
int
-/* $OpenBSD: ipifuncs.c,v 1.38 2023/10/30 12:50:59 mvs Exp $ */
+/* $OpenBSD: ipifuncs.c,v 1.39 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: ipifuncs.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*-
wbinvd();
for(;;) {
- __asm volatile("hlt");
+ if (cpu_suspend_cycle_fcn)
+ cpu_suspend_cycle_fcn();
+ else
+ __asm volatile("hlt");
}
}
-/* $OpenBSD: machdep.c,v 1.293 2024/04/29 00:29:48 jsg Exp $ */
+/* $OpenBSD: machdep.c,v 1.294 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
*/
void cpu_idle_cycle_hlt(void);
void (*cpu_idle_cycle_fcn)(void) = &cpu_idle_cycle_hlt;
+void (*cpu_suspend_cycle_fcn)(void);
/* the following is used externally for concurrent handlers */
int setperf_prio = 0;
-/* $OpenBSD: cpu.h,v 1.171 2024/05/29 12:21:33 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.172 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
int amd64_pa_used(paddr_t);
#define cpu_idle_enter() do { /* nothing */ } while (0)
extern void (*cpu_idle_cycle_fcn)(void);
+extern void (*cpu_suspend_cycle_fcn)(void);
#define cpu_idle_cycle() (*cpu_idle_cycle_fcn)()
#define cpu_idle_leave() do { /* nothing */ } while (0)
extern void (*initclock_func)(void);
-/* $OpenBSD: machdep.c,v 1.671 2024/05/26 13:37:32 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.672 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
void (*cpu_idle_leave_fcn)(void) = NULL;
void (*cpu_idle_cycle_fcn)(void) = NULL;
void (*cpu_idle_enter_fcn)(void) = NULL;
+void (*cpu_suspend_cycle_fcn)(void);
struct uvm_constraint_range isa_constraint = { 0x0, 0x00ffffffUL };
-/* $OpenBSD: cpu.h,v 1.189 2024/05/21 23:16:06 jsg Exp $ */
+/* $OpenBSD: cpu.h,v 1.190 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */
/*-
extern void (*cpu_idle_enter_fcn)(void);
extern void (*cpu_idle_cycle_fcn)(void);
extern void (*cpu_idle_leave_fcn)(void);
+extern void (*cpu_suspend_cycle_fcn)(void);
extern int cpuspeed;
-/* $OpenBSD: acpicpu.c,v 1.92 2022/04/06 18:59:27 naddy Exp $ */
+/* $OpenBSD: acpicpu.c,v 1.93 2024/06/07 16:53:35 kettenis Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
* Copyright (c) 2015 Philip Guenther <guenther@openbsd.org>
int _flags, int _latency, int _power, uint64_t _address);
void acpicpu_set_pdc(struct acpicpu_softc *);
void acpicpu_idle(void);
+void acpicpu_suspend(void);
#if 0
void acpicpu_set_throttle(struct acpicpu_softc *, int);
extern uint32_t acpi_force_bm;
cpu_idle_cycle_fcn = &acpicpu_idle;
+ cpu_suspend_cycle_fcn = &acpicpu_suspend;
/*
* C3 (and maybe C2?) needs BM_RLD to be set to
sc->sc_prev_sleep = (sc->sc_prev_sleep + (sc->sc_prev_sleep >> 1)
+ itime) >> 1;
}
+
+void
+acpicpu_suspend(void)
+{
+ extern int cpu_suspended;
+ struct cpu_info *ci = curcpu();
+ struct acpicpu_softc *sc = (struct acpicpu_softc *)ci->ci_acpicpudev;
+ struct acpi_cstate *best, *cx;
+
+ if (sc == NULL) {
+ __asm volatile("sti");
+ panic("null acpicpu");
+ }
+
+ /*
+ * Find the lowest usable state.
+ */
+ best = cx = SLIST_FIRST(&sc->sc_cstates);
+ while ((cx->flags & CST_FLAG_SKIP)) {
+ if ((cx = SLIST_NEXT(cx, link)) == NULL)
+ break;
+ best = cx;
+ }
+
+ switch (best->method) {
+ default:
+ case CST_METH_HALT:
+ __asm volatile("sti; hlt");
+ break;
+
+ case CST_METH_IO_HALT:
+ inb((u_short)best->address);
+ __asm volatile("sti; hlt");
+ break;
+
+ case CST_METH_MWAIT:
+ {
+ unsigned int hints;
+
+ hints = (unsigned)best->address;
+ /* intel errata AAI65: cflush before monitor */
+ if (ci->ci_cflushsz != 0 &&
+ strcmp(cpu_vendor, "GenuineIntel") == 0) {
+ membar_sync();
+ clflush((unsigned long)&cpu_suspended);
+ membar_sync();
+ }
+
+ monitor(&cpu_suspended, 0, 0);
+ if (cpu_suspended || !CPU_IS_PRIMARY(ci))
+ mwait(0, hints);
+
+ break;
+ }
+
+ case CST_METH_GAS_IO:
+ inb((u_short)best->address);
+ /* something harmless to give system time to change state */
+ acpi_read_pmreg(acpi_softc, ACPIREG_PM1_STS, 0);
+ break;
+
+ }
+}