Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch gic_splx: performance optimizations



details:   https://anonhg.NetBSD.org/src/rev/a65859905f88
branches:  trunk
changeset: 1023613:a65859905f88
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Sep 18 12:25:06 2021 +0000

description:
gic_splx: performance optimizations

Avoid any kind of register access (DAIF, PMR, etc), barriers, and atomic
operations in the common case where no interrupt fires between spl being
raised and lowered.

This introduces a per-CPU return address (ci_splx_restart) used by the
vector handler to restart a sequence in splx that compares the new ipl
with the per-CPU hardware priority state stored in ci_hwpl.

diffstat:

 sys/arch/aarch64/aarch64/genassym.cf |   3 +-
 sys/arch/aarch64/aarch64/vectors.S   |  23 ++++++++++++++++++--
 sys/arch/aarch64/include/cpu.h       |   4 ++-
 sys/arch/arm/cortex/gic_splfuncs.c   |  40 +++++++++++++++++++++++++++++------
 sys/arch/evbarm/conf/std.generic64   |   3 +-
 5 files changed, 60 insertions(+), 13 deletions(-)

diffs (173 lines):

diff -r 53fc3eba052c -r a65859905f88 sys/arch/aarch64/aarch64/genassym.cf
--- a/sys/arch/aarch64/aarch64/genassym.cf      Sat Sep 18 10:46:17 2021 +0000
+++ b/sys/arch/aarch64/aarch64/genassym.cf      Sat Sep 18 12:25:06 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: genassym.cf,v 1.33 2020/12/11 18:03:33 skrll Exp $
+# $NetBSD: genassym.cf,v 1.34 2021/09/18 12:25:06 jmcneill Exp $
 #-
 # Copyright (c) 2014 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -296,6 +296,7 @@
 define CI_SOFTINTS             offsetof(struct cpu_info, ci_softints)
 define CI_IDLELWP              offsetof(struct cpu_info, ci_data.cpu_idlelwp)
 define CI_CC_NINTR             offsetof(struct cpu_info, ci_data.cpu_nintr)
+define CI_SPLX_RESTART         offsetof(struct cpu_info, ci_splx_restart)
 
 define V_RESCHED_KPREEMPT      ilog2(RESCHED_KPREEMPT)
 
diff -r 53fc3eba052c -r a65859905f88 sys/arch/aarch64/aarch64/vectors.S
--- a/sys/arch/aarch64/aarch64/vectors.S        Sat Sep 18 10:46:17 2021 +0000
+++ b/sys/arch/aarch64/aarch64/vectors.S        Sat Sep 18 12:25:06 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vectors.S,v 1.23 2021/08/30 23:20:00 jmcneill Exp $    */
+/*     $NetBSD: vectors.S,v 1.24 2021/09/18 12:25:06 jmcneill Exp $    */
 
 #include <aarch64/asm.h>
 #include <aarch64/locore.h>
@@ -9,8 +9,9 @@
 #include "opt_cpuoptions.h"
 #include "opt_ddb.h"
 #include "opt_dtrace.h"
+#include "opt_gic.h"
 
-RCSID("$NetBSD: vectors.S,v 1.23 2021/08/30 23:20:00 jmcneill Exp $")
+RCSID("$NetBSD: vectors.S,v 1.24 2021/09/18 12:25:06 jmcneill Exp $")
 
        ARMV8_DEFINE_OPTIONS
 
@@ -220,7 +221,23 @@
 
        unwind_x3_x30
 
-#if TF_PC + 8 == TF_SPSR
+#ifdef GIC_SPLFUNCS
+       mrs     x0, tpidr_el1           /* get curlwp */
+       ldr     x0, [x0, #L_CPU]        /* get curcpu */
+
+       /*
+        * If ci_intr_depth == 0 and ci_splx_restart != 0, return
+        * to splx restart. Otherwise return to exception pc.
+        */
+       ldr     w1, [x0, #CI_INTR_DEPTH]
+       cbnz    w1, 1f
+       ldr     x0, [x0, #CI_SPLX_RESTART]
+       cbnz    x0, 2f
+1:
+       ldr     x0, [sp, #TF_PC]
+2:
+       ldr     x1, [sp, #TF_SPSR]
+#elif TF_PC + 8 == TF_SPSR
        ldp     x0, x1, [sp, #TF_PC]
 #else
        ldr     x0, [sp, #TF_PC]
diff -r 53fc3eba052c -r a65859905f88 sys/arch/aarch64/include/cpu.h
--- a/sys/arch/aarch64/include/cpu.h    Sat Sep 18 10:46:17 2021 +0000
+++ b/sys/arch/aarch64/include/cpu.h    Sat Sep 18 12:25:06 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.38 2021/08/14 17:51:18 ryo Exp $ */
+/* $NetBSD: cpu.h,v 1.39 2021/09/18 12:25:06 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.
@@ -108,6 +108,8 @@
        volatile uint32_t ci_blocked_pics;
        volatile uint32_t ci_pending_pics;
        volatile uint32_t ci_pending_ipls;
+       void *ci_splx_restart;
+       int ci_splx_savedipl;
 
        int ci_kfpu_spl;
 
diff -r 53fc3eba052c -r a65859905f88 sys/arch/arm/cortex/gic_splfuncs.c
--- a/sys/arch/arm/cortex/gic_splfuncs.c        Sat Sep 18 10:46:17 2021 +0000
+++ b/sys/arch/arm/cortex/gic_splfuncs.c        Sat Sep 18 12:25:06 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: gic_splfuncs.c,v 1.1 2021/08/10 15:33:09 jmcneill Exp $ */
+/* $NetBSD: gic_splfuncs.c,v 1.2 2021/09/18 12:25:07 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2021 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gic_splfuncs.c,v 1.1 2021/08/10 15:33:09 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gic_splfuncs.c,v 1.2 2021/09/18 12:25:07 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -75,26 +75,52 @@
 static void
 gic_splx(int newipl)
 {
-       struct cpu_info * const ci = curcpu();
+       struct cpu_info *ci = curcpu();
+       register_t psw;
 
        if (newipl >= ci->ci_cpl) {
                return;
        }
 
-       if (ci->ci_hwpl <= newipl) {
-               ci->ci_cpl = newipl;
+       /*
+        * Try to avoid touching any hardware registers (DAIF, PMR) as an
+        * optimization for the common case of splraise followed by splx
+        * with no interrupts in between.
+        *
+        * If an interrupt fires in this critical section, the vector
+        * handler is responsible for returning to the address pointed
+        * to by ci_splx_restart to restart the sequence.
+        */
+       if (__predict_true(ci->ci_intr_depth == 0)) {
+               ci->ci_splx_savedipl = newipl;
+               ci->ci_splx_restart = &&restart;
+               __insn_barrier();
+checkhwpl:
                if (ci->ci_hwpl <= newipl) {
-                       return;
+                       ci->ci_cpl = newipl;
+                       __insn_barrier();
+                       ci->ci_splx_restart = NULL;
+                       goto dosoft;
+               } else {
+                       ci->ci_splx_restart = NULL;
+                       goto dohard;
                }
+restart:
+               ci = curcpu();
+               newipl = ci->ci_splx_savedipl;
+               goto checkhwpl;
        }
 
-       register_t psw = DISABLE_INTERRUPT_SAVE();
+dohard:
+       psw = DISABLE_INTERRUPT_SAVE();
        ci->ci_intr_depth++;
        pic_do_pending_ints(psw, newipl, NULL);
        ci->ci_intr_depth--;
        if ((psw & I32_bit) == 0) {
                ENABLE_INTERRUPT();
        }
+
+dosoft:
        cpu_dosoftints();
 }
 
diff -r 53fc3eba052c -r a65859905f88 sys/arch/evbarm/conf/std.generic64
--- a/sys/arch/evbarm/conf/std.generic64        Sat Sep 18 10:46:17 2021 +0000
+++ b/sys/arch/evbarm/conf/std.generic64        Sat Sep 18 12:25:06 2021 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: std.generic64,v 1.14 2021/08/08 12:31:42 jmcneill Exp $
+#      $NetBSD: std.generic64,v 1.15 2021/09/18 12:25:07 jmcneill Exp $
 #
 #      generic NetBSD/evbarm64 with FDT support
 
@@ -16,6 +16,7 @@
 options        EVBARM_BOARDTYPE="FDT"
 options        FDT                             # Flattened Device Tree support
 options        FPU_VFP
+options        GIC_SPLFUNCS
 options        MODULAR
 options        MODULAR_DEFAULT_AUTOLOAD
 options        PCI_NETBSD_CONFIGURE



Home | Main Index | Thread Index | Old Index