diff options
author | Per Fogelstrom <pefo@cvs.openbsd.org> | 2004-09-27 19:20:50 +0000 |
---|---|---|
committer | Per Fogelstrom <pefo@cvs.openbsd.org> | 2004-09-27 19:20:50 +0000 |
commit | ebb4c30d0ba37fca21a45b416ade8714393b0ac0 (patch) | |
tree | 659762f6cdfca5b38da2a5d042378b63c78bae41 | |
parent | 23ce51ea125bb5370965cf6b3d4a6c95f8954d4b (diff) |
Rewrite parts of the interrupt system to achive:
o Remove do_pending code and take a real int instead. The performance
impact seems to be very low and it simplifies the code considerably.
o Allow interrupt nesting at first level. Run softints with HW ints
enabled.
-rw-r--r-- | sys/arch/mips64/include/cpu.h | 6 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/exception.S | 79 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/interrupt.c | 111 | ||||
-rw-r--r-- | sys/arch/sgi/include/intr.h | 37 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/macebus.c | 74 |
5 files changed, 188 insertions, 119 deletions
diff --git a/sys/arch/mips64/include/cpu.h b/sys/arch/mips64/include/cpu.h index 57ac780dfc3..15b1352e2e3 100644 --- a/sys/arch/mips64/include/cpu.h +++ b/sys/arch/mips64/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.7 2004/09/21 05:51:13 miod Exp $ */ +/* $OpenBSD: cpu.h,v 1.8 2004/09/27 19:20:49 pefo Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -328,12 +328,12 @@ * Arguments to hardclock and gatherstats encapsulate the previous * machine state in an opaque clockframe. */ +extern int int_nest_cntr; #define clockframe trap_frame /* Use normal trap frame */ #define CLKF_USERMODE(framep) ((framep)->sr & SR_KSU_USER) -#define CLKF_BASEPRI(framep) ((framep)->cpl == 0) #define CLKF_PC(framep) ((framep)->pc) -#define CLKF_INTR(framep) (0) +#define CLKF_INTR(framep) (int_nest_cntr > 0) /* * Preempt the current process if in interrupt from user mode, diff --git a/sys/arch/mips64/mips64/exception.S b/sys/arch/mips64/mips64/exception.S index 1a06df4938b..65e582604b9 100644 --- a/sys/arch/mips64/mips64/exception.S +++ b/sys/arch/mips64/mips64/exception.S @@ -1,4 +1,4 @@ -/* $OpenBSD: exception.S,v 1.6 2004/09/19 20:24:38 pefo Exp $ */ +/* $OpenBSD: exception.S,v 1.7 2004/09/27 19:20:49 pefo Exp $ */ /* * Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -48,15 +48,14 @@ #include "assym.h" -/* - * DDB stack backtrace uses 'jr ra' to find functions starts. - * Put this after functions which does not end with 'jr ra'. - */ -#define DDB_BARRIER \ - jr ra; nop - .set mips3 + .data + .globl int_nest_cntr +int_nest_cntr: + .word -1 + .text + k_exception_table: PTR_VAL k_intr PTR_VAL k_general @@ -127,8 +126,6 @@ u_exception_table: .set noreorder # Noreorder is default style! -#define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; - /*---------------------------------------------------------------- exception * General exception handler dispatcher. This code is copied * to the vector area and must thus be PIC and less than 128 @@ -151,7 +148,7 @@ exception: PTR_L k1, tlbtrcptr PTR_ADDU k1, 4*REGSZ LI k0, 0x100 - nor k0, zero, k0 + not k0, k0 and k1, k0 LA k0, tlbtrcptr PTR_S k1, 0(k0) @@ -184,7 +181,6 @@ k_exception: .globl e_exception e_exception: - DDB_BARRIER /*---------------------------------------------------------------- k_intr * Handle an interrupt in kernel mode. This is easy since we @@ -206,6 +202,10 @@ NNON_LEAF(k_intr, FRAMESZ(KERN_EXC_FRAME_SIZE), ra) LA gp, _gp and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK) mtc0 t0, COP_0_STATUS_REG + LA t1, int_nest_cntr + lw t2, (t1) + addiu t2, 1 + sw t2, (t1) ITLBNOPFIX PTR_S a0, 0(sp) jal interrupt @@ -216,6 +216,11 @@ NNON_LEAF(k_intr, FRAMESZ(KERN_EXC_FRAME_SIZE), ra) and t0, t0, t1 mtc0 t0, COP_0_STATUS_REG + LA t1, int_nest_cntr + lw t2, (t1) + addiu t2, -1 + sw t2, (t1) + PTR_L a0, CF_RA_OFFS + KERN_REG_SIZE(sp) .set noat #if 0 @@ -226,7 +231,6 @@ NNON_LEAF(k_intr, FRAMESZ(KERN_EXC_FRAME_SIZE), ra) PTR_ADDU sp, sp, FRAMESZ(KERN_EXC_FRAME_SIZE) sync eret - DDB_BARRIER .set at END(k_intr) @@ -250,6 +254,10 @@ NNON_LEAF(u_intr, FRAMESZ(CF_SZ), ra) .set at and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK) mtc0 t0, COP_0_STATUS_REG + LA t1, int_nest_cntr + lw t2, (t1) + addiu t2, 1 + sw t2, (t1) ITLBNOPFIX PTR_S a0, 0(sp) jal interrupt @@ -316,11 +324,14 @@ NNON_LEAF(u_intr, FRAMESZ(CF_SZ), ra) li t1, ~SR_INT_ENAB and t0, t0, t1 mtc0 t0, COP_0_STATUS_REG - ITLBNOPFIX + + LA t1, int_nest_cntr + lw t2, (t1) + addiu t2, -1 + sw t2, (t1) ori t0, SR_EXL # restoring to user mode. mtc0 t0, COP_0_STATUS_REG # must set exeption level bit. - ITLBNOPFIX PTR_L k0, curprocpaddr RESTORE_REG(a3, CPL, k0, 0) @@ -337,24 +348,39 @@ NNON_LEAF(u_intr, FRAMESZ(CF_SZ), ra) LI k1, 0 sync eret - DDB_BARRIER .set at END(u_intr) -/*---------------------------------------------------------------- set_sint - * Atomic ipending update +/*---------------------------------------------------------------- set_ipending + * Atomic ipending set + */ +LEAF(set_ipending, 0) + LA a1, ipending +1: + ll v0, 0(a1) + or v1, v0, a0 + sc v1, 0(a1) + beqz v1, 1b + nop + j ra + nop +END(set_ipending) + +/*---------------------------------------------------------------- set_ipending + * Atomic ipending clear */ -LEAF(set_sint, 0) - LA v1, ipending +LEAF(clr_ipending, 0) + LA a1, ipending + not a0, a0 1: - ll v0, 0(v1) - or v0, a0 - sc v0, 0(v1) - beqz v0, 1b + ll v0, 0(a1) + and v1, v0, a0 + sc v1, 0(a1) + beqz v1, 1b nop j ra nop -END(set_sint) +END(clr_ipending) /*---------------------------------------------------------------- k_general * Handle a kernel general trap. This is very much like @@ -398,7 +424,6 @@ NNON_LEAF(k_general, FRAMESZ(KERN_EXC_FRAME_SIZE), ra) PTR_ADDU sp, sp, FRAMESZ(KERN_EXC_FRAME_SIZE) sync eret - DDB_BARRIER .set at END(k_general) @@ -494,7 +519,6 @@ NNON_LEAF(u_general, FRAMESZ(CF_SZ), ra) LI k1, 0 sync eret - DDB_BARRIER .set at END(u_general) @@ -606,7 +630,6 @@ NNON_LEAF(u_syscall, FRAMESZ(CF_SZ), ra) REG_L ra, UADDR+U_PCB_REGS+(RA * REGSZ) sync eret - DDB_BARRIER .set at END(u_syscall) #endif diff --git a/sys/arch/mips64/mips64/interrupt.c b/sys/arch/mips64/mips64/interrupt.c index fc1eacf6c3a..df77cd1374f 100644 --- a/sys/arch/mips64/mips64/interrupt.c +++ b/sys/arch/mips64/mips64/interrupt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: interrupt.c,v 1.7 2004/09/24 14:22:49 deraadt Exp $ */ +/* $OpenBSD: interrupt.c,v 1.8 2004/09/27 19:20:49 pefo Exp $ */ /* * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -56,6 +56,9 @@ #include <ddb/db_sym.h> #endif +static struct evcount soft_count; +static int soft_irq = 0; + volatile intrmask_t cpl; volatile intrmask_t ipending, astpending; @@ -69,7 +72,9 @@ struct { intrmask_t (*int_hand)(intrmask_t, struct trap_frame *); } cpu_int_tab[NLOWINT]; -void_f *pending_hand; +void dummy_do_pending_int(int); + +int_f *pending_hand = &dummy_do_pending_int; int netisr; @@ -136,7 +141,7 @@ interrupt(struct trap_frame *trapframe) u_int32_t pending; u_int32_t cause; int i; - intrmask_t pcpl; + intrmask_t xcpl; /* * Paranoic? Perhaps. But if we got here with the enable @@ -149,22 +154,21 @@ interrupt(struct trap_frame *trapframe) return; } - uvmexp.intrs++; - pcpl = splhigh() ; /* Turn off all and get current SW mask */ - #ifdef DEBUG_INTERRUPT trapdebug_enter(trapframe, 0); #endif - pending = trapframe->cause & CR_IPEND; -#ifdef IMASK_EXTERNAL - pending &= idle_mask << 8; -#else - ipending |= (pending >> 8) & pcpl; - pending &= ~(pcpl << 8); -#endif + uvmexp.intrs++; + + /* Mask out interrupts from cause that are unmasked */ + pending = trapframe->cause & CR_IPEND & trapframe->sr; cause = pending; + if (cause & SOFT_INT_MASK_0) { + clearsoftintr0(); + soft_count.ec_count++; + } + if (cause & CR_INT_PERF) { rm7k_perfintr(trapframe); cause &= ~CR_INT_PERF; @@ -187,19 +191,31 @@ printf("Unhandled interrupt %x:%x\n", cause, pending); * Reenable all non served hardware levels. */ #if 0 - splx((trapframe->sr & ~cause & SR_INT_MASK) | SR_INT_ENAB); + /* XXX the following should, when req., change the IC reg as well */ + setsr((trapframe->sr & ~pending) | SR_INT_ENAB); #endif - if (pending & SOFT_INT_MASK_0) { - clearsoftintr0(); - uvmexp.softs++; + xcpl = splsoftnet(); + if ((ipending & SINT_CLOCKMASK) & ~xcpl) { + clr_ipending(SINT_CLOCKMASK); + softclock(); + } + if ((ipending & SINT_NETMASK) & ~xcpl) { + extern int netisr; + int isr = netisr; + netisr = 0; + clr_ipending(SINT_NETMASK); +#define DONETISR(b,f) if (isr & (1 << (b))) f(); +#include <net/netisr_dispatch.h> } -#ifndef IMASK_EXTERNAL - trapframe->sr &= ~((pcpl << 8) & SR_INT_MASK); - trapframe->ic &= ~(pcpl & IC_INT_MASK); +#ifdef NOTYET + if ((ipending & SINT_TTYMASK) & ~xcpl) { + clr_ipending(SINT_TTYMASK); + compoll(NULL); + } #endif - splx(pcpl); /* Process pendings. */ + cpl = xcpl; } @@ -213,6 +229,8 @@ void set_intr(int pri, intrmask_t mask, intrmask_t (*int_hand)(intrmask_t, struct trap_frame *)) { + if (!idle_mask & (SOFT_INT_MASK >> 8)) + evcount_attach(&soft_count, "soft", (void *)&soft_irq, &evcount_intr); if (pri < 0 || pri >= NLOWINT) { panic("set_intr: to high priority"); } @@ -458,31 +476,29 @@ generic_intr_makemasks() } void -generic_do_pending_int() +generic_do_pending_int(int newcpl) { struct intrhand *ih; int vector; - intrmask_t pcpl; intrmask_t hwpend; struct trap_frame cf; -static volatile int processing; + static volatile int processing; - /* Don't recurse... */ - if (processing) + /* Don't recurse... but change the mask. */ + if (processing) { + cpl = newcpl; return; + } processing = 1; -/* XXX interrupt vulnerable when changing ipending */ - pcpl = splhigh(); /* Turn off all */ - /* XXX Fake a trapframe for clock pendings... */ cf.pc = (int)&generic_do_pending_int; cf.sr = 0; - cf.cpl = pcpl; + cf.cpl = cpl; - hwpend = ipending & ~pcpl; /* Do now unmasked pendings */ + hwpend = ipending & ~newcpl; /* Do pendings being unmasked */ hwpend &= ~(SINT_ALLMASK); - ipending &= ~hwpend; + clr_ipending(hwpend); intem |= hwpend; while (hwpend) { vector = ffs(hwpend) - 1; @@ -496,30 +512,36 @@ static volatile int processing; ih = ih->ih_next; } } - if ((ipending & SINT_CLOCKMASK) & ~pcpl) { - ipending &= ~SINT_CLOCKMASK; + if ((ipending & SINT_CLOCKMASK) & ~newcpl) { + clr_ipending(SINT_CLOCKMASK); softclock(); } - if ((ipending & SINT_NETMASK) & ~pcpl) { + if ((ipending & SINT_NETMASK) & ~newcpl) { int isr = netisr; netisr = 0; - ipending &= ~SINT_NETMASK; + clr_ipending(SINT_NETMASK); #define DONETISR(b,f) if (isr & (1 << (b))) f(); #include <net/netisr_dispatch.h> } #ifdef NOTYET - if ((ipending & SINT_TTYMASK) & ~pcpl) { - ipending &= ~SINT_TTYMASK; + if ((ipending & SINT_TTYMASK) & ~newcpl) { + clr_ipending(SINT_TTYMASK); compoll(NULL); } #endif - cpl = pcpl; /* Don't use splx... we are here already! */ - updateimask(pcpl); /* Update CPU mask ins SR register */ + cpl = newcpl; + updateimask(newcpl); /* Update CPU mask ins SR register */ processing = 0; } +void +dummy_do_pending_int(int newcpl) +{ + /* Dummy handler */ +} + /* * splinit() is special in that sense that it require us to update * the interrupt mask in the CPU since it may be the first time we arm @@ -553,6 +575,11 @@ generic_iointr(intrmask_t pending, struct trap_frame *cf) catched = 0; + set_ipending((pending >> 8) & cpl); + pending &= ~(cpl << 8); + cf->sr &= ~((ipending << 8) & SR_INT_MASK); + cf->ic &= ~(ipending & IC_INT_MASK); + for (v = 2, vm = 0x400; pending != 0 && v < 16 ; v++, vm <<= 1) { if (pending & vm) { ih = intrhand[v]; @@ -582,8 +609,4 @@ splraise(int newcpl) __asm__ (" sync\n .set reorder\n"); return (oldcpl); } -volatile intrmask_t cpl; -volatile intrmask_t ipending, astpending; - -intrmask_t imask[NIPLS]; #endif diff --git a/sys/arch/sgi/include/intr.h b/sys/arch/sgi/include/intr.h index 7e9a3a847f1..ff245ca9ad1 100644 --- a/sys/arch/sgi/include/intr.h +++ b/sys/arch/sgi/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.8 2004/09/24 14:22:48 deraadt Exp $ */ +/* $OpenBSD: intr.h,v 1.9 2004/09/27 19:20:49 pefo Exp $ */ /* * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -107,9 +107,9 @@ #define spllowersoftclock() spllower(SINT_CLOCKMASK) -#define setsoftclock() set_sint(SINT_CLOCKMASK); -#define setsoftnet() set_sint(SINT_NETMASK); -#define setsofttty() set_sint(SINT_TTYMASK); +#define setsoftclock() set_ipending(SINT_CLOCKMASK); +#define setsoftnet() set_ipending(SINT_NETMASK); +#define setsofttty() set_ipending(SINT_TTYMASK); void splinit(void); @@ -149,15 +149,15 @@ extern intrmask_t imask[NIPLS]; */ /* Inlines */ -static __inline void register_pending_int_handler(void (*)(void)); +static __inline void register_pending_int_handler(void (*)(int)); static __inline void splx(int newcpl); static __inline int spllower(int newcpl); -typedef void (void_f) (void); -extern void_f *pending_hand; +typedef void (int_f) (int); +extern int_f *pending_hand; static __inline void -register_pending_int_handler(void(*pending)(void)) +register_pending_int_handler(void(*pending)(int)) { pending_hand = pending; } @@ -184,10 +184,10 @@ int splraise(int newcpl); static __inline void splx(int newcpl) { - cpl = newcpl; - if ((ipending & ~newcpl) && (pending_hand != NULL)) { - (*pending_hand)(); - } + if (ipending & ~newcpl) + (*pending_hand)(newcpl); + else + cpl = newcpl; } static __inline int @@ -196,17 +196,18 @@ spllower(int newcpl) int oldcpl; oldcpl = cpl; - cpl = newcpl; - if ((ipending & ~newcpl) && (pending_hand != NULL)) { - (*pending_hand)(); - } + if (ipending & ~newcpl) + (*pending_hand)(newcpl); + else + cpl = newcpl; return (oldcpl); } /* * Atomically update ipending. */ -void set_sint(int pending); +void set_ipending(int); +void clr_ipending(int); /* * Interrupt control struct used by interrupt dispatchers @@ -255,7 +256,7 @@ void *generic_intr_establish(void *, u_long, int, int, int (*) __P((void *)), void *, char *); void generic_intr_disestablish(void *, void *); void generic_intr_makemasks(void); -void generic_do_pending_int(void); +void generic_do_pending_int(int); intrmask_t generic_iointr(intrmask_t, struct trap_frame *); #endif /* _LOCORE */ diff --git a/sys/arch/sgi/localbus/macebus.c b/sys/arch/sgi/localbus/macebus.c index b4686226f0e..2510a7eb819 100644 --- a/sys/arch/sgi/localbus/macebus.c +++ b/sys/arch/sgi/localbus/macebus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: macebus.c,v 1.9 2004/09/24 14:22:49 deraadt Exp $ */ +/* $OpenBSD: macebus.c,v 1.10 2004/09/27 19:20:49 pefo Exp $ */ /* * Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se) @@ -64,7 +64,7 @@ void *macebus_intr_establish(void *, u_long, int, int, int (*)(void *), void *, char *); void macebus_intr_disestablish(void *, void *); void macebus_intr_makemasks(void); -void macebus_do_pending_int(void); +void macebus_do_pending_int(int); intrmask_t macebus_iointr(intrmask_t, struct trap_frame *); intrmask_t macebus_aux(intrmask_t, struct trap_frame *); @@ -73,8 +73,6 @@ long crime_ext_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof (long)]; int maceticks; /* Time tracker for special events */ -u_int64_t crimestat; - struct cfattach macebus_ca = { sizeof(struct device), macebusmatch, macebusattach }; @@ -597,31 +595,40 @@ macebus_intr_makemasks(void) } void -macebus_do_pending_int(void) +macebus_do_pending_int(int newcpl) { +#ifdef _USE_SILLY_OVERWORKED_HW_INT_PENDING_HANDLER_ struct intrhand *ih; int vector; - intrmask_t pcpl; intrmask_t hwpend; struct trap_frame cf; static volatile int processing; - /* Don't recurse... */ - if (processing) + /* Don't recurse... but change the mask */ + if (processing) { + cpl = newcpl; return; + } processing = 1; - /* XXX interrupt vulnerable when changing ipending */ - pcpl = splhigh(); /* Turn off all */ /* XXX Fake a trapframe for clock pendings... */ cf.pc = (int)&macebus_do_pending_int; cf.sr = 0; - cf.cpl = pcpl; + cf.cpl = cpl; + + /* Hard mask current cpl so we don't get any new pendings */ + hw_setintrmask(cpl); + + /* Get what interrupt we should process */ + hwpend = ipending & ~newcpl; + hwpend &= ~SINT_ALLMASK; + clr_ipending(hwpend); + + /* Enable all non pending non masked hardware interrupts */ + cpl = (cpl & SINT_ALLMASK) | (newcpl & ~SINT_ALLMASK) | hwpend; + hw_setintrmask(cpl); - hwpend = ipending & ~pcpl; /* Do now unmasked pendings */ - hwpend &= ~(SINT_ALLMASK); - ipending &= ~hwpend; while (hwpend) { vector = ffs(hwpend) - 1; hwpend &= ~(1L << vector); @@ -634,30 +641,44 @@ macebus_do_pending_int(void) ih = ih->ih_next; } } - if ((ipending & SINT_CLOCKMASK) & ~pcpl) { - ipending &= ~SINT_CLOCKMASK; + + /* Enable all processed pending hardware interrupts */ + cpl &= ~hwpend; + hw_setintrmask(cpl); + + if ((ipending & SINT_CLOCKMASK) & ~newcpl) { + clr_ipending(SINT_CLOCKMASK); softclock(); } - if ((ipending & SINT_NETMASK) & ~pcpl) { + if ((ipending & SINT_NETMASK) & ~newcpl) { extern int netisr; int isr = netisr; netisr = 0; - ipending &= ~SINT_NETMASK; + clr_ipending(SINT_NETMASK); #define DONETISR(b,f) if (isr & (1 << (b))) f(); #include <net/netisr_dispatch.h> } #ifdef NOTYET - if ((ipending & SINT_TTYMASK) & ~pcpl) { - ipending &= ~SINT_TTYMASK; + if ((ipending & SINT_TTYMASK) & ~newcpl) { + clr_ipending(SINT_TTYMASK); compoll(NULL); } #endif - cpl = pcpl; /* Don't use splx... we are here already! */ - hw_setintrmask(pcpl); + /* Update masks to new cpl. Order highly important! */ + cpl = newcpl; + hw_setintrmask(newcpl); processing = 0; +#else + /* Update masks to new cpl. Order highly important! */ + cpl = newcpl; + hw_setintrmask(newcpl); + /* If we still have softints pending trigg processing */ + if (ipending & SINT_ALLMASK & ~cpl) + setsoftintr0(); +#endif } /* @@ -673,22 +694,23 @@ macebus_iointr(intrmask_t hwpend, struct trap_frame *cf) u_int64_t intstat, isastat, mask; intstat = bus_space_read_8(&crimebus_tag, crime_h, CRIME_INT_STAT); -crimestat=intstat; - intstat &= 0x0000ffff; + intstat &= 0xffff; + isastat = bus_space_read_8(&macebus_tag, mace_h, MACE_ISA_INT_STAT); catched = 0; /* Mask off masked interrupts and save them as pending */ if (intstat & cf->cpl) { - ipending |= intstat & cf->cpl; + set_ipending(intstat & cf->cpl); mask = bus_space_read_8(&crimebus_tag, crime_h, CRIME_INT_MASK); mask &= ~ipending; bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_MASK, mask); catched++; } - /* Scan the first 16 for now */ + /* Scan all unmasked. Scan the first 16 for now */ pending = intstat & ~cf->cpl; + clr_ipending(pending); for (v = 0, vm = 1; pending != 0 && v < 16 ; v++, vm <<= 1) { if (pending & vm) { |