summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjmcneill <jmcneill@NetBSD.org>2021-03-27 12:15:08 +0000
committerjmcneill <jmcneill@NetBSD.org>2021-03-27 12:15:08 +0000
commitbb4115e5132ea5dcde3c3840fa29602014bb0f99 (patch)
tree50fe2880c70f366dab3e276fb347c9d5f0e88476
parent1984b6e1e24ada91f1dcd20a0c60ab1d7f52db1f (diff)
Revert recent pic optimizations until I have more time to work on this.
-rw-r--r--sys/arch/aarch64/include/cpu.h5
-rw-r--r--sys/arch/arm/include/cpu.h5
-rw-r--r--sys/arch/arm/pic/pic.c111
-rw-r--r--sys/arch/arm/pic/pic_splfuncs.c67
-rw-r--r--sys/arch/arm/pic/picvar.h24
5 files changed, 101 insertions, 111 deletions
diff --git a/sys/arch/aarch64/include/cpu.h b/sys/arch/aarch64/include/cpu.h
index 142c3b4b749..fdbefa93d51 100644
--- a/sys/arch/aarch64/include/cpu.h
+++ b/sys/arch/aarch64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.33 2021/02/21 17:07:06 jmcneill Exp $ */
+/* $NetBSD: cpu.h,v 1.34 2021/03/27 12:15:09 jmcneill Exp $ */
/*-
* Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.
@@ -104,9 +104,6 @@ struct cpu_info {
int ci_hwpl; /* current hardware priority */
volatile u_int ci_softints;
volatile u_int ci_intr_depth;
- volatile uint32_t ci_blocked_pics;
- volatile uint32_t ci_pending_pics;
- volatile uint32_t ci_pending_ipls;
int ci_kfpu_spl;
diff --git a/sys/arch/arm/include/cpu.h b/sys/arch/arm/include/cpu.h
index f628201396f..688f641077a 100644
--- a/sys/arch/arm/include/cpu.h
+++ b/sys/arch/arm/include/cpu.h
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.116 2021/02/21 15:00:04 jmcneill Exp $ */
+/* $NetBSD: cpu.h,v 1.117 2021/03/27 12:15:08 jmcneill Exp $ */
/*
* Copyright (c) 1994-1996 Mark Brinicombe.
@@ -190,9 +190,6 @@ struct cpu_info {
volatile u_int ci_intr_depth; /* */
volatile u_int ci_softints;
- volatile uint32_t ci_blocked_pics;
- volatile uint32_t ci_pending_pics;
- volatile uint32_t ci_pending_ipls;
lwp_t * ci_lastlwp; /* last lwp */
diff --git a/sys/arch/arm/pic/pic.c b/sys/arch/arm/pic/pic.c
index 8adaab617c9..ace7b2dc458 100644
--- a/sys/arch/arm/pic/pic.c
+++ b/sys/arch/arm/pic/pic.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pic.c,v 1.69 2021/02/21 17:07:45 jmcneill Exp $ */
+/* $NetBSD: pic.c,v 1.70 2021/03/27 12:15:09 jmcneill Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -33,7 +33,7 @@
#include "opt_multiprocessor.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.69 2021/02/21 17:07:45 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.70 2021/03/27 12:15:09 jmcneill Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@@ -59,20 +59,43 @@ __KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.69 2021/02/21 17:07:45 jmcneill Exp $");
#include <arm/pic/picvar.h>
#if defined(__HAVE_PIC_PENDING_INTRS)
-
/*
* This implementation of pending interrupts on a MULTIPROCESSOR system makes
* the assumption that a PIC (pic_softc) shall only have all its interrupts
* come from the same CPU. In other words, interrupts from a single PIC will
* not be distributed among multiple CPUs.
*/
+struct pic_pending {
+ volatile uint32_t blocked_pics;
+ volatile uint32_t pending_pics;
+ volatile uint32_t pending_ipls;
+};
static uint32_t
pic_find_pending_irqs_by_ipl(struct pic_softc *, size_t, uint32_t, int);
static struct pic_softc *
- pic_list_find_pic_by_pending_ipl(struct cpu_info *, uint32_t);
+ pic_list_find_pic_by_pending_ipl(struct pic_pending *, uint32_t);
+static void
+ pic_deliver_irqs(struct pic_pending *, struct pic_softc *, int, void *);
static void
- pic_deliver_irqs(struct cpu_info *, struct pic_softc *, int, void *);
+ pic_list_deliver_irqs(struct pic_pending *, register_t, int, void *);
+#ifdef MULTIPROCESSOR
+percpu_t *pic_pending_percpu;
+static struct pic_pending *
+pic_pending_get(void)
+{
+ return percpu_getref(pic_pending_percpu);
+}
+static void
+pic_pending_put(struct pic_pending *pend)
+{
+ percpu_putref(pic_pending_percpu);
+}
+#else
+struct pic_pending pic_pending;
+#define pic_pending_get() (&pic_pending)
+#define pic_pending_put(pend) __nothing
+#endif /* MULTIPROCESSOR */
#endif /* __HAVE_PIC_PENDING_INTRS */
struct pic_softc *pic_list[PIC_MAXPICS];
@@ -95,6 +118,20 @@ EVCNT_ATTACH_STATIC(pic_deferral_ev);
static int pic_init(void);
+#ifdef __HAVE_PIC_SET_PRIORITY
+void
+pic_set_priority(struct cpu_info *ci, int newipl)
+{
+ register_t psw = DISABLE_INTERRUPT_SAVE();
+ if (pic_list[0] != NULL)
+ (pic_list[0]->pic_ops->pic_set_priority)(pic_list[0], newipl);
+ ci->ci_cpl = newipl;
+ if ((psw & I32_bit) == 0) {
+ ENABLE_INTERRUPT();
+ }
+}
+#endif
+
#ifdef MULTIPROCESSOR
int
pic_ipi_ast(void *arg)
@@ -138,9 +175,7 @@ pic_ipi_ddb(void *arg)
int
pic_ipi_kpreempt(void *arg)
{
- struct lwp *l = curlwp;
-
- l->l_md.md_astpending |= __BIT(1);
+ atomic_or_uint(&curcpu()->ci_astpending, __BIT(1));
return 1;
}
#endif /* __HAVE_PREEMPTION */
@@ -229,14 +264,15 @@ void
pic_mark_pending_source(struct pic_softc *pic, struct intrsource *is)
{
const uint32_t ipl_mask = __BIT(is->is_ipl);
- struct cpu_info * const ci = curcpu();
atomic_or_32(&pic->pic_pending_irqs[is->is_irq >> 5],
__BIT(is->is_irq & 0x1f));
atomic_or_32(&pic->pic_pending_ipls, ipl_mask);
- atomic_or_32(&ci->ci_pending_ipls, ipl_mask);
- atomic_or_32(&ci->ci_pending_pics, __BIT(pic->pic_id));
+ struct pic_pending *pend = pic_pending_get();
+ atomic_or_32(&pend->pending_ipls, ipl_mask);
+ atomic_or_32(&pend->pending_pics, __BIT(pic->pic_id));
+ pic_pending_put(pend);
}
void
@@ -257,7 +293,6 @@ pic_mark_pending_sources(struct pic_softc *pic, size_t irq_base,
struct intrsource ** const isbase = &pic->pic_sources[irq_base];
struct intrsource *is;
volatile uint32_t *ipending = &pic->pic_pending_irqs[irq_base >> 5];
- struct cpu_info * const ci = curcpu();
uint32_t ipl_mask = 0;
if (pending == 0)
@@ -280,8 +315,10 @@ pic_mark_pending_sources(struct pic_softc *pic, size_t irq_base,
}
atomic_or_32(&pic->pic_pending_ipls, ipl_mask);
- atomic_or_32(&ci->ci_pending_ipls, ipl_mask);
- atomic_or_32(&ci->ci_pending_pics, __BIT(pic->pic_id));
+ struct pic_pending *pend = pic_pending_get();
+ atomic_or_32(&pend->pending_ipls, ipl_mask);
+ atomic_or_32(&pend->pending_pics, __BIT(pic->pic_id));
+ pic_pending_put(pend);
return ipl_mask;
}
@@ -350,7 +387,7 @@ pic_dispatch(struct intrsource *is, void *frame)
#if defined(__HAVE_PIC_PENDING_INTRS)
void
-pic_deliver_irqs(struct cpu_info *ci, struct pic_softc *pic, int ipl,
+pic_deliver_irqs(struct pic_pending *pend, struct pic_softc *pic, int ipl,
void *frame)
{
const uint32_t ipl_mask = __BIT(ipl);
@@ -431,7 +468,7 @@ pic_deliver_irqs(struct cpu_info *ci, struct pic_softc *pic, int ipl,
} while (pending_irqs);
if (blocked_irqs) {
atomic_or_32(iblocked, blocked_irqs);
- atomic_or_32(&ci->ci_blocked_pics, __BIT(pic->pic_id));
+ atomic_or_32(&pend->blocked_pics, __BIT(pic->pic_id));
}
}
@@ -441,15 +478,15 @@ pic_deliver_irqs(struct cpu_info *ci, struct pic_softc *pic, int ipl,
* about these.
*/
if (atomic_and_32_nv(&pic->pic_pending_ipls, ~ipl_mask) == 0)
- atomic_and_32(&ci->ci_pending_pics, ~__BIT(pic->pic_id));
+ atomic_and_32(&pend->pending_pics, ~__BIT(pic->pic_id));
}
-void
-pic_list_unblock_irqs(struct cpu_info *ci)
+static void
+pic_list_unblock_irqs(struct pic_pending *pend)
{
- uint32_t blocked_pics = ci->ci_blocked_pics;
+ uint32_t blocked_pics = pend->blocked_pics;
- ci->ci_blocked_pics = 0;
+ pend->blocked_pics = 0;
for (;;) {
struct pic_softc *pic;
@@ -486,9 +523,9 @@ pic_list_unblock_irqs(struct cpu_info *ci)
}
struct pic_softc *
-pic_list_find_pic_by_pending_ipl(struct cpu_info *ci, uint32_t ipl_mask)
+pic_list_find_pic_by_pending_ipl(struct pic_pending *pend, uint32_t ipl_mask)
{
- uint32_t pending_pics = ci->ci_pending_pics;
+ uint32_t pending_pics = pend->pending_pics;
struct pic_softc *pic;
for (;;) {
@@ -505,17 +542,17 @@ pic_list_find_pic_by_pending_ipl(struct cpu_info *ci, uint32_t ipl_mask)
}
void
-pic_list_deliver_irqs(struct cpu_info *ci, register_t psw, int ipl,
+pic_list_deliver_irqs(struct pic_pending *pend, register_t psw, int ipl,
void *frame)
{
const uint32_t ipl_mask = __BIT(ipl);
struct pic_softc *pic;
- while ((pic = pic_list_find_pic_by_pending_ipl(ci, ipl_mask)) != NULL) {
- pic_deliver_irqs(ci, pic, ipl, frame);
+ while ((pic = pic_list_find_pic_by_pending_ipl(pend, ipl_mask)) != NULL) {
+ pic_deliver_irqs(pend, pic, ipl, frame);
KASSERT((pic->pic_pending_ipls & ipl_mask) == 0);
}
- atomic_and_32(&ci->ci_pending_ipls, ~ipl_mask);
+ atomic_and_32(&pend->pending_ipls, ~ipl_mask);
}
#endif /* __HAVE_PIC_PENDING_INTRS */
@@ -528,23 +565,24 @@ pic_do_pending_ints(register_t psw, int newipl, void *frame)
return;
}
#if defined(__HAVE_PIC_PENDING_INTRS)
- while ((ci->ci_pending_ipls & ~__BIT(newipl)) > __BIT(newipl)) {
- KASSERT(ci->ci_pending_ipls < __BIT(NIPL));
+ struct pic_pending *pend = pic_pending_get();
+ while ((pend->pending_ipls & ~__BIT(newipl)) > __BIT(newipl)) {
+ KASSERT(pend->pending_ipls < __BIT(NIPL));
for (;;) {
- int ipl = 31 - __builtin_clz(ci->ci_pending_ipls);
+ int ipl = 31 - __builtin_clz(pend->pending_ipls);
KASSERT(ipl < NIPL);
if (ipl <= newipl)
break;
pic_set_priority(ci, ipl);
- pic_list_deliver_irqs(ci, psw, ipl, frame);
- pic_list_unblock_irqs(ci);
+ pic_list_deliver_irqs(pend, psw, ipl, frame);
+ pic_list_unblock_irqs(pend);
}
}
+ pic_pending_put(pend);
#endif /* __HAVE_PIC_PENDING_INTRS */
#ifdef __HAVE_PREEMPTION
- struct lwp *l = curlwp;
- if (newipl == IPL_NONE && (l->l_md.md_astpending & __BIT(1))) {
+ if (newipl == IPL_NONE && (ci->ci_astpending & __BIT(1))) {
pic_set_priority(ci, IPL_SCHED);
kpreempt(0);
}
@@ -604,6 +642,11 @@ pic_add(struct pic_softc *pic, int irqbase)
KASSERT(strlen(pic->pic_name) > 0);
+#if defined(__HAVE_PIC_PENDING_INTRS) && defined(MULTIPROCESSOR)
+ if (__predict_false(pic_pending_percpu == NULL))
+ pic_pending_percpu = percpu_alloc(sizeof(struct pic_pending));
+#endif /* __HAVE_PIC_PENDING_INTRS && MULTIPROCESSOR */
+
mutex_enter(&pic_lock);
if (irqbase == PIC_IRQBASE_ALLOC) {
irqbase = pic_lastbase;
diff --git a/sys/arch/arm/pic/pic_splfuncs.c b/sys/arch/arm/pic/pic_splfuncs.c
index 47eefac02e8..0122ee10bcc 100644
--- a/sys/arch/arm/pic/pic_splfuncs.c
+++ b/sys/arch/arm/pic/pic_splfuncs.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pic_splfuncs.c,v 1.19 2021/03/01 11:29:14 jmcneill Exp $ */
+/* $NetBSD: pic_splfuncs.c,v 1.20 2021/03/27 12:15:09 jmcneill Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -28,7 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pic_splfuncs.c,v 1.19 2021/03/01 11:29:14 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pic_splfuncs.c,v 1.20 2021/03/27 12:15:09 jmcneill Exp $");
#define _INTR_PRIVATE
#include <sys/param.h>
@@ -46,42 +46,31 @@ __KERNEL_RCSID(0, "$NetBSD: pic_splfuncs.c,v 1.19 2021/03/01 11:29:14 jmcneill E
#include <arm/pic/picvar.h>
-#if defined(__HAVE_CPU_DOSOFTINTS_CI)
-#define CPU_DOSOFTINTS(ci) cpu_dosoftints_ci((ci))
-#else
-#define CPU_DOSOFTINTS(ci) cpu_dosoftints()
-#endif
-
-#if defined(__HAVE_PIC_PENDING_INTRS)
-static void splx_dopendingints(struct cpu_info *, const int);
-#endif
int
_splraise(int newipl)
{
struct cpu_info * const ci = curcpu();
const int oldipl = ci->ci_cpl;
- KDASSERT(newipl < NIPL);
+ KASSERT(newipl < NIPL);
if (newipl > ci->ci_cpl) {
pic_set_priority(ci, newipl);
}
return oldipl;
}
-
int
_spllower(int newipl)
{
struct cpu_info * const ci = curcpu();
const int oldipl = ci->ci_cpl;
- KDASSERT(panicstr || newipl <= ci->ci_cpl);
+ KASSERT(panicstr || newipl <= ci->ci_cpl);
if (newipl < ci->ci_cpl) {
register_t psw = DISABLE_INTERRUPT_SAVE();
ci->ci_intr_depth++;
pic_do_pending_ints(psw, newipl, NULL);
ci->ci_intr_depth--;
- if ((psw & I32_bit) == 0 || newipl == IPL_NONE) {
+ if ((psw & I32_bit) == 0 || newipl == IPL_NONE)
ENABLE_INTERRUPT();
- }
cpu_dosoftints();
}
return oldipl;
@@ -91,48 +80,24 @@ void
splx(int savedipl)
{
struct cpu_info * const ci = curcpu();
- KDASSERT(savedipl < NIPL);
+ KASSERT(savedipl < NIPL);
if (__predict_false(savedipl == ci->ci_cpl)) {
return;
}
-#if defined(__HAVE_PIC_PENDING_INTRS)
- if (__predict_false(ci->ci_pending_ipls != 0)) {
- splx_dopendingints(ci, savedipl);
- }
-#endif
-
- pic_set_priority(ci, savedipl);
- CPU_DOSOFTINTS(ci);
-
- KDASSERTMSG(ci->ci_cpl == savedipl, "cpl %d savedipl %d",
- ci->ci_cpl, savedipl);
-}
+ register_t psw = DISABLE_INTERRUPT_SAVE();
+ KASSERTMSG(panicstr != NULL || savedipl < ci->ci_cpl,
+ "splx(%d) to a higher ipl than %d", savedipl, ci->ci_cpl);
-#if defined(__HAVE_PIC_PENDING_INTRS)
-static void __noinline
-splx_dopendingints(struct cpu_info *ci, const int savedipl)
-{
- const register_t psw = DISABLE_INTERRUPT_SAVE();
ci->ci_intr_depth++;
- while ((ci->ci_pending_ipls & ~__BIT(savedipl)) > __BIT(savedipl)) {
- KASSERT(ci->ci_pending_ipls < __BIT(NIPL));
- for (;;) {
- int ipl = 31 - __builtin_clz(ci->ci_pending_ipls);
- KASSERT(ipl < NIPL);
- if (ipl <= savedipl) {
- break;
- }
-
- pic_set_priority(ci, ipl);
- pic_list_deliver_irqs(ci, psw, ipl, NULL);
- pic_list_unblock_irqs(ci);
- }
- }
+ pic_do_pending_ints(psw, savedipl, NULL);
ci->ci_intr_depth--;
- if ((psw & I32_bit) == 0) {
+ KASSERTMSG(ci->ci_cpl == savedipl, "cpl %d savedipl %d",
+ ci->ci_cpl, savedipl);
+ if ((psw & I32_bit) == 0)
ENABLE_INTERRUPT();
- }
+ cpu_dosoftints();
+ KASSERTMSG(ci->ci_cpl == savedipl, "cpl %d savedipl %d",
+ ci->ci_cpl, savedipl);
}
-#endif
diff --git a/sys/arch/arm/pic/picvar.h b/sys/arch/arm/pic/picvar.h
index f8201122e61..7ab192951d2 100644
--- a/sys/arch/arm/pic/picvar.h
+++ b/sys/arch/arm/pic/picvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: picvar.h,v 1.33 2021/02/27 14:22:07 jmcneill Exp $ */
+/* $NetBSD: picvar.h,v 1.34 2021/03/27 12:15:09 jmcneill Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -73,8 +73,6 @@ void pic_mark_pending(struct pic_softc *pic, int irq);
void pic_mark_pending_source(struct pic_softc *pic, struct intrsource *is);
uint32_t pic_mark_pending_sources(struct pic_softc *pic, size_t irq_base,
uint32_t pending);
-void pic_list_deliver_irqs(struct cpu_info *, register_t, int, void *);
-void pic_list_unblock_irqs(struct cpu_info *);
#endif /* __HAVE_PIC_PENDING_INTRS */
void *pic_establish_intr(struct pic_softc *pic, int irq, int ipl, int type,
int (*func)(void *), void *arg, const char *);
@@ -107,8 +105,6 @@ void intr_ipi_send(const kcpuset_t *, u_long ipi);
#include <sys/evcnt.h>
#include <sys/percpu.h>
-#include <arm/cpufunc.h>
-
#ifndef PIC_MAXPICS
#define PIC_MAXPICS 32
#endif
@@ -178,30 +174,22 @@ struct pic_ops {
#endif
};
-/* Using an inline causes catch-22 problems with cpu.h */
#ifdef __HAVE_PIC_SET_PRIORITY
/*
* This is used to update a hardware pic with a value corresponding
* to the ipl being set.
*/
-#define pic_set_priority(ci, newipl) \
- do { \
- register_t __psw = cpsid(I32_bit); \
- (ci)->ci_cpl = (newipl); \
- if (__predict_true(pic_list[0] != NULL)) { \
- (pic_list[0]->pic_ops->pic_set_priority)(pic_list[0], newipl); \
- } \
- if ((__psw & I32_bit) == 0) { \
- cpsie(I32_bit); \
- } \
- } while (0)
+struct cpu_info;
+void pic_set_priority(struct cpu_info *, int);
#else
-#define pic_set_priority(ci, newipl) ((void)((ci)->ci_cpl = (newipl)))
+/* Using an inline causes catch-22 problems with cpu.h */
+#define pic_set_priority(ci, newipl) ((void)((ci)->ci_cpl = (newipl)))
#endif
#define PIC_IRQBASE_ALLOC (-2)
int pic_add(struct pic_softc *, int);
+void pic_do_pending_int(void);
#ifdef MULTIPROCESSOR
int pic_ipi_ast(void *);
int pic_ipi_nop(void *);