Only use the CPU_OFF PSCI call if SYSTEM_SUSPEND is supported. This means
authorkettenis <kettenis@openbsd.org>
Fri, 27 Jan 2023 23:11:59 +0000 (23:11 +0000)
committerkettenis <kettenis@openbsd.org>
Fri, 27 Jan 2023 23:11:59 +0000 (23:11 +0000)
that secondary CPUs will get parked in a WFI loop like we already do on
Apple Silicon systems.  This requires some small changes in agintc(4) to
make sure we ack the "halt" IPI such that we can send a "wakeup" IPI later.

ok patrick@

sys/arch/arm64/arm64/cpu.c
sys/arch/arm64/dev/agintc.c

index daef07d..e40634e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.c,v 1.80 2023/01/26 13:09:18 kettenis Exp $       */
+/*     $OpenBSD: cpu.c,v 1.81 2023/01/27 23:11:59 kettenis Exp $       */
 
 /*
  * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
@@ -1064,17 +1064,19 @@ cpu_halt(void)
 {
        struct cpu_info *ci = curcpu();
        int count = 0;
+       u_long psw;
 
        KERNEL_ASSERT_UNLOCKED();
        SCHED_ASSERT_UNLOCKED();
 
-       intr_disable();
+       psw = intr_disable();
 
        atomic_clearbits_int(&ci->ci_flags,
            CPUF_RUNNING | CPUF_PRESENT | CPUF_GO);
 
 #if NPSCI > 0
-       psci_cpu_off();
+       if (psci_can_suspend())
+               psci_cpu_off();
 #endif
 
        /*
@@ -1097,7 +1099,7 @@ cpu_halt(void)
        atomic_setbits_int(&ci->ci_flags, CPUF_RUNNING);
        __asm volatile("dsb sy; sev" ::: "memory");
 
-       intr_enable();
+       intr_restore(psw);
 
        /* Unmask clock interrupts. */
        WRITE_SPECIALREG(cntv_ctl_el0,
index 02989a4..905b511 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: agintc.c,v 1.46 2022/12/21 23:18:09 patrick Exp $ */
+/* $OpenBSD: agintc.c,v 1.47 2023/01/27 23:11:59 kettenis Exp $ */
 /*
  * Copyright (c) 2007, 2009, 2011, 2017 Dale Rahn <drahn@dalerahn.com>
  * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
@@ -1396,7 +1396,17 @@ agintc_ipi_ddb(void *v)
 int
 agintc_ipi_halt(void *v)
 {
+       struct agintc_softc *sc = v;
+       int old = curcpu()->ci_cpl;
+
+       intr_disable();
+       agintc_eoi(sc->sc_ipi_num[ARM_IPI_HALT]);
+       agintc_setipl(IPL_NONE);
+
        cpu_halt();
+
+       agintc_setipl(old);
+       intr_enable();
        return 1;
 }