From fc30b644f1922d25f1f8a9187113a50ce3610714 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 26 May 2024 13:37:31 +0000 Subject: [PATCH] Implement wakeup interrupts on amd64. Provide a dummy implementation for i386 such that we can call the necessary hooks in the suspend/resume code without adding #ifdefs. Tweak the arm64 implementation such that we can call the hooks earlier as this is necessary to mask MSI and MSI-X interrupts on arm64. ok deraadt@, mlarkin@ --- sys/arch/amd64/amd64/acpi_machdep.c | 5 +-- sys/arch/amd64/amd64/intr.c | 52 +++++++++++++++++++++++++++-- sys/arch/amd64/include/intr.h | 4 ++- sys/arch/amd64/include/intrdefs.h | 3 +- sys/arch/arm64/arm64/cpu.c | 8 +++-- sys/arch/arm64/arm64/intr.c | 6 +--- sys/arch/i386/i386/machdep.c | 16 ++++++++- sys/arch/i386/include/intr.h | 4 ++- sys/kern/subr_suspend.c | 4 ++- 9 files changed, 84 insertions(+), 18 deletions(-) diff --git a/sys/arch/amd64/amd64/acpi_machdep.c b/sys/arch/amd64/amd64/acpi_machdep.c index 6980217ba01..bf7add7efd7 100644 --- a/sys/arch/amd64/amd64/acpi_machdep.c +++ b/sys/arch/amd64/amd64/acpi_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi_machdep.c,v 1.108 2023/06/07 04:46:09 deraadt Exp $ */ +/* $OpenBSD: acpi_machdep.c,v 1.109 2024/05/26 13:37:31 kettenis Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert * @@ -333,7 +333,8 @@ acpi_attach_machdep(struct acpi_softc *sc) extern void (*cpuresetfn)(void); sc->sc_interrupt = isa_intr_establish(NULL, sc->sc_fadt->sci_int, - IST_LEVEL, IPL_BIO, acpi_interrupt, sc, sc->sc_dev.dv_xname); + IST_LEVEL, IPL_BIO | IPL_WAKEUP, acpi_interrupt, + sc, sc->sc_dev.dv_xname); cpuresetfn = acpi_reset; #ifndef SMALL_KERNEL diff --git a/sys/arch/amd64/amd64/intr.c b/sys/arch/amd64/amd64/intr.c index 64396b3899a..9b1182e9545 100644 --- a/sys/arch/amd64/amd64/intr.c +++ b/sys/arch/amd64/amd64/intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.c,v 1.56 2024/01/19 18:38:16 kettenis Exp $ */ +/* $OpenBSD: intr.c,v 1.57 2024/05/26 13:37:31 kettenis Exp $ */ /* $NetBSD: intr.c,v 1.3 2003/03/03 22:16:20 fvdl Exp $ */ /* @@ -354,8 +354,8 @@ intr_establish(int legacy_irq, struct pic *pic, int pin, int type, int level, panic("intr_establish: non-legacy IRQ on i8259"); #endif - flags = level & IPL_MPSAFE; - level &= ~IPL_MPSAFE; + flags = level & (IPL_MPSAFE | IPL_WAKEUP); + level &= ~(IPL_MPSAFE | IPL_WAKEUP); KASSERT(level <= IPL_TTY || level >= IPL_CLOCK || flags & IPL_MPSAFE); @@ -694,6 +694,52 @@ intr_barrier(void *cookie) sched_barrier(ih->ih_cpu); } +#ifdef SUSPEND + +void +intr_enable_wakeup(void) +{ + struct cpu_info *ci = curcpu(); + struct pic *pic; + int irq, pin; + + for (irq = 0; irq < MAX_INTR_SOURCES; irq++) { + if (ci->ci_isources[irq] == NULL) + continue; + + if (ci->ci_isources[irq]->is_handlers->ih_flags & IPL_WAKEUP) + continue; + + pic = ci->ci_isources[irq]->is_pic; + pin = ci->ci_isources[irq]->is_pin; + if (pic->pic_hwmask) + pic->pic_hwmask(pic, pin); + } +} + +void +intr_disable_wakeup(void) +{ + struct cpu_info *ci = curcpu(); + struct pic *pic; + int irq, pin; + + for (irq = 0; irq < MAX_INTR_SOURCES; irq++) { + if (ci->ci_isources[irq] == NULL) + continue; + + if (ci->ci_isources[irq]->is_handlers->ih_flags & IPL_WAKEUP) + continue; + + pic = ci->ci_isources[irq]->is_pic; + pin = ci->ci_isources[irq]->is_pin; + if (pic->pic_hwunmask) + pic->pic_hwunmask(pic, pin); + } +} + +#endif + /* * Add a mask to cpl, and return the old value of cpl. */ diff --git a/sys/arch/amd64/include/intr.h b/sys/arch/amd64/include/intr.h index 2fe24d36ff6..9f0c717da6f 100644 --- a/sys/arch/amd64/include/intr.h +++ b/sys/arch/amd64/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.33 2021/12/14 18:16:14 deraadt Exp $ */ +/* $OpenBSD: intr.h,v 1.34 2024/05/26 13:37:31 kettenis Exp $ */ /* $NetBSD: intr.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */ /*- @@ -206,6 +206,8 @@ int intr_handler(struct intrframe *, struct intrhand *); void cpu_intr_init(struct cpu_info *); void intr_printconfig(void); void intr_barrier(void *); +void intr_enable_wakeup(void); +void intr_disable_wakeup(void); #ifdef MULTIPROCESSOR void x86_send_ipi(struct cpu_info *, int); diff --git a/sys/arch/amd64/include/intrdefs.h b/sys/arch/amd64/include/intrdefs.h index 9b6de3c3e4a..048d0202b88 100644 --- a/sys/arch/amd64/include/intrdefs.h +++ b/sys/arch/amd64/include/intrdefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intrdefs.h,v 1.23 2024/01/04 20:50:43 kettenis Exp $ */ +/* $OpenBSD: intrdefs.h,v 1.24 2024/05/26 13:37:31 kettenis Exp $ */ /* $NetBSD: intrdefs.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */ #ifndef _AMD64_INTRDEFS_H @@ -36,6 +36,7 @@ #define IPL_MPFLOOR IPL_TTY #define IPL_MPSAFE 0x100 +#define IPL_WAKEUP 0x200 /* Interrupt sharing types. */ #define IST_NONE 0 /* none */ diff --git a/sys/arch/arm64/arm64/cpu.c b/sys/arch/arm64/arm64/cpu.c index 2bfb445e259..112afeb7855 100644 --- a/sys/arch/arm64/arm64/cpu.c +++ b/sys/arch/arm64/arm64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.114 2024/04/13 14:19:39 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.115 2024/05/26 13:37:31 kettenis Exp $ */ /* * Copyright (c) 2016 Dale Rahn @@ -1526,7 +1526,8 @@ cpu_suspend_primary(void) * wake us up by clearing the flag. */ cpu_suspended = 1; - intr_enable_wakeup(); + arm_intr_func.setipl(IPL_NONE); + intr_enable(); while (cpu_suspended) { #if NPSCI > 0 @@ -1542,7 +1543,8 @@ cpu_suspend_primary(void) } resume: - intr_disable_wakeup(); + intr_disable(); + arm_intr_func.setipl(IPL_HIGH); /* Unmask clock interrupts. */ WRITE_SPECIALREG(cntv_ctl_el0, diff --git a/sys/arch/arm64/arm64/intr.c b/sys/arch/arm64/arm64/intr.c index 34dd9c53624..9e69fd001ca 100644 --- a/sys/arch/arm64/arm64/intr.c +++ b/sys/arch/arm64/arm64/intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.c,v 1.27 2022/12/21 22:30:42 kettenis Exp $ */ +/* $OpenBSD: intr.c,v 1.28 2024/05/26 13:37:31 kettenis Exp $ */ /* * Copyright (c) 2011 Dale Rahn * @@ -888,15 +888,11 @@ intr_enable_wakeup(void) { if (arm_intr_func.enable_wakeup) arm_intr_func.enable_wakeup(); - arm_intr_func.setipl(IPL_NONE); - intr_enable(); } void intr_disable_wakeup(void) { - intr_disable(); - arm_intr_func.setipl(IPL_HIGH); if (arm_intr_func.disable_wakeup) arm_intr_func.disable_wakeup(); } diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index c7edd204796..a75259a7474 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.670 2024/04/29 00:29:48 jsg Exp $ */ +/* $OpenBSD: machdep.c,v 1.671 2024/05/26 13:37:32 kettenis Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -3966,6 +3966,20 @@ intr_barrier(void *ih) sched_barrier(NULL); } +#ifdef SUSPEND + +void +intr_enable_wakeup(void) +{ +} + +void +intr_disable_wakeup(void) +{ +} + +#endif + unsigned int cpu_rnd_messybits(void) { diff --git a/sys/arch/i386/include/intr.h b/sys/arch/i386/include/intr.h index 60fe6dccabc..9682673acd4 100644 --- a/sys/arch/i386/include/intr.h +++ b/sys/arch/i386/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.49 2021/12/14 18:16:14 deraadt Exp $ */ +/* $OpenBSD: intr.h,v 1.50 2024/05/26 13:37:32 kettenis Exp $ */ /* $NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $ */ /* @@ -128,6 +128,8 @@ void splassert_check(int, const char *); struct cpu_info; void intr_barrier(void *); +void intr_enable_wakeup(void); +void intr_disable_wakeup(void); #ifdef MULTIPROCESSOR void i386_send_ipi(struct cpu_info *, int); diff --git a/sys/kern/subr_suspend.c b/sys/kern/subr_suspend.c index 1b4f4062918..40f7fa7bfc4 100644 --- a/sys/kern/subr_suspend.c +++ b/sys/kern/subr_suspend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_suspend.c,v 1.16 2023/07/12 18:40:06 cheloha Exp $ */ +/* $OpenBSD: subr_suspend.c,v 1.17 2024/05/26 13:37:32 kettenis Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert * Copyright (c) 2005 Jordan Hargrave @@ -132,6 +132,7 @@ top: s = splhigh(); intr_disable(); /* PSL_I for resume; PIC/APIC broken until repair */ cold = 2; /* Force other code to delay() instead of tsleep() */ + intr_enable_wakeup(); if (config_suspend_all(DVACT_SUSPEND) != 0) { sleep_abort(v); @@ -172,6 +173,7 @@ fail_pts: config_suspend_all(DVACT_RESUME); fail_suspend: + intr_disable_wakeup(); cold = 0; intr_enable(); splx(s); -- 2.20.1