diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-10-01 20:19:20 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-10-01 20:19:20 +0000 |
commit | 2f170aacf72c46c917cdfe67ac32e89d65edf81d (patch) | |
tree | 1dc5956ddab9243ed357fece1a6b970c972f9953 /sys/arch/powerpc | |
parent | 6c8d318a056e70f92a487ab483553d455ad77e55 (diff) |
Generic soft interrupts for macppc. Tested by mk@, deraadt@
ok miod@
Diffstat (limited to 'sys/arch/powerpc')
-rw-r--r-- | sys/arch/powerpc/conf/files.powerpc | 3 | ||||
-rw-r--r-- | sys/arch/powerpc/include/_types.h | 3 | ||||
-rw-r--r-- | sys/arch/powerpc/include/intr.h | 68 | ||||
-rw-r--r-- | sys/arch/powerpc/powerpc/softintr.c | 221 |
4 files changed, 275 insertions, 20 deletions
diff --git a/sys/arch/powerpc/conf/files.powerpc b/sys/arch/powerpc/conf/files.powerpc index 51c7956b2a8..6710564694a 100644 --- a/sys/arch/powerpc/conf/files.powerpc +++ b/sys/arch/powerpc/conf/files.powerpc @@ -1,4 +1,4 @@ -# $OpenBSD: files.powerpc,v 1.46 2008/04/25 14:51:35 jmc Exp $ +# $OpenBSD: files.powerpc,v 1.47 2009/10/01 20:19:19 kettenis Exp $ # file arch/powerpc/powerpc/setjmp.S ddb @@ -14,6 +14,7 @@ file arch/powerpc/powerpc/trap.c file arch/powerpc/powerpc/vm_machdep.c file arch/powerpc/powerpc/mutex.S file arch/powerpc/powerpc/intr.c +file arch/powerpc/powerpc/softintr.c file arch/powerpc/ddb/db_memrw.c ddb file arch/powerpc/ddb/db_disasm.c ddb diff --git a/sys/arch/powerpc/include/_types.h b/sys/arch/powerpc/include/_types.h index 9d3a51f6e95..9cf552e0b4f 100644 --- a/sys/arch/powerpc/include/_types.h +++ b/sys/arch/powerpc/include/_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: _types.h,v 1.8 2008/07/21 20:50:55 martynas Exp $ */ +/* $OpenBSD: _types.h,v 1.9 2009/10/01 20:19:19 kettenis Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -118,6 +118,7 @@ typedef void * __wctrans_t; typedef void * __wctype_t; /* Feature test macros */ +#define __HAVE_GENERIC_SOFT_INTERRUPTS #define __HAVE_TIMECOUNTER #endif /* _POWERPC__TYPES_H_ */ diff --git a/sys/arch/powerpc/include/intr.h b/sys/arch/powerpc/include/intr.h index 455cebf38dd..937c3f5f26e 100644 --- a/sys/arch/powerpc/include/intr.h +++ b/sys/arch/powerpc/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.42 2009/08/22 02:54:50 mk Exp $ */ +/* $OpenBSD: intr.h,v 1.43 2009/10/01 20:19:19 kettenis Exp $ */ /* * Copyright (c) 1997 Per Fogelstrom, Opsycon AB and RTMX Inc, USA. @@ -59,13 +59,6 @@ #define PPC_CLK_IRQ 64 #define PPC_STAT_IRQ 65 -void setsoftclock(void); -void clearsoftclock(void); -int splsoftclock(void); -void setsoftnet(void); -void clearsoftnet(void); -int splsoftnet(void); - int splraise(int); int spllower(int); void splx(int); @@ -79,13 +72,56 @@ extern int imask[IPL_NUM]; #define splassert(wantipl) /* nothing */ #define splsoftassert(wantipl) /* nothing */ -#define set_sint(p) atomic_setbits_int(&curcpu()->ci_ipending, p) +#define SINTBIT(q) (31 - (q)) +#define SINTMASK(q) (1 << SINTBIT(q)) + +#define SPL_CLOCKMASK SINTMASK(SI_NQUEUES) + +/* Soft interrupt masks. */ + +#define IPL_SOFTCLOCK 0 +#define IPL_SOFTNET 1 +#define IPL_SOFTTTY 2 -#define SINT_CLOCK 0x10000000 -#define SINT_NET 0x20000000 -#define SINT_TTY 0x40000000 -#define SPL_CLOCK 0x80000000 -#define SINT_MASK (SINT_CLOCK|SINT_NET|SINT_TTY) +#define SI_SOFTCLOCK 0 /* for IPL_SOFTCLOCK */ +#define SI_SOFTNET 1 /* for IPL_SOFTNET */ +#define SI_SOFTTTY 2 /* for IPL_SOFTTY */ + +#define SINT_ALLMASK (SINTMASK(SI_SOFTCLOCK) | \ + SINTMASK(SI_SOFTNET) | SINTMASK(SI_SOFTTTY)) +#define SI_NQUEUES 3 + +#include <machine/mutex.h> +#include <sys/queue.h> + +struct soft_intrhand { + TAILQ_ENTRY(soft_intrhand) sih_list; + void (*sih_func)(void *); + void *sih_arg; + struct soft_intrq *sih_siq; + int sih_pending; +}; + +struct soft_intrq { + TAILQ_HEAD(, soft_intrhand) siq_list; + int siq_si; + struct mutex siq_mtx; +}; + +void softintr_disestablish(void *); +void softintr_dispatch(int); +void *softintr_establish(int, void (*)(void *), void *); +void softintr_init(void); +void softintr_schedule(void *); + +/* XXX For legacy software interrupts. */ +extern struct soft_intrhand *softnet_intrhand; + +#define setsoftnet() softintr_schedule(softnet_intrhand) + +#define SINT_CLOCK SINTMASK(SI_SOFTCLOCK) +#define SINT_NET SINTMASK(SI_SOFTNET) +#define SINT_TTY SINTMASK(SI_SOFTTTY) #define splbio() splraise(imask[IPL_BIO]) #define splnet() splraise(imask[IPL_NET]) @@ -100,10 +136,6 @@ extern int imask[IPL_NUM]; #define splsoftnet() splraise(SINT_NET|SINT_CLOCK) #define splsofttty() splraise(SINT_TTY|SINT_NET|SINT_CLOCK) -#define setsoftclock() set_sint(SINT_CLOCK); -#define setsoftnet() set_sint(SINT_NET); -#define setsofttty() set_sint(SINT_TTY); - #define splhigh() splraise(0xffffffff) #define spl0() spllower(0) diff --git a/sys/arch/powerpc/powerpc/softintr.c b/sys/arch/powerpc/powerpc/softintr.c new file mode 100644 index 00000000000..79ddc5cd627 --- /dev/null +++ b/sys/arch/powerpc/powerpc/softintr.c @@ -0,0 +1,221 @@ +/* $OpenBSD: softintr.c,v 1.1 2009/10/01 20:19:19 kettenis Exp $ */ +/* $NetBSD: softintr.c,v 1.2 2003/07/15 00:24:39 lukem Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/malloc.h> + +/* XXX Network interrupts should be converted to new softintrs. */ +#include <net/netisr.h> + +#include <uvm/uvm_extern.h> + +#include <machine/atomic.h> +#include <machine/intr.h> + +struct soft_intrq soft_intrq[SI_NQUEUES]; + +struct soft_intrhand *softnet_intrhand; + +void netintr(void); + +/* + * Initialize the software interrupt system. + */ +void +softintr_init(void) +{ + struct soft_intrq *siq; + int i; + + for (i = 0; i < SI_NQUEUES; i++) { + siq = &soft_intrq[i]; + TAILQ_INIT(&siq->siq_list); + siq->siq_si = i; + mtx_init(&siq->siq_mtx, IPL_HIGH); + } + + /* XXX Establish legacy software interrupt handlers. */ + softnet_intrhand = softintr_establish(IPL_SOFTNET, + (void (*)(void *))netintr, NULL); +} + +/* + * Process pending software interrupts on the specified queue. + * + * NOTE: We must already be at the correct interrupt priority level. + */ +void +softintr_dispatch(int si) +{ + struct soft_intrq *siq = &soft_intrq[si]; + struct soft_intrhand *sih; + + for (;;) { + mtx_enter(&siq->siq_mtx); + sih = TAILQ_FIRST(&siq->siq_list); + if (sih == NULL) { + mtx_leave(&siq->siq_mtx); + break; + } + + TAILQ_REMOVE(&siq->siq_list, sih, sih_list); + sih->sih_pending = 0; + + uvmexp.softs++; + + mtx_leave(&siq->siq_mtx); + + (*sih->sih_func)(sih->sih_arg); + } +} + +/* + * Register a software interrupt handler. + */ +void * +softintr_establish(int ipl, void (*func)(void *), void *arg) +{ + struct soft_intrhand *sih; + int si; + + switch (ipl) { +#if 0 + case IPL_SOFT: + si = SI_SOFT; + break; +#endif + case IPL_SOFTCLOCK: + si = SI_SOFTCLOCK; + break; + case IPL_SOFTNET: + si = SI_SOFTNET; + break; + case IPL_TTY: /* XXX until MI code is fixed */ + case IPL_SOFTTTY: + si = SI_SOFTTTY; + break; + default: + printf("softintr_establish: unknown soft IPL %d\n", ipl); + return NULL; + } + + sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT); + if (__predict_true(sih != NULL)) { + sih->sih_func = func; + sih->sih_arg = arg; + sih->sih_siq = &soft_intrq[si]; + sih->sih_pending = 0; + } + return (sih); +} + +/* + * Unregister a software interrupt handler. + */ +void +softintr_disestablish(void *arg) +{ + struct soft_intrhand *sih = arg; + struct soft_intrq *siq = sih->sih_siq; + + mtx_enter(&siq->siq_mtx); + if (sih->sih_pending) { + TAILQ_REMOVE(&siq->siq_list, sih, sih_list); + sih->sih_pending = 0; + } + mtx_leave(&siq->siq_mtx); + + free(sih, M_DEVBUF); +} + +/* + * Schedule a software interrupt. + */ +void +softintr_schedule(void *arg) +{ + struct soft_intrhand *sih = (struct soft_intrhand *)arg; + struct soft_intrq *siq = sih->sih_siq; + struct cpu_info *ci = curcpu(); + + mtx_enter(&siq->siq_mtx); + if (sih->sih_pending == 0) { + TAILQ_INSERT_TAIL(&siq->siq_list, sih, sih_list); + sih->sih_pending = 1; + atomic_setbits_int(&ci->ci_ipending, SINTMASK(siq->siq_si)); + } + mtx_leave(&siq->siq_mtx); +} + +int netisr; + +void +netintr(void) +{ + int n; + + while ((n = netisr) != 0) { + atomic_clearbits_int(&netisr, n); +#define DONETISR(bit, fn) \ + do { \ + if (n & (1 << (bit))) \ + fn(); \ + } while (0) +#include <net/netisr_dispatch.h> +#undef DONETISR + } +} + +#if 0 +void +dosoftint(int xcpl) +{ + struct cpu_info *ci = curcpu(); + int sir, q, mask; + + while ((sir = (ci->ci_ipending & SINT_ALLMASK & ~xcpl)) != 0) { + atomic_clearbits_int(&ci->ci_ipending, sir); + + for (q = SI_NQUEUES - 1; q >= 0; q--) { + mask = SINTMASK(q); + if (sir & mask) + softintr_dispatch(q); + } + } +} +#endif |