Module Name: src Committed By: jmcneill Date: Sat Sep 18 12:25:07 UTC 2021
Modified Files: src/sys/arch/aarch64/aarch64: genassym.cf vectors.S src/sys/arch/aarch64/include: cpu.h src/sys/arch/arm/cortex: gic_splfuncs.c src/sys/arch/evbarm/conf: std.generic64 Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.33 -r1.34 src/sys/arch/aarch64/aarch64/genassym.cf cvs rdiff -u -r1.23 -r1.24 src/sys/arch/aarch64/aarch64/vectors.S cvs rdiff -u -r1.38 -r1.39 src/sys/arch/aarch64/include/cpu.h cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/cortex/gic_splfuncs.c cvs rdiff -u -r1.14 -r1.15 src/sys/arch/evbarm/conf/std.generic64 Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/aarch64/aarch64/genassym.cf diff -u src/sys/arch/aarch64/aarch64/genassym.cf:1.33 src/sys/arch/aarch64/aarch64/genassym.cf:1.34 --- src/sys/arch/aarch64/aarch64/genassym.cf:1.33 Fri Dec 11 18:03:33 2020 +++ src/sys/arch/aarch64/aarch64/genassym.cf Sat Sep 18 12:25:06 2021 @@ -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_MTX_COUNT offsetof(struct cpu 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) Index: src/sys/arch/aarch64/aarch64/vectors.S diff -u src/sys/arch/aarch64/aarch64/vectors.S:1.23 src/sys/arch/aarch64/aarch64/vectors.S:1.24 --- src/sys/arch/aarch64/aarch64/vectors.S:1.23 Mon Aug 30 23:20:00 2021 +++ src/sys/arch/aarch64/aarch64/vectors.S Sat Sep 18 12:25:06 2021 @@ -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 @@ ENTRY_NP(el1_trap_exit) 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] Index: src/sys/arch/aarch64/include/cpu.h diff -u src/sys/arch/aarch64/include/cpu.h:1.38 src/sys/arch/aarch64/include/cpu.h:1.39 --- src/sys/arch/aarch64/include/cpu.h:1.38 Sat Aug 14 17:51:18 2021 +++ src/sys/arch/aarch64/include/cpu.h Sat Sep 18 12:25:06 2021 @@ -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 @@ struct cpu_info { 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; Index: src/sys/arch/arm/cortex/gic_splfuncs.c diff -u src/sys/arch/arm/cortex/gic_splfuncs.c:1.1 src/sys/arch/arm/cortex/gic_splfuncs.c:1.2 --- src/sys/arch/arm/cortex/gic_splfuncs.c:1.1 Tue Aug 10 15:33:09 2021 +++ src/sys/arch/arm/cortex/gic_splfuncs.c Sat Sep 18 12:25:07 2021 @@ -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 <jmcne...@invisible.ca> @@ -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 @@ gic_spllower(int newipl) 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(); } Index: src/sys/arch/evbarm/conf/std.generic64 diff -u src/sys/arch/evbarm/conf/std.generic64:1.14 src/sys/arch/evbarm/conf/std.generic64:1.15 --- src/sys/arch/evbarm/conf/std.generic64:1.14 Sun Aug 8 12:31:42 2021 +++ src/sys/arch/evbarm/conf/std.generic64 Sat Sep 18 12:25:07 2021 @@ -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 DRAM_BLOCKS=256 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