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++;

Reply via email to