Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/cortex Optimize hardware priority updates.



details:   https://anonhg.NetBSD.org/src/rev/de253b6c639d
branches:  trunk
changeset: 951938:de253b6c639d
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Feb 07 21:24:50 2021 +0000

description:
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.

diffstat:

 sys/arch/arm/cortex/gicv3.c |  26 ++++++++++++++++++--------
 1 files changed, 18 insertions(+), 8 deletions(-)

diffs (87 lines):

diff -r d9ebecf860f9 -r de253b6c639d sys/arch/arm/cortex/gicv3.c
--- a/sys/arch/arm/cortex/gicv3.c       Sun Feb 07 21:18:37 2021 +0000
+++ b/sys/arch/arm/cortex/gicv3.c       Sun Feb 07 21:24:50 2021 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
 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 @@
                ;
 
        /* 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_redist_enable(sc, ci);
 
        /* Allow IRQ exceptions */
-       cpsie(I32_bit);
+       ENABLE_INTERRUPT();
 }
 
 #ifdef MULTIPROCESSOR
@@ -722,9 +727,14 @@
        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 @@
                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 @@
 
                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++;



Home | Main Index | Thread Index | Old Index