Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sparc/sparc In DIAGNOSTIC kernels detect situation ...
details: https://anonhg.NetBSD.org/src/rev/50cfe9a7940b
branches: trunk
changeset: 534852:50cfe9a7940b
user: uwe <uwe%NetBSD.org@localhost>
date: Sun Aug 04 14:57:34 2002 +0000
description:
In DIAGNOSTIC kernels detect situation that on sun4m neither hardware
nor software interrupt pending bit is set for the current ipl. Report
this as a "bogus" interrupt (better name anyone?). This is a symptom
of a bug in interrupt handling in one of device drivers interrupting
at this ipl. Reviewed by pk.
diffstat:
sys/arch/sparc/sparc/intr.c | 26 ++++++++++-
sys/arch/sparc/sparc/locore.s | 95 +++++++++++++++++++++++++++++++++++++-----
2 files changed, 107 insertions(+), 14 deletions(-)
diffs (178 lines):
diff -r e6f8c8867d6e -r 50cfe9a7940b sys/arch/sparc/sparc/intr.c
--- a/sys/arch/sparc/sparc/intr.c Sun Aug 04 14:43:47 2002 +0000
+++ b/sys/arch/sparc/sparc/intr.c Sun Aug 04 14:57:34 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.c,v 1.58 2001/12/04 00:05:06 darrenr Exp $ */
+/* $NetBSD: intr.c,v 1.59 2002/08/04 14:57:34 uwe Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -75,6 +75,9 @@
void *softnet_cookie;
void strayintr __P((struct clockframe *));
+#ifdef DIAGNOSTIC
+void bogusintr __P((struct clockframe *));
+#endif
void softnet __P((void *));
/*
@@ -96,7 +99,7 @@
timesince = time.tv_sec - straytime;
if (timesince <= 10) {
- if (++nstray > 9)
+ if (++nstray > 10)
panic("crazy interrupts");
} else {
straytime = time.tv_sec;
@@ -104,6 +107,25 @@
}
}
+
+#ifdef DIAGNOSTIC
+/*
+ * Bogus interrupt for which neither hard nor soft interrupt bit in
+ * the IPR was set.
+ */
+void
+bogusintr(fp)
+ struct clockframe *fp;
+{
+ char bits[64];
+
+ printf("bogus interrupt ipl 0x%x pc=0x%x npc=0x%x psr=%s\n",
+ fp->ipl, fp->pc, fp->npc, bitmask_snprintf(fp->psr,
+ PSR_BITS, bits, sizeof(bits)));
+}
+#endif /* DIAGNOSTIC */
+
+
/*
* Process software network interrupts.
*/
diff -r e6f8c8867d6e -r 50cfe9a7940b sys/arch/sparc/sparc/locore.s
--- a/sys/arch/sparc/sparc/locore.s Sun Aug 04 14:43:47 2002 +0000
+++ b/sys/arch/sparc/sparc/locore.s Sun Aug 04 14:57:34 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.s,v 1.159 2002/07/17 16:59:09 thorpej Exp $ */
+/* $NetBSD: locore.s,v 1.160 2002/08/04 14:57:34 uwe Exp $ */
/*
* Copyright (c) 1996 Paul Kranenburg
@@ -2470,32 +2470,103 @@
#if defined(SUN4M)
_ENTRY(_C_LABEL(sparc_interrupt4m))
#if !defined(MSIIEP) /* "normal" sun4m */
- mov 1, %l4
sethi %hi(CPUINFO_VA+CPUINFO_INTREG), %l6
ld [%l6 + %lo(CPUINFO_VA+CPUINFO_INTREG)], %l6
+ mov 1, %l4
ld [%l6 + ICR_PI_PEND_OFFSET], %l5 ! get pending interrupts
- sll %l4, %l3, %l4 ! test SOFTINT bit
- andcc %l5, %l4, %g0
- bne sparc_interrupt_common
+ sll %l4, %l3, %l4 ! hw intr bits are in the lower halfword
+
+ btst %l4, %l5 ! has pending hw intr at this level?
+ bnz sparc_interrupt_common
nop
- ! a soft interrupt; clear bit in interrupt-pending register
- sll %l4, 16, %l5
- st %l5, [%l6 + ICR_PI_CLR_OFFSET]
- b,a softintr_common
+#ifdef DIAGNOSTIC
+ ! both softint pending and clear bits are in upper halfwords of
+ ! their respective registers so shift the test bit in %l4 up there
+ sll %l4, 16, %l4
+ btst %l4, %l5 ! make sure softint pending bit is set
+ bnz softintr_common
+ st %l4, [%l6 + ICR_PI_CLR_OFFSET]
+ /* FALLTHROUGH to sparc_interrupt4m_bogus */
+#else
+ b softintr_common
+ st %l4, [%l6 + ICR_PI_CLR_OFFSET]
+#endif
+
#else /* MSIIEP */
sethi %hi(MSIIEP_PCIC_VA), %l6
mov 1, %l4
ld [%l6 + PCIC_PROC_IPR_REG], %l5 ! get pending interrupts
- sll %l4, %l3, %l4
- btst %l4, %l5 ! has pending hw intr at this level?
+ sll %l4, %l3, %l4 ! hw intr bits are in the lower halfword
+
+ btst %l4, %l5 ! has pending hw intr at this level?
bnz sparc_interrupt_common
nop
- ! a soft interrupt; clear its bit in softintr clear register
+#ifdef DIAGNOSTIC
+ ! softint pending bits are in the upper halfword, but softint
+ ! clear bits are in the lower halfword so we want the bit in %l4
+ ! kept in the lower half and instead shift pending bits right
+ srl %l5, 16, %l7
+ btst %l4, %l7 ! make sure softint pending bit is set
+ bnz softintr_common
+ sth %l4, [%l6 + PCIC_SOFT_INTR_CLEAR_REG]
+ /* FALLTHROUGH to sparc_interrupt4m_bogus */
+#else
b softintr_common
sth %l4, [%l6 + PCIC_SOFT_INTR_CLEAR_REG]
+#endif
+
#endif /* MSIIEP */
+
+#ifdef DIAGNOSTIC
+ /*
+ * sparc_interrupt4m detected that neither hardware nor software
+ * interrupt pending bit is set for this interrupt. Report this
+ * situation, this is most probably a symptom of a driver bug.
+ */
+sparc_interrupt4m_bogus:
+ INTR_SETUP(-CCFSZ-80)
+ std %g2, [%sp + CCFSZ + 24] ! save registers
+ INCR(_C_LABEL(uvmexp)+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1)
+ mov %g1, %l7
+ rd %y, %l6
+ std %g4, [%sp + CCFSZ + 32]
+ andn %l0, PSR_PIL, %l4 ! %l4 = psr & ~PSR_PIL |
+ sll %l3, 8, %l5 ! intlev << IPLSHIFT
+ std %g6, [%sp + CCFSZ + 40]
+ or %l5, %l4, %l4 ! ;
+ wr %l4, 0, %psr ! the manual claims this
+ wr %l4, PSR_ET, %psr ! song and dance is necessary
+ std %l0, [%sp + CCFSZ + 0] ! set up intrframe/clockframe
+ sll %l3, 2, %l5
+ set _C_LABEL(intrcnt), %l4 ! intrcnt[intlev]++;
+ ld [%l4 + %l5], %o0
+ std %l2, [%sp + CCFSZ + 8] ! set up intrframe/clockframe
+ inc %o0
+ st %o0, [%l4 + %l5]
+
+ st %fp, [%sp + CCFSZ + 16]
+
+ /* Unhandled interrupts while cold cause IPL to be raised to `high' */
+ sethi %hi(_C_LABEL(cold)), %o0
+ ld [%o0 + %lo(_C_LABEL(cold))], %o0
+ tst %o0 ! if (cold) {
+ bnz,a 1f ! splhigh();
+ or %l0, 0xf00, %l0 ! } else
+
+ call _C_LABEL(bogusintr) ! strayintr(&intrframe)
+ add %sp, CCFSZ, %o0
+ /* all done: restore registers and go return */
+1:
+ mov %l7, %g1
+ wr %l6, 0, %y
+ ldd [%sp + CCFSZ + 24], %g2
+ ldd [%sp + CCFSZ + 32], %g4
+ ldd [%sp + CCFSZ + 40], %g6
+ b return_from_trap
+ wr %l0, 0, %psr
+#endif /* DIAGNOSTIC */
#endif /* SUN4M */
_ENTRY(_C_LABEL(sparc_interrupt44c))
Home |
Main Index |
Thread Index |
Old Index