Module Name: src Committed By: jmcneill Date: Sat Mar 27 12:15:09 UTC 2021
Modified Files: src/sys/arch/aarch64/include: cpu.h src/sys/arch/arm/include: cpu.h src/sys/arch/arm/pic: pic.c pic_splfuncs.c picvar.h Log Message: Revert recent pic optimizations until I have more time to work on this. To generate a diff of this commit: cvs rdiff -u -r1.33 -r1.34 src/sys/arch/aarch64/include/cpu.h cvs rdiff -u -r1.116 -r1.117 src/sys/arch/arm/include/cpu.h cvs rdiff -u -r1.69 -r1.70 src/sys/arch/arm/pic/pic.c cvs rdiff -u -r1.19 -r1.20 src/sys/arch/arm/pic/pic_splfuncs.c cvs rdiff -u -r1.33 -r1.34 src/sys/arch/arm/pic/picvar.h 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/aarch64/include/cpu.h diff -u src/sys/arch/aarch64/include/cpu.h:1.33 src/sys/arch/aarch64/include/cpu.h:1.34 --- src/sys/arch/aarch64/include/cpu.h:1.33 Sun Feb 21 17:07:06 2021 +++ src/sys/arch/aarch64/include/cpu.h Sat Mar 27 12:15:09 2021 @@ -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; Index: src/sys/arch/arm/include/cpu.h diff -u src/sys/arch/arm/include/cpu.h:1.116 src/sys/arch/arm/include/cpu.h:1.117 --- src/sys/arch/arm/include/cpu.h:1.116 Sun Feb 21 15:00:04 2021 +++ src/sys/arch/arm/include/cpu.h Sat Mar 27 12:15:08 2021 @@ -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 */ Index: src/sys/arch/arm/pic/pic.c diff -u src/sys/arch/arm/pic/pic.c:1.69 src/sys/arch/arm/pic/pic.c:1.70 --- src/sys/arch/arm/pic/pic.c:1.69 Sun Feb 21 17:07:45 2021 +++ src/sys/arch/arm/pic/pic.c Sat Mar 27 12:15:09 2021 @@ -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 #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_soft 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_soft } 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 #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, st } 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, st * 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 *c } 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 } 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 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 irqba 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; Index: src/sys/arch/arm/pic/pic_splfuncs.c diff -u src/sys/arch/arm/pic/pic_splfuncs.c:1.19 src/sys/arch/arm/pic/pic_splfuncs.c:1.20 --- src/sys/arch/arm/pic/pic_splfuncs.c:1.19 Mon Mar 1 11:29:14 2021 +++ src/sys/arch/arm/pic/pic_splfuncs.c Sat Mar 27 12:15:09 2021 @@ -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 #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 Index: src/sys/arch/arm/pic/picvar.h diff -u src/sys/arch/arm/pic/picvar.h:1.33 src/sys/arch/arm/pic/picvar.h:1.34 --- src/sys/arch/arm/pic/picvar.h:1.33 Sat Feb 27 14:22:07 2021 +++ src/sys/arch/arm/pic/picvar.h Sat Mar 27 12:15:09 2021 @@ -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 * 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_ #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 *);