summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/sparc64/include/cpu.h5
-rw-r--r--sys/arch/sparc64/sparc64/genassym.cf1
-rw-r--r--sys/arch/sparc64/sparc64/intr.c4
-rw-r--r--sys/arch/sparc64/sparc64/locore.s63
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