Module Name: src Committed By: jmcneill Date: Sun Feb 7 21:24:50 UTC 2021
Modified Files: src/sys/arch/arm/cortex: gicv3.c Log Message: Optimize hardware priority updates. In gicv3_set_priority, read the current priority mask and only update it if we are lowering the priority. The hardware priority filter is raised only after taking an interrupt. This makes splfoo/splx without an interrupt in between considerably cheaper as PMR writes are relatively expensive compared to reads. While here, avoid an extra daif read when dispatching interrupts by using ENABLE_INTERRUPT() / DISABLE_INTERRUPT() instead of cpsie() / cpsid() macros. To generate a diff of this commit: cvs rdiff -u -r1.39 -r1.40 src/sys/arch/arm/cortex/gicv3.c 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/arm/cortex/gicv3.c diff -u src/sys/arch/arm/cortex/gicv3.c:1.39 src/sys/arch/arm/cortex/gicv3.c:1.40 --- src/sys/arch/arm/cortex/gicv3.c:1.39 Sat Jan 16 21:05:15 2021 +++ src/sys/arch/arm/cortex/gicv3.c Sun Feb 7 21:24:50 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3.c,v 1.39 2021/01/16 21:05:15 jmcneill Exp $ */ +/* $NetBSD: gicv3.c,v 1.40 2021/02/07 21:24:50 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -31,7 +31,7 @@ #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.39 2021/01/16 21:05:15 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.40 2021/02/07 21:24:50 jmcneill Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -220,8 +220,13 @@ static void gicv3_set_priority(struct pic_softc *pic, int ipl) { struct gicv3_softc * const sc = PICTOSOFTC(pic); + const uint8_t curpmr = icc_pmr_read(); + const uint8_t newpmr = IPL_TO_PMR(sc, ipl); - icc_pmr_write(IPL_TO_PMR(sc, ipl)); + if (newpmr > curpmr) { + /* Lowering priority mask */ + icc_pmr_write(newpmr); + } } static void @@ -407,7 +412,7 @@ gicv3_cpu_init(struct pic_softc *pic, st ; /* Set initial priority mask */ - gicv3_set_priority(pic, IPL_HIGH); + icc_pmr_write(IPL_TO_PMR(sc, IPL_HIGH)); /* Set the binary point field to the minimum value */ icc_bpr1_write(0); @@ -424,7 +429,7 @@ gicv3_cpu_init(struct pic_softc *pic, st gicv3_redist_enable(sc, ci); /* Allow IRQ exceptions */ - cpsie(I32_bit); + ENABLE_INTERRUPT(); } #ifdef MULTIPROCESSOR @@ -722,9 +727,14 @@ gicv3_irq_handler(void *frame) struct gicv3_softc * const sc = gicv3_softc; struct pic_softc *pic; const int oldipl = ci->ci_cpl; + const uint8_t pmr = IPL_TO_PMR(sc, oldipl); ci->ci_data.cpu_nintr++; + if (icc_pmr_read() != pmr) { + icc_pmr_write(pmr); + } + for (;;) { const uint32_t iar = icc_iar1_read(); dsb(sy); @@ -745,7 +755,7 @@ gicv3_irq_handler(void *frame) if (__predict_false(ipl < ci->ci_cpl)) { pic_do_pending_ints(I32_bit, ipl, frame); } else if (ci->ci_cpl != ipl) { - gicv3_set_priority(pic, ipl); + icc_pmr_write(IPL_TO_PMR(sc, ipl)); ci->ci_cpl = ipl; } @@ -756,9 +766,9 @@ gicv3_irq_handler(void *frame) const int64_t nintr = ci->ci_data.cpu_nintr; - cpsie(I32_bit); + ENABLE_INTERRUPT(); pic_dispatch(is, frame); - cpsid(I32_bit); + DISABLE_INTERRUPT(); if (nintr != ci->ci_data.cpu_nintr) ci->ci_intr_preempt.ev_count++;