From ebfa05375088d510da702ab7f48d794fb544562f Mon Sep 17 00:00:00 2001 From: miod Date: Tue, 19 May 2015 20:28:14 +0000 Subject: [PATCH] Move acquisition of the kernel lock deeper in the interrupt path, and make sure clock interrupts do not attempt to acquire it. This will also eventually allow for IPL_MPSAFE interrupts on alpha. Tested by dlg@ and I. --- sys/arch/alpha/alpha/interrupt.c | 17 +++----------- sys/arch/alpha/dev/shared_intr.c | 11 ++++++++- sys/arch/alpha/tc/tc_3000_300.c | 38 +++++++++++++++++++++----------- sys/arch/alpha/tc/tc_3000_500.c | 38 +++++++++++++++++++++----------- 4 files changed, 63 insertions(+), 41 deletions(-) diff --git a/sys/arch/alpha/alpha/interrupt.c b/sys/arch/alpha/alpha/interrupt.c index 9be29cd9105..ae7f6134fbc 100644 --- a/sys/arch/alpha/alpha/interrupt.c +++ b/sys/arch/alpha/alpha/interrupt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: interrupt.c,v 1.34 2014/11/18 20:51:00 krw Exp $ */ +/* $OpenBSD: interrupt.c,v 1.35 2015/05/19 20:28:14 miod Exp $ */ /* $NetBSD: interrupt.c,v 1.46 2000/06/03 20:47:36 thorpej Exp $ */ /*- @@ -141,6 +141,7 @@ scb_set(u_long vec, void (*func)(void *, u_long), void *arg) splx(s); } +#ifdef unused u_long scb_alloc(void (*func)(void *, u_long), void *arg) { @@ -169,6 +170,7 @@ scb_alloc(void (*func)(void *, u_long), void *arg) return (SCB_ALLOC_FAILED); } +#endif void scb_free(u_long vec) @@ -260,22 +262,9 @@ interrupt(unsigned long a0, unsigned long a1, unsigned long a2, KDASSERT(a1 >= SCB_IOVECBASE && a1 < SCB_SIZE); atomic_add_ulong(&ci->ci_intrdepth, 1); -#if defined(MULTIPROCESSOR) - /* - * XXX Need to support IPL_MPSAFE eventually. Acquiring the - * XXX kernel lock could be done deeper, as most of the - * XXX scb handlers end up invoking - * XXX alpha_shared_intr_dispatch(). - */ - __mp_lock(&kernel_lock); -#endif atomic_add_int(&uvmexp.intrs, 1); - scb = &scb_iovectab[SCB_VECTOIDX(a1 - SCB_IOVECBASE)]; (*scb->scb_func)(scb->scb_arg, a1); -#if defined(MULTIPROCESSOR) - __mp_unlock(&kernel_lock); -#endif atomic_sub_ulong(&ci->ci_intrdepth, 1); break; } diff --git a/sys/arch/alpha/dev/shared_intr.c b/sys/arch/alpha/dev/shared_intr.c index 2f1066fdd75..7dbeb939bae 100644 --- a/sys/arch/alpha/dev/shared_intr.c +++ b/sys/arch/alpha/dev/shared_intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: shared_intr.c,v 1.20 2014/12/09 06:58:28 doug Exp $ */ +/* $OpenBSD: shared_intr.c,v 1.21 2015/05/19 20:28:14 miod Exp $ */ /* $NetBSD: shared_intr.c,v 1.13 2000/03/19 01:46:18 thorpej Exp $ */ /* @@ -97,6 +97,11 @@ alpha_shared_intr_dispatch(intr, num) handled = 0; TAILQ_FOREACH(ih, &intr[num].intr_q, ih_q) { +#if defined(MULTIPROCESSOR) + /* XXX Need to support IPL_MPSAFE eventually. */ + if (ih->ih_level < IPL_CLOCK) + __mp_lock(&kernel_lock); +#endif /* * The handler returns one of three values: * 0: This interrupt wasn't for me. @@ -107,6 +112,10 @@ alpha_shared_intr_dispatch(intr, num) rv = (*ih->ih_fn)(ih->ih_arg); if (rv) ih->ih_count.ec_count++; +#if defined(MULTIPROCESSOR) + if (ih->ih_level < IPL_CLOCK) + __mp_unlock(&kernel_lock); +#endif handled = handled || (rv != 0); if (intr_shared_edge == 0 && rv == 1) break; diff --git a/sys/arch/alpha/tc/tc_3000_300.c b/sys/arch/alpha/tc/tc_3000_300.c index 7d95c20c091..2104e880be6 100644 --- a/sys/arch/alpha/tc/tc_3000_300.c +++ b/sys/arch/alpha/tc/tc_3000_300.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tc_3000_300.c,v 1.17 2010/09/22 12:36:32 miod Exp $ */ +/* $OpenBSD: tc_3000_300.c,v 1.18 2015/05/19 20:28:14 miod Exp $ */ /* $NetBSD: tc_3000_300.c,v 1.26 2001/07/27 00:25:21 thorpej Exp $ */ /* @@ -84,6 +84,7 @@ int tc_3000_300_nbuiltins = struct tcintr { int (*tci_func)(void *); void *tci_arg; + int tci_level; struct evcount tci_count; } tc_3000_300_intr[TC_3000_300_NCOOKIES]; @@ -105,6 +106,7 @@ tc_3000_300_intr_setup() for (i = 0; i < TC_3000_300_NCOOKIES; i++) { tc_3000_300_intr[i].tci_func = tc_3000_300_intrnull; tc_3000_300_intr[i].tci_arg = (void *)i; + tc_3000_300_intr[i].tci_level = IPL_HIGH; } } @@ -128,6 +130,7 @@ tc_3000_300_intr_establish(tcadev, cookie, level, func, arg, name) tc_3000_300_intr[dev].tci_func = func; tc_3000_300_intr[dev].tci_arg = arg; + tc_3000_300_intr[dev].tci_level = level; if (name != NULL) evcount_attach(&tc_3000_300_intr[dev].tci_count, name, NULL); @@ -177,6 +180,7 @@ tc_3000_300_intr_disestablish(tcadev, cookie, name) tc_3000_300_intr[dev].tci_func = tc_3000_300_intrnull; tc_3000_300_intr[dev].tci_arg = (void *)dev; + tc_3000_300_intr[dev].tci_level = IPL_HIGH; if (name != NULL) evcount_detach(&tc_3000_300_intr[dev].tci_count); } @@ -198,17 +202,6 @@ tc_3000_300_iointr(arg, vec) u_int32_t tcir, ioasicir, ioasicimr; int ifound; -#ifdef DIAGNOSTIC - int s; - if (vec != 0x800) - panic("INVALID ASSUMPTION: vec 0x%lx, not 0x800", vec); - s = splhigh(); - if (s != ALPHA_PSL_IPL_IO) - panic("INVALID ASSUMPTION: IPL %d, not %d", s, - ALPHA_PSL_IPL_IO); - splx(s); -#endif - do { tc_syncbus(); @@ -230,13 +223,27 @@ tc_3000_300_iointr(arg, vec) ifound = 0; +#ifdef MULTIPROCESSOR +#define INTRLOCK(slot) \ + if (tc_3000_300_intr[slot].tci_level < IPL_CLOCK) \ + __mp_lock(&kernel_lock) +#define INTRUNLOCK(slot) \ + if (tc_3000_300_intr[slot].tci_level < IPL_CLOCK) \ + __mp_unlock(&kernel_lock) +#else +#define INTRLOCK(slot) do { } while (0) +#define INTRUNLOCK(slot) do { } while (0) +#endif #define CHECKINTR(slot, flag) \ if (flag) { \ ifound = 1; \ - tc_3000_300_intr[slot].tci_count.ec_count++; \ + INTRLOCK(slot); \ (*tc_3000_300_intr[slot].tci_func) \ (tc_3000_300_intr[slot].tci_arg); \ + tc_3000_300_intr[slot].tci_count.ec_count++; \ + INTRUNLOCK(slot); \ } + /* Do them in order of priority; highest slot # first. */ CHECKINTR(TC_3000_300_DEV_CXTURBO, tcir & TC_3000_300_IR_CXTURBO); @@ -248,12 +255,16 @@ tc_3000_300_iointr(arg, vec) ioasicir & IOASIC_INTR_300_OPT1); CHECKINTR(TC_3000_300_DEV_OPT0, ioasicir & IOASIC_INTR_300_OPT0); + +#undef INTRUNLOCK +#undef INTRLOCK #undef CHECKINTR #ifdef DIAGNOSTIC #define PRINTINTR(msg, bits) \ if (tcir & bits) \ printf(msg); + PRINTINTR("BCache tag parity error\n", TC_3000_300_IR_BCTAGPARITY); PRINTINTR("TC overrun error\n", TC_3000_300_IR_TCOVERRUN); @@ -261,6 +272,7 @@ tc_3000_300_iointr(arg, vec) PRINTINTR("Bcache parity error\n", TC_3000_300_IR_BCACHEPARITY); PRINTINTR("Memory parity error\n", TC_3000_300_IR_MEMPARITY); + #undef PRINTINTR #endif } while (ifound); diff --git a/sys/arch/alpha/tc/tc_3000_500.c b/sys/arch/alpha/tc/tc_3000_500.c index 53d9f99fe10..427f73f8147 100644 --- a/sys/arch/alpha/tc/tc_3000_500.c +++ b/sys/arch/alpha/tc/tc_3000_500.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tc_3000_500.c,v 1.18 2010/09/22 12:36:32 miod Exp $ */ +/* $OpenBSD: tc_3000_500.c,v 1.19 2015/05/19 20:28:14 miod Exp $ */ /* $NetBSD: tc_3000_500.c,v 1.24 2001/07/27 00:25:21 thorpej Exp $ */ /* @@ -97,6 +97,7 @@ u_int32_t tc_3000_500_intrbits[TC_3000_500_NCOOKIES] = { struct tcintr { int (*tci_func)(void *); void *tci_arg; + int tci_level; struct evcount tci_count; } tc_3000_500_intr[TC_3000_500_NCOOKIES]; @@ -123,6 +124,7 @@ tc_3000_500_intr_setup() for (i = 0; i < TC_3000_500_NCOOKIES; i++) { tc_3000_500_intr[i].tci_func = tc_3000_500_intrnull; tc_3000_500_intr[i].tci_arg = (void *)i; + tc_3000_500_intr[i].tci_level = IPL_HIGH; } } @@ -145,6 +147,7 @@ tc_3000_500_intr_establish(tcadev, cookie, level, func, arg, name) tc_3000_500_intr[dev].tci_func = func; tc_3000_500_intr[dev].tci_arg = arg; + tc_3000_500_intr[dev].tci_level = level; if (name != NULL) evcount_attach(&tc_3000_500_intr[dev].tci_count, name, NULL); @@ -175,6 +178,7 @@ tc_3000_500_intr_disestablish(tcadev, cookie, name) tc_3000_500_intr[dev].tci_func = tc_3000_500_intrnull; tc_3000_500_intr[dev].tci_arg = (void *)dev; + tc_3000_500_intr[dev].tci_level = IPL_HIGH; if (name != NULL) evcount_detach(&tc_3000_500_intr[dev].tci_count); } @@ -196,17 +200,6 @@ tc_3000_500_iointr(arg, vec) u_int32_t ir; int ifound; -#ifdef DIAGNOSTIC - int s; - if (vec != 0x800) - panic("INVALID ASSUMPTION: vec 0x%lx, not 0x800", vec); - s = splhigh(); - if (s != ALPHA_PSL_IPL_IO) - panic("INVALID ASSUMPTION: IPL %d, not %d", s, - ALPHA_PSL_IPL_IO); - splx(s); -#endif - do { tc_syncbus(); ir = *(volatile u_int32_t *)TC_3000_500_IR_CLEAR; @@ -216,13 +209,27 @@ tc_3000_500_iointr(arg, vec) ifound = 0; +#ifdef MULTIPROCESSOR +#define INTRLOCK(slot) \ + if (tc_3000_500_intr[slot].tci_level < IPL_CLOCK) \ + __mp_lock(&kernel_lock) +#define INTRUNLOCK(slot) \ + if (tc_3000_500_intr[slot].tci_level < IPL_CLOCK) \ + __mp_unlock(&kernel_lock) +#else +#define INTRLOCK(slot) do { } while (0) +#define INTRUNLOCK(slot) do { } while (0) +#endif #define CHECKINTR(slot) \ if (ir & tc_3000_500_intrbits[slot]) { \ ifound = 1; \ - tc_3000_500_intr[slot].tci_count.ec_count++; \ + INTRLOCK(slot); \ (*tc_3000_500_intr[slot].tci_func) \ (tc_3000_500_intr[slot].tci_arg); \ + tc_3000_500_intr[slot].tci_count.ec_count++; \ + INTRUNLOCK(slot); \ } + /* Do them in order of priority; highest slot # first. */ CHECKINTR(TC_3000_500_DEV_CXTURBO); CHECKINTR(TC_3000_500_DEV_IOASIC); @@ -233,12 +240,16 @@ tc_3000_500_iointr(arg, vec) CHECKINTR(TC_3000_500_DEV_OPT2); CHECKINTR(TC_3000_500_DEV_OPT1); CHECKINTR(TC_3000_500_DEV_OPT0); + +#undef INTRUNLOCK +#undef INTRLOCK #undef CHECKINTR #ifdef DIAGNOSTIC #define PRINTINTR(msg, bits) \ if (ir & bits) \ printf(msg); + PRINTINTR("Second error occurred\n", TC_3000_500_IR_ERR2); PRINTINTR("DMA buffer error\n", TC_3000_500_IR_DMABE); PRINTINTR("DMA cross 2K boundary\n", TC_3000_500_IR_DMA2K); @@ -253,6 +264,7 @@ tc_3000_500_iointr(arg, vec) PRINTINTR("DMA scatter/gather invalid\n", TC_3000_500_IR_DMASG); PRINTINTR("Scatter/gather parity error\n", TC_3000_500_IR_SGPAR); + #undef PRINTINTR #endif } while (ifound); -- 2.20.1