From miod@online.fr Fri May 1 07:03:54 2015 Delivered-To: david@gwynne.id.au Received: by 10.194.71.146 with SMTP id v18csp3345557wju; Thu, 30 Apr 2015 14:03:55 -0700 (PDT) X-Received: by 10.140.98.208 with SMTP id o74mr6367160qge.66.1430427834509; Thu, 30 Apr 2015 14:03:54 -0700 (PDT) Return-Path: Received: from cvs.openbsd.org (cvs.openbsd.org. [199.185.137.3]) by mx.google.com with ESMTPS id e32si1967338yhb.6.2015.04.30.14.03.53 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 30 Apr 2015 14:03:54 -0700 (PDT) Received-SPF: none (google.com: miod@online.fr does not designate permitted sender hosts) client-ip=199.185.137.3; Authentication-Results: mx.google.com; spf=none (google.com: miod@online.fr does not designate permitted sender hosts) smtp.mail=miod@online.fr Received: from shear.ucar.edu (lists.openbsd.org [192.43.244.163]) by cvs.openbsd.org (OpenSMTPD) with ESMTPS id 624251ab TLS version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL; Thu, 30 Apr 2015 15:03:52 -0600 (MDT) Received: from tazenat.gentiane.org (odyssee.gentiane.org [80.65.224.82]) by shear.ucar.edu (8.14.7/8.14.7) with ESMTP id t3UL3k7K006656 (version=TLSv1/SSLv3 cipher=DHE-DSS-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 30 Apr 2015 15:03:49 -0600 (MDT) Received: from localhost (tazenat.gentiane.org [local]); by tazenat.gentiane.org (OpenSMTPD) with ESMTPA id a8c34c1b; Thu, 30 Apr 2015 21:03:46 +0000 (GMT) Date: Thu, 30 Apr 2015 21:03:46 +0000 From: Miod Vallat To: Mark Kettenis Cc: deraadt@openbsd.org, dlg@openbsd.org, landry@openbsd.org Subject: Re: clock interrupts and the kernel lock Message-ID: <20150430210346.GE1681@tazenat.gentiane.org> References: <201504281932.t3SJWZTN020795@glazunov.sibelius.xs4all.nl> <20150430114846.GB1681@tazenat.gentiane.org> <201504301305.t3UD52Ns023809@glazunov.sibelius.xs4all.nl> <20150430145940.GD1681@tazenat.gentiane.org> <201504301521.t3UFLgiY004840@glazunov.sibelius.xs4all.nl> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <201504301521.t3UFLgiY004840@glazunov.sibelius.xs4all.nl> User-Agent: Mutt/1.5.23 (2014-03-12) Status: RO Content-Length: 8945 Lines: 288 Now for alpha. Untested on MP kernels (yet). Note that none of the TC systems is MP-capable, but we nevertheless need GENERIC.MP to work on such systems (even if it's an exercize in futility). Index: alpha/interrupt.c =================================================================== RCS file: /OpenBSD/src/sys/arch/alpha/alpha/interrupt.c,v retrieving revision 1.34 diff -u -p -r1.34 interrupt.c --- alpha/interrupt.c 18 Nov 2014 20:51:00 -0000 1.34 +++ alpha/interrupt.c 30 Apr 2015 20:49:08 -0000 @@ -260,22 +262,9 @@ interrupt(unsigned long a0, unsigned lon 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; } Index: dev/shared_intr.c =================================================================== RCS file: /OpenBSD/src/sys/arch/alpha/dev/shared_intr.c,v retrieving revision 1.20 diff -u -p -r1.20 shared_intr.c --- dev/shared_intr.c 9 Dec 2014 06:58:28 -0000 1.20 +++ dev/shared_intr.c 30 Apr 2015 20:49:08 -0000 @@ -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; Index: tc/tc_3000_300.c =================================================================== RCS file: /OpenBSD/src/sys/arch/alpha/tc/tc_3000_300.c,v retrieving revision 1.17 diff -u -p -r1.17 tc_3000_300.c --- tc/tc_3000_300.c 22 Sep 2010 12:36:32 -0000 1.17 +++ tc/tc_3000_300.c 30 Apr 2015 20:49:09 -0000 @@ -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, cooki 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, co 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); Index: tc/tc_3000_500.c =================================================================== RCS file: /OpenBSD/src/sys/arch/alpha/tc/tc_3000_500.c,v retrieving revision 1.18 diff -u -p -r1.18 tc_3000_500.c --- tc/tc_3000_500.c 22 Sep 2010 12:36:32 -0000 1.18 +++ tc/tc_3000_500.c 30 Apr 2015 20:49:09 -0000 @@ -97,6 +97,7 @@ u_int32_t tc_3000_500_intrbits[TC_3000_5 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, cooki 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, co 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);