summaryrefslogtreecommitdiff
path: root/sys/arch/powerpc
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-10-01 20:19:20 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-10-01 20:19:20 +0000
commit2f170aacf72c46c917cdfe67ac32e89d65edf81d (patch)
tree1dc5956ddab9243ed357fece1a6b970c972f9953 /sys/arch/powerpc
parent6c8d318a056e70f92a487ab483553d455ad77e55 (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.powerpc3
-rw-r--r--sys/arch/powerpc/include/_types.h3
-rw-r--r--sys/arch/powerpc/include/intr.h68
-rw-r--r--sys/arch/powerpc/powerpc/softintr.c221
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