summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-01-04 13:01:43 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-01-04 13:01:43 +0000
commitb5aa09b33d64540760172d36438ee5864c0b24f4 (patch)
treed4b642b74030caea41fe90cdecbd3e87b8104afb
parent11e22c6125c49fc01f5752389ca129e42973f458 (diff)
Implement splassert(9) for powerpc.
This changes the logic to prevent a recursion when processing soft interrupts. Previously a per-CPU flag was set before re-enabling interrupts. Now the IPL level is raised to SOFTTTY which makes splsoftassert() happy, greatly inspired by mips64. As a side effect, the ppc_intr_{disable,enable}() dance is now done only once instead of twice per splx(9). While here, make use of dosoftint() instead of having 3 different functions for dispatching soft interrupts. Tested by deraadt@ on G4 smp and by myself G5 smp, G3, G4 and socppc. No objection from the usual (and over busy) suspects.
-rw-r--r--sys/arch/macppc/dev/macintr.c69
-rw-r--r--sys/arch/macppc/dev/openpic.c104
-rw-r--r--sys/arch/powerpc/include/cpu.h3
-rw-r--r--sys/arch/powerpc/include/intr.h23
-rw-r--r--sys/arch/powerpc/powerpc/intr.c18
-rw-r--r--sys/arch/powerpc/powerpc/softintr.c18
-rw-r--r--sys/arch/socppc/dev/ipic.c21
-rw-r--r--sys/arch/socppc/socppc/machdep.c39
8 files changed, 101 insertions, 194 deletions
diff --git a/sys/arch/macppc/dev/macintr.c b/sys/arch/macppc/dev/macintr.c
index b0c69316db0..443e70a57f2 100644
--- a/sys/arch/macppc/dev/macintr.c
+++ b/sys/arch/macppc/dev/macintr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: macintr.c,v 1.49 2014/09/06 10:45:29 mpi Exp $ */
+/* $OpenBSD: macintr.c,v 1.50 2015/01/04 13:01:42 mpi Exp $ */
/*-
* Copyright (c) 2008 Dale Rahn <drahn@openbsd.org>
@@ -64,7 +64,6 @@ struct intrq macintr_handler[ICU_LEN];
void macintr_calc_mask(void);
void macintr_eoi(int irq);
int macintr_read_irq(void);
-static void macintr_do_pending_int(void);
extern u_int32_t *heathrow_FCR;
@@ -83,7 +82,6 @@ struct macintr_softc {
int macintr_match(struct device *parent, void *cf, void *aux);
void macintr_attach(struct device *, struct device *, void *);
-void mac_do_pending_int(void);
void mac_ext_intr(void);
void macintr_collect_preconf_intr(void);
void macintr_setipl(int ipl);
@@ -125,7 +123,6 @@ macintr_match(struct device *parent, void *cf, void *aux)
u_int8_t *interrupt_reg;
typedef void (void_f) (void);
-extern void_f *pending_int_f;
int macintr_prog_button (void *arg);
intr_establish_t macintr_establish;
@@ -142,12 +139,16 @@ int
macintr_splraise(int newcpl)
{
struct cpu_info *ci = curcpu();
- newcpl = macintr_pri_share[newcpl];
int ocpl = ci->ci_cpl;
+ int s;
+
+ newcpl = macintr_pri_share[newcpl];
if (ocpl > newcpl)
newcpl = ocpl;
+ s = ppc_intr_disable();
macintr_setipl(newcpl);
+ ppc_intr_enable(s);
return ocpl;
}
@@ -167,10 +168,16 @@ void
macintr_splx(int newcpl)
{
struct cpu_info *ci = curcpu();
-
+ int intr, s;
+
+ intr = ppc_intr_disable();
macintr_setipl(newcpl);
- if (ci->ci_ipending & ppc_smask[newcpl])
- macintr_do_pending_int();
+ if ((newcpl < IPL_SOFTTTY && ci->ci_ipending & ppc_smask[newcpl])) {
+ s = splsofttty();
+ dosoftint(newcpl);
+ macintr_setipl(s); /* no-overhead splx */
+ }
+ ppc_intr_enable(intr);
}
void
@@ -192,7 +199,6 @@ macintr_attach(struct device *parent, struct device *self, void *aux)
ppc_smask_init();
install_extint(mac_ext_intr);
- pending_int_f = macintr_do_pending_int;
intr_establish_func = macintr_establish;
intr_disestablish_func = macintr_disestablish;
mac_intr_establish_func = macintr_establish;
@@ -254,19 +260,18 @@ macintr_prog_button (void *arg)
return 1;
}
+/* Must be called with interrupt disable. */
void
macintr_setipl(int ipl)
{
struct cpu_info *ci = curcpu();
- int s;
- s = ppc_intr_disable();
+
ci->ci_cpl = ipl;
if (heathrow_FCR)
out32rb(INT_ENABLE_REG1,
macintr_ienable_h[macintr_pri_share[ipl]]);
out32rb(INT_ENABLE_REG0, macintr_ienable_l[macintr_pri_share[ipl]]);
- ppc_intr_enable(s);
}
/*
@@ -469,45 +474,7 @@ mac_ext_intr()
irq = macintr_read_irq();
}
- ppc_intr_enable(1);
- splx(pcpl); /* Process pendings. */
-}
-
-void
-macintr_do_pending_int()
-{
- struct cpu_info *ci = curcpu();
- int pcpl = ci->ci_cpl; /* XXX */
- int s;
- s = ppc_intr_disable();
- if (ci->ci_flags & CI_FLAGS_PROCESSING_SOFT) {
- ppc_intr_enable(s);
- return;
- }
- atomic_setbits_int(&ci->ci_flags, CI_FLAGS_PROCESSING_SOFT);
-
- do {
- if((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTCLOCK)) &&
- (pcpl < IPL_SOFTCLOCK)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTCLOCK);
- softintr_dispatch(SI_SOFTCLOCK);
- }
- if((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTNET)) &&
- (pcpl < IPL_SOFTNET)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTNET);
- softintr_dispatch(SI_SOFTNET);
- }
- if((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTTTY)) &&
- (pcpl < IPL_SOFTTTY)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTTTY);
- softintr_dispatch(SI_SOFTTTY);
- }
-
- } while (ci->ci_ipending & ppc_smask[pcpl]);
- macintr_setipl(pcpl);
- ppc_intr_enable(s);
-
- atomic_clearbits_int(&ci->ci_flags, CI_FLAGS_PROCESSING_SOFT);
+ macintr_splx(pcpl); /* Process pendings. */
}
void
diff --git a/sys/arch/macppc/dev/openpic.c b/sys/arch/macppc/dev/openpic.c
index 1b55ffd0e15..41ee10334ca 100644
--- a/sys/arch/macppc/dev/openpic.c
+++ b/sys/arch/macppc/dev/openpic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: openpic.c,v 1.75 2014/10/08 22:24:26 deraadt Exp $ */
+/* $OpenBSD: openpic.c,v 1.76 2015/01/04 13:01:42 mpi Exp $ */
/*-
* Copyright (c) 2008 Dale Rahn <drahn@openbsd.org>
@@ -108,8 +108,6 @@ struct openpic_softc {
int openpic_match(struct device *parent, void *cf, void *aux);
void openpic_attach(struct device *, struct device *, void *);
-void openpic_do_pending_int(int pcpl);
-void openpic_do_pending_int_dis(int pcpl, int s);
void openpic_collect_preconf_intr(void);
void openpic_ext_intr(void);
@@ -235,28 +233,30 @@ openpic_attach(struct device *parent, struct device *self, void *aux)
printf("\n");
}
+/* Must be called with interrupt disable. */
static inline void
openpic_setipl(int newcpl)
{
struct cpu_info *ci = curcpu();
- int s;
- /* XXX - try do to this without the disable */
- s = ppc_intr_disable();
+
ci->ci_cpl = newcpl;
openpic_set_priority(ci->ci_cpuid, newcpl);
- ppc_intr_enable(s);
}
int
openpic_splraise(int newcpl)
{
struct cpu_info *ci = curcpu();
- newcpl = openpic_pri_share[newcpl];
int ocpl = ci->ci_cpl;
+ int s;
+
+ newcpl = openpic_pri_share[newcpl];
if (ocpl > newcpl)
newcpl = ocpl;
+ s = ppc_intr_disable();
openpic_setipl(newcpl);
+ ppc_intr_enable(s);
return ocpl;
}
@@ -275,7 +275,17 @@ openpic_spllower(int newcpl)
void
openpic_splx(int newcpl)
{
- openpic_do_pending_int(newcpl);
+ struct cpu_info *ci = curcpu();
+ int intr, s;
+
+ intr = ppc_intr_disable();
+ openpic_setipl(newcpl);
+ if (newcpl < IPL_SOFTTTY && (ci->ci_ipending & ppc_smask[newcpl])) {
+ s = splsofttty();
+ dosoftint(newcpl);
+ openpic_setipl(s); /* no-overhead splx */
+ }
+ ppc_intr_enable(intr);
}
void
@@ -442,71 +452,6 @@ openpic_calc_mask()
}
void
-openpic_do_pending_int(int pcpl)
-{
- int s;
- s = ppc_intr_disable();
- openpic_do_pending_int_dis(pcpl, s);
- ppc_intr_enable(s);
-
-}
-
-/*
- * This function expect interrupts disabled on entry and exit,
- * the s argument indicates if interrupts may be enabled during
- * the processing of off level interrupts, s 'should' always be 1.
- */
-void
-openpic_do_pending_int_dis(int pcpl, int s)
-{
- struct cpu_info *ci = curcpu();
-
- (void)ppc_intr_disable();
- if (ci->ci_flags & CI_FLAGS_PROCESSING_SOFT) {
- /* soft interrupts are being processed, just set ipl/return */
- openpic_setipl(pcpl);
- ppc_intr_enable(s);
- return;
- }
-
- atomic_setbits_int(&ci->ci_flags, CI_FLAGS_PROCESSING_SOFT);
-
- do {
- if ((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTCLOCK)) &&
- (pcpl < IPL_SOFTCLOCK)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTCLOCK);
- ppc_intr_enable(1);
- KERNEL_LOCK();
- softintr_dispatch(SI_SOFTCLOCK);
- KERNEL_UNLOCK();
- (void)ppc_intr_disable();
- }
- if ((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTNET)) &&
- (pcpl < IPL_SOFTNET)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTNET);
- ppc_intr_enable(1);
- KERNEL_LOCK();
- softintr_dispatch(SI_SOFTNET);
- KERNEL_UNLOCK();
- (void)ppc_intr_disable();
- }
- if ((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTTTY)) &&
- (pcpl < IPL_SOFTTTY)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTTTY);
- ppc_intr_enable(1);
- KERNEL_LOCK();
- softintr_dispatch(SI_SOFTTTY);
- KERNEL_UNLOCK();
- (void)ppc_intr_disable();
- }
- } while (ci->ci_ipending & ppc_smask[pcpl]);
- openpic_setipl(pcpl); /* Don't use splx... we are here already! */
-
- atomic_clearbits_int(&ci->ci_flags, CI_FLAGS_PROCESSING_SOFT);
- ppc_intr_enable(s);
-}
-
-void
openpic_enable_irq(int irq, int pri)
{
u_int x;
@@ -618,7 +563,7 @@ openpic_ext_intr()
openpic_read(OPENPIC_CPU_PRIORITY(ci->ci_cpuid)));
if (iq->iq_ipl > maxipl)
maxipl = iq->iq_ipl;
- splraise(iq->iq_ipl);
+ openpic_splraise(iq->iq_ipl);
openpic_eoi(ci->ci_cpuid);
spurious = 1;
@@ -649,14 +594,7 @@ openpic_ext_intr()
irq = openpic_read_irq(ci->ci_cpuid);
}
- /*
- * sending 0 in to openpic_do_pending_int_dis will leave
- * external interrupts disabled, but since we are about
- * to return from interrupt leaving them disabled until then
- * prevents additional recursion.
- */
- openpic_do_pending_int_dis(pcpl, 0);
-
+ openpic_splx(pcpl); /* Process pendings. */
openpic_irqnest[ci->ci_cpuid]--;
}
diff --git a/sys/arch/powerpc/include/cpu.h b/sys/arch/powerpc/include/cpu.h
index ecd5b9e796b..567f0433b58 100644
--- a/sys/arch/powerpc/include/cpu.h
+++ b/sys/arch/powerpc/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.58 2014/10/10 04:08:11 mpi Exp $ */
+/* $OpenBSD: cpu.h,v 1.59 2015/01/04 13:01:42 mpi Exp $ */
/* $NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $ */
/*
@@ -57,7 +57,6 @@ struct cpu_info {
volatile int ci_ipending;
volatile int ci_flags;
-#define CI_FLAGS_PROCESSING_SOFT 1
#define CI_FLAGS_SLEEPING 2
int ci_intrdepth;
diff --git a/sys/arch/powerpc/include/intr.h b/sys/arch/powerpc/include/intr.h
index ce2d4142d43..448e729bf30 100644
--- a/sys/arch/powerpc/include/intr.h
+++ b/sys/arch/powerpc/include/intr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.h,v 1.49 2013/05/17 19:38:52 kettenis Exp $ */
+/* $OpenBSD: intr.h,v 1.50 2015/01/04 13:01:42 mpi Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom, Opsycon AB and RTMX Inc, USA.
@@ -88,8 +88,24 @@ char *ppc_intr_typename(int type);
void do_pending_int(void);
/* SPL asserts */
-#define splassert(wantipl) /* nothing */
-#define splsoftassert(wantipl) /* nothing */
+#ifdef DIAGNOSTIC
+/*
+ * Although this function is implemented in MI code, it must be in this MD
+ * header because we don't want this header to include MI includes.
+ */
+void splassert_fail(int, int, const char *);
+extern int splassert_ctl;
+void splassert_check(int, const char *);
+#define splassert(__wantipl) do { \
+ if (splassert_ctl > 0) { \
+ splassert_check(__wantipl, __func__); \
+ } \
+} while (0)
+#define splsoftassert(wantipl) splassert(wantipl)
+#else
+#define splassert(wantipl) do { /* nada */ } while (0)
+#define splsoftassert(wantipl) do { /* nada */ } while (0)
+#endif
#define set_sint(p) atomic_setbits_int(&curcpu()->ci_ipending, p)
@@ -138,6 +154,7 @@ void *softintr_establish(int, void (*)(void *), void *);
void softintr_init(void);
void softintr_schedule(void *);
+void dosoftint(int);
#define set_sint(p) atomic_setbits_int(&curcpu()->ci_ipending, p)
diff --git a/sys/arch/powerpc/powerpc/intr.c b/sys/arch/powerpc/powerpc/intr.c
index fa5535d646c..35b62911893 100644
--- a/sys/arch/powerpc/powerpc/intr.c
+++ b/sys/arch/powerpc/powerpc/intr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.c,v 1.7 2011/08/29 20:21:44 drahn Exp $ */
+/* $OpenBSD: intr.c,v 1.8 2015/01/04 13:01:42 mpi Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom, Opsycon AB and RTMX Inc, USA.
@@ -121,7 +121,7 @@ ppc_dflt_splx(int newcpl)
ci->ci_cpl = newcpl;
if (ci->ci_ipending & ppc_smask[newcpl])
- do_pending_int();
+ dosoftint(newcpl);
}
struct ppc_intr_func ppc_intr_func =
@@ -147,3 +147,17 @@ ppc_intr_typename(int type)
return ("unknown");
}
}
+
+#ifdef DIAGNOSTIC
+void
+splassert_check(int wantipl, const char *func)
+{
+ struct cpu_info *ci = curcpu();
+
+ if (ci->ci_cpl < wantipl)
+ splassert_fail(wantipl, ci->ci_cpl, func);
+
+ if (wantipl == IPL_NONE && ci->ci_intrdepth != -1)
+ splassert_fail(-1, ci->ci_intrdepth, func);
+}
+#endif
diff --git a/sys/arch/powerpc/powerpc/softintr.c b/sys/arch/powerpc/powerpc/softintr.c
index f018a1b120a..6f5f92acfc5 100644
--- a/sys/arch/powerpc/powerpc/softintr.c
+++ b/sys/arch/powerpc/powerpc/softintr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softintr.c,v 1.6 2014/07/12 18:44:42 tedu Exp $ */
+/* $OpenBSD: softintr.c,v 1.7 2015/01/04 13:01:42 mpi Exp $ */
/* $NetBSD: softintr.c,v 1.2 2003/07/15 00:24:39 lukem Exp $ */
/*
@@ -92,9 +92,7 @@ softintr_dispatch(int si)
mtx_leave(&siq->siq_mtx);
- KERNEL_LOCK();
(*sih->sih_func)(sih->sih_arg);
- KERNEL_UNLOCK();
}
}
@@ -176,21 +174,25 @@ softintr_schedule(void *arg)
mtx_leave(&siq->siq_mtx);
}
-#if 0
void
-dosoftint(int xcpl)
+dosoftint(int pcpl)
{
struct cpu_info *ci = curcpu();
int sir, q, mask;
- while ((sir = (ci->ci_ipending & SINT_ALLMASK & ~xcpl)) != 0) {
+ ppc_intr_enable(1);
+ KERNEL_LOCK();
+
+ while ((sir = (ci->ci_ipending & ppc_smask[pcpl])) != 0) {
atomic_clearbits_int(&ci->ci_ipending, sir);
for (q = SI_NQUEUES - 1; q >= 0; q--) {
- mask = SINTMASK(q);
+ mask = SI_TO_IRQBIT(q);
if (sir & mask)
softintr_dispatch(q);
}
}
+
+ KERNEL_UNLOCK();
+ (void)ppc_intr_disable();
}
-#endif
diff --git a/sys/arch/socppc/dev/ipic.c b/sys/arch/socppc/dev/ipic.c
index b7205e5c490..44b4d37f305 100644
--- a/sys/arch/socppc/dev/ipic.c
+++ b/sys/arch/socppc/dev/ipic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipic.c,v 1.16 2014/02/08 10:58:17 kettenis Exp $ */
+/* $OpenBSD: ipic.c,v 1.17 2015/01/04 13:01:42 mpi Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -298,11 +298,11 @@ intr_establish(int ivec, int type, int level,
*/
s = ppc_intr_disable();
TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list);
- ppc_intr_enable(s);
/* Unmask the interrupt. */
if (sc)
ipic_setipl(curcpu()->ci_cpl);
+ ppc_intr_enable(s);
return (ih);
}
@@ -347,11 +347,14 @@ ipic_splraise(int newcpl)
{
struct cpu_info *ci = curcpu();
int ocpl = ci->ci_cpl;
+ int s;
if (ocpl > newcpl)
newcpl = ocpl;
+ s = ppc_intr_disable();
ipic_setipl(newcpl);
+ ppc_intr_enable(s);
return (ocpl);
}
@@ -371,21 +374,26 @@ void
ipic_splx(int newcpl)
{
struct cpu_info *ci = curcpu();
+ int intr, s;
+ intr = ppc_intr_disable();
ipic_setipl(newcpl);
- if (ci->ci_ipending & ppc_smask[newcpl])
- do_pending_int();
+ if (newcpl < IPL_SOFTTTY && (ci->ci_ipending & ppc_smask[newcpl])) {
+ s = splsofttty();
+ dosoftint(newcpl);
+ ipic_setipl(s); /* no-overhead splx */
+ }
+ ppc_intr_enable(intr);
}
+/* Must be called with interrupt disable. */
void
ipic_setipl(int ipl)
{
struct cpu_info *ci = curcpu();
struct ipic_softc *sc = ipic_sc;
uint32_t mask;
- int s;
- s = ppc_intr_disable();
ci->ci_cpl = ipl;
mask = sc->sc_simsr_h[IPL_HIGH] & ~sc->sc_simsr_h[ipl];
ipic_write(sc, IPIC_SIMSR_H, mask);
@@ -393,5 +401,4 @@ ipic_setipl(int ipl)
ipic_write(sc, IPIC_SIMSR_L, mask);
mask = sc->sc_semsr[IPL_HIGH] & ~sc->sc_semsr[ipl];
ipic_write(sc, IPIC_SEMSR, mask);
- ppc_intr_enable(s);
}
diff --git a/sys/arch/socppc/socppc/machdep.c b/sys/arch/socppc/socppc/machdep.c
index 2edb7167d7e..2f9d5fc3d1c 100644
--- a/sys/arch/socppc/socppc/machdep.c
+++ b/sys/arch/socppc/socppc/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.60 2014/12/10 15:29:53 mikeb Exp $ */
+/* $OpenBSD: machdep.c,v 1.61 2015/01/04 13:01:42 mpi Exp $ */
/* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */
/*
@@ -1084,43 +1084,6 @@ haltsys:
/* NOTREACHED */
}
-void
-do_pending_int(void)
-{
- struct cpu_info *ci = curcpu();
- int pcpl = ci->ci_cpl; /* XXX */
- int s;
- s = ppc_intr_disable();
- if (ci->ci_flags & CI_FLAGS_PROCESSING_SOFT) {
- ppc_intr_enable(s);
- return;
- }
- atomic_setbits_int(&ci->ci_flags, CI_FLAGS_PROCESSING_SOFT);
-
- do {
- if((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTCLOCK)) &&
- (pcpl < IPL_SOFTCLOCK)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTCLOCK);
- softintr_dispatch(SI_SOFTCLOCK);
- }
- if((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTNET)) &&
- (pcpl < IPL_SOFTNET)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTNET);
- softintr_dispatch(SI_SOFTNET);
- }
- if((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTTTY)) &&
- (pcpl < IPL_SOFTTTY)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTTTY);
- softintr_dispatch(SI_SOFTTTY);
- }
-
- } while (ci->ci_ipending & ppc_smask[pcpl]);
- splx(pcpl);
- ppc_intr_enable(s);
-
- atomic_clearbits_int(&ci->ci_flags, CI_FLAGS_PROCESSING_SOFT);
-}
-
/*
* Notify the current process (p) that it has a signal pending,
* process as soon as possible.