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 <[email protected]>
@@ -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++;