diff options
author | Henric Jungheim <henric@cvs.openbsd.org> | 2003-03-20 23:05:31 +0000 |
---|---|---|
committer | Henric Jungheim <henric@cvs.openbsd.org> | 2003-03-20 23:05:31 +0000 |
commit | 95b81e285a18d146b4b7413f9bdb06cd69031045 (patch) | |
tree | ef94cce28411b4ab447bc64bb477f248f6498306 /sys/arch | |
parent | 225a8263dc0322501697fe099723684ceb482d5a (diff) |
The current code tries to use the same field in the interrupt handler as
both a "next" pointer for a singly-linked list and as an in-use flag.
This obviously does not work all that well. This change adds a separate
ih_busy flag to mark the handler as in-use, leaving ih_pending for use by
the list code.
Testing by *many* (thanks).
ok miod jason
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc64/include/cpu.h | 5 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/genassym.cf | 1 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/intr.c | 4 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/locore.s | 63 |
4 files changed, 49 insertions, 24 deletions
diff --git a/sys/arch/sparc64/include/cpu.h b/sys/arch/sparc64/include/cpu.h index c2afaecc8d6..24dacd82711 100644 --- a/sys/arch/sparc64/include/cpu.h +++ b/sys/arch/sparc64/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.17 2003/02/12 06:32:59 jason Exp $ */ +/* $OpenBSD: cpu.h,v 1.18 2003/03/20 23:05:30 henric Exp $ */ /* $NetBSD: cpu.h,v 1.28 2001/06/14 22:56:58 thorpej Exp $ */ /* @@ -245,8 +245,9 @@ struct intrhand { short ih_number; /* interrupt number */ /* the H/W provides */ char ih_pil; /* interrupt priority */ + volatile char ih_busy; /* handler is on list */ struct intrhand *ih_next; /* global list */ - struct intrhand *ih_pending; /* interrupt queued */ + struct intrhand *ih_pending; /* pending list */ volatile u_int64_t *ih_map; /* Interrupt map reg */ volatile u_int64_t *ih_clr; /* clear interrupt reg */ }; diff --git a/sys/arch/sparc64/sparc64/genassym.cf b/sys/arch/sparc64/sparc64/genassym.cf index 9ec28c28950..a98e01343f5 100644 --- a/sys/arch/sparc64/sparc64/genassym.cf +++ b/sys/arch/sparc64/sparc64/genassym.cf @@ -245,6 +245,7 @@ member ih_fun member ih_arg member ih_number member ih_pil +member ih_busy member IH_PEND ih_pending member ih_next member ih_map diff --git a/sys/arch/sparc64/sparc64/intr.c b/sys/arch/sparc64/sparc64/intr.c index f7d5505d441..72e559413d2 100644 --- a/sys/arch/sparc64/sparc64/intr.c +++ b/sys/arch/sparc64/sparc64/intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.c,v 1.12 2003/02/17 01:29:20 henric Exp $ */ +/* $OpenBSD: intr.c,v 1.13 2003/03/20 23:05:30 henric Exp $ */ /* $NetBSD: intr.c,v 1.39 2001/07/19 23:38:11 eeh Exp $ */ /* @@ -250,6 +250,7 @@ intr_establish(level, ih) * and we do want to preserve order. */ ih->ih_pil = level; /* XXXX caller should have done this before */ + ih->ih_busy = 0; /* XXXX caller should have done this before */ ih->ih_pending = 0; /* XXXX caller should have done this before */ ih->ih_next = NULL; for (p = &intrhand[level]; (q = *p) != NULL; p = &q->ih_next) @@ -347,6 +348,7 @@ softintr_establish(level, fun, arg) ih->ih_fun = (int (*)(void *))fun; /* XXX */ ih->ih_arg = arg; ih->ih_pil = level; + ih->ih_busy = 0; ih->ih_pending = 0; ih->ih_clr = NULL; return (void *)ih; diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s index 3673f4182dd..cee315361d6 100644 --- a/sys/arch/sparc64/sparc64/locore.s +++ b/sys/arch/sparc64/sparc64/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.29 2003/02/28 21:27:42 jason Exp $ */ +/* $OpenBSD: locore.s,v 1.30 2003/03/20 23:05:30 henric Exp $ */ /* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */ /* @@ -2808,8 +2808,9 @@ winfixsave: /* Did we save a user or kernel window ? */ ! srax %g3, 48, %g7 ! User or kernel store? (TAG TARGET) sllx %g3, (64-13), %g7 ! User or kernel store? (TAG ACCESS) + sethi %hi((2*NBPG)-8), %g7 brnz,pt %g7, 1f ! User fault -- save windows to pcb - set (2*NBPG)-8, %g7 + or %g7, %lo((2*NBPG)-8), %g7 and %g4, CWP, %g4 ! %g4 = %cwp of trap wrpr %g4, 0, %cwp ! Kernel fault -- restore %cwp and force and trap to debugger @@ -3970,7 +3971,8 @@ interrupt_vector: setup_sparcintr: #ifdef INTR_INTERLOCK - LDPTR [%g5+IH_PEND], %g6 ! Read pending flag + ldstub [%g5+IH_BUSY], %g6 ! Check if already in use + membar #LoadLoad | #LoadStore brnz,pn %g6, ret_from_intr_vector ! Skip it if it's running #endif ldub [%g5+IH_PIL], %g6 ! Read interrupt mask @@ -4011,7 +4013,7 @@ setup_sparcintr: LOCTOGLOB restore 97: -#endif +#endif /* DEBUG */ dec %g7 brgz,pt %g7, 1b inc PTRSZ, %g1 ! Next slot @@ -4032,9 +4034,10 @@ setup_sparcintr: ta 1 LOCTOGLOB restore -#endif -#endif /* INTRLIST */ 2: +#endif /* DIAGNOSTIC */ +#endif /* INTRLIST */ + #ifdef DEBUG set _C_LABEL(intrdebug), %g7 ld [%g7], %g7 @@ -4055,7 +4058,7 @@ setup_sparcintr: LOCTOGLOB restore 97: -#endif +#endif /* DEBUG */ mov 1, %g7 sll %g7, %g6, %g6 wr %g6, 0, SET_SOFTINT ! Invoke a softint @@ -4269,21 +4272,37 @@ sparc_intr_retry: bne,pn %icc, 1b add %sp, CC64FSZ+STKB, %o2 ! tf = %sp + CC64FSZ + STKB 2: + LDPTR [%l2 + IH_PEND], %l7 ! Load next pending LDPTR [%l2 + IH_FUN], %o4 ! ih->ih_fun LDPTR [%l2 + IH_ARG], %o0 ! ih->ih_arg + LDPTR [%l2 + IH_CLR], %l1 ! ih->ih_clear + + STPTR %g0, [%l2 + IH_PEND] ! Unlink from list + + ! Note that the function handler itself or an interrupt + ! may add handlers to the pending pending. This includes + ! the current entry in %l2 and entries held on our local + ! pending list in %l7. The former is ok because we are + ! done with it now and the latter because they are still + ! marked busy. We may also be able to do this by having + ! the soft interrupts use a variation of the hardware + ! interrupts' ih_clr scheme. Note: The busy flag does + ! not itself prevent the handler from being entered + ! recursively. It only indicates that the handler is + ! about to be invoked and that it should not be added + ! to the pending table. + membar #StoreStore | #LoadStore + stb %g0, [%l2 + IH_BUSY] ! Allow the ih to be reused + + ! At this point, the current ih could already be added + ! back to the pending table. jmpl %o4, %o7 ! handled = (*ih->ih_fun)(...) movrz %o0, %o2, %o0 ! arg = (arg == 0) ? arg : tf - LDPTR [%l2 + IH_PEND], %l7 ! Clear pending flag - LDPTR [%l2 + IH_CLR], %l1 - membar #LoadStore - STPTR %g0, [%l2 + IH_PEND] ! Clear pending flag - membar #Sync brz,pn %l1, 0f - add %l5, %o0, %l5 + add %l5, %o0, %l5 ! Add handler return value stx %g0, [%l1] ! Clear intr source - membar #Sync ! Should not be needed 0: brnz,pn %l7, 2b ! 'Nother? mov %l7, %l2 @@ -11492,15 +11511,17 @@ ENTRY(ienab_bic) */ ENTRY(send_softint) rdpr %pil, %g1 ! s = splx(level) - cmp %g1, %o1 - bge,pt %icc, 1f - nop - wrpr %o1, 0, %pil + !cmp %g1, %o1 + !bge,pt %icc, 1f + ! nop + wrpr %g0, PIL_HIGH, %pil 1: brz,pn %o2, 1f - set intrpending, %o3 - LDPTR [%o2 + IH_PEND], %o5 - mov 8, %o4 ! Number of slots to search + mov 8, %o4 ! Number of slots to search + set intrpending, %o3 + + ldstub [%o2 + IH_BUSY], %o5 + membar #LoadLoad | #LoadStore #ifdef INTR_INTERLOCK brnz %o5, 1f #endif |