generic soft interrupt patch
Izumi Tsutsui <[email protected]> Mon, 28 Apr 2003 15:35:17 +0900
| Newsgroups | gmane.os.netbsd.ports.arc |
|---|---|
| Message-ID | <[email protected]> |
I've just made a patch to support generic soft interrupt for arc. It's based on algor port (as newsmips patch) and seems to work on my NEC-JC94, but I'm not sure if isabus.c fix is correct or not. (Has anyone tried any ISA device that uses interrupts on arc?) Note it seems that getty for /dev/tty00 does not work if console isn't com, but I think old kernels also has the same problem. cpu_intr() in arc_trap.c should also be rewritten as noted in arch/arc/TODO file, but it's a future work. (BTW, we should rename arc_trap.c to interrupt.c like other mips ports?) --- Izumi Tsutsui [email protected] Index: arc/arc_trap.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/arc_trap.c,v retrieving revision 1.24 diff -u -r1.24 arc_trap.c --- arc/arc_trap.c 2003/04/27 17:13:01 1.24 +++ arc/arc_trap.c 2003/04/28 06:03:51 @@ -2,6 +2,42 @@ /* $OpenBSD: trap.c,v 1.22 1999/05/24 23:08:59 jason Exp $ */ /* + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -46,9 +82,12 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/malloc.h> #include <uvm/uvm_extern.h> +#include <net/netisr.h> /* Legacy softnet support */ + #include <mips/locore.h> #include <machine/autoconf.h> @@ -60,6 +99,20 @@ int arc_hardware_intr __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t)); +/* XXX For legacy software interrupts. */ +struct arc_soft_intrhand *softnet_intrhand; + +const u_int32_t *ipl_sr_bits; + +const u_int32_t ipl_si_to_sr[_IPL_NSOFT] = { + MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ + MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ +}; + +struct arc_soft_intr arc_soft_intrs[_IPL_NSOFT]; + #define MIPS_INT_LEVELS 8 struct { @@ -133,46 +186,131 @@ u_int32_t pc; u_int32_t ipending; /* pending interrupts & enable mask */ { -#if defined(MIPS3) && defined(MIPS_INT_MASK_CLOCK) - if ((ipending & MIPS_INT_MASK_CLOCK) && CPUISMIPS3) { + struct arc_soft_intr *asi; + struct arc_soft_intrhand *sih; + int i, s; + + if (ipending & MIPS_INT_MASK_CLOCK) { /* * Writing a value to the Compare register, * as a side effect, clears the timer interrupt request. */ mips3_cp0_compare_write(mips3_cp0_count_read()); } -#endif uvmexp.intrs++; /* real device interrupt */ if (ipending & INT_MASK_REAL_DEV) { _splset(arc_hardware_intr(status, cause, pc, ipending)); } + + /* software interrupts */ + ipending &= (MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0); + if (ipending == 0) + return; + + _clrsoftintr(ipending); -#if defined(MIPS1) && defined(INT_MASK_FPU) - if ((ipending & INT_MASK_FPU) && CPUISMIPS1) { - intrcnt[FPU_INTR]++; - if (!USERMODE(status)) - panic("kernel used FPU: PC %x, CR %x, SR %x", - pc, cause, status); -#if !defined(SOFTFLOAT) - MachFPInterrupt(status, cause, pc, curlwp->l_md.md_regs); -#endif - } -#endif - - /* 'softnet' interrupt */ - if (ipending & MIPS_SOFT_INT_MASK_1) { - clearsoftnet(); - uvmexp.softs++; - netintr(); - } - - /* 'softclock' interrupt */ - if (ipending & MIPS_SOFT_INT_MASK_0) { - clearsoftclock(); - uvmexp.softs++; - intrcnt[SOFTCLOCK_INTR]++; - softclock(NULL); + for (i = _IPL_NSOFT - 1; i >= 0; i--) { + if ((ipending & ipl_si_to_sr[i]) == 0) + continue; + + asi = &arc_soft_intrs[i]; + + if (TAILQ_FIRST(&asi->softintr_q) != NULL) + asi->softintr_evcnt.ev_count++; + + for (;;) { + s = splhigh(); + + sih = TAILQ_FIRST(&asi->softintr_q); + if (sih != NULL) { + TAILQ_REMOVE(&asi->softintr_q, sih, sih_q); + sih->sih_pending = 0; + } + + splx(s); + + if (sih == NULL) + break; + + uvmexp.softs++; + (*sih->sih_func)(sih->sih_arg); + } } +} + +/* + * softintr_init: + * + * Initialize the software interrupt system. + */ +void +softintr_init(void) +{ + static const char *softintr_names[] = IPL_SOFTNAMES; + struct arc_soft_intr *asi; + int i; + + for (i = 0; i < _IPL_NSOFT; i++) { + asi = &arc_soft_intrs[i]; + TAILQ_INIT(&asi->softintr_q); + asi->softintr_ipl = IPL_SOFT + i; + evcnt_attach_dynamic(&asi->softintr_evcnt, EVCNT_TYPE_INTR, + NULL, "soft", softintr_names[i]); + } + + /* XXX Establish legacy soft interrupt handlers. */ + softnet_intrhand = softintr_establish(IPL_SOFTNET, + (void (*)(void *))netintr, NULL); + + KASSERT(softnet_intrhand != NULL); +} + +/* + * softintr_establish: [interface] + * + * Register a software interrupt handler. + */ +void * +softintr_establish(int ipl, void (*func)(void *), void *arg) +{ + struct arc_soft_intr *asi; + struct arc_soft_intrhand *sih; + + if (__predict_false(ipl >= (IPL_SOFT + _IPL_NSOFT) || ipl < IPL_SOFT)) + panic("softintr_establish"); + + asi = &arc_soft_intrs[ipl - IPL_SOFT]; + + sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT); + if (__predict_true(sih != NULL)) { + sih->sih_intrhead = asi; + sih->sih_func = func; + sih->sih_arg = arg; + sih->sih_pending = 0; + } + return sih; +} + +/* + * softintr_disestablish: [interface] + * + * Unregister a software interrupt handler. + */ +void +softintr_disestablish(void *arg) +{ + struct arc_soft_intrhand *sih = arg; + struct arc_soft_intr *asi = sih->sih_intrhead; + int s; + + s = splhigh(); + if (sih->sih_pending) { + TAILQ_REMOVE(&asi->softintr_q, sih, sih_q); + sih->sih_pending = 0; + } + splx(s); + + free(sih, M_DEVBUF); } Index: arc/autoconf.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/autoconf.c,v retrieving revision 1.18 diff -u -r1.18 autoconf.c --- arc/autoconf.c 2002/09/27 02:24:09 1.18 +++ arc/autoconf.c 2003/04/28 06:03:51 @@ -91,6 +91,9 @@ void cpu_configure() { + + softintr_init(); + (void)splhigh(); /* To be really sure.. */ if (config_rootfound("mainbus", "mainbus") == NULL) panic("no mainbus found"); Index: arc/c_magnum.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/c_magnum.c,v retrieving revision 1.3 diff -u -r1.3 c_magnum.c --- arc/c_magnum.c 2003/04/27 11:33:36 1.3 +++ arc/c_magnum.c 2003/04/28 06:03:52 @@ -80,6 +80,54 @@ timer_magnum_init, }; +/* + * This is a mask of bits to clear in the SR when we go to a + * given interrupt priority level. + */ +static const u_int32_t magnum_ipl_sr_bits[_IPL_N] = { + 0, /* IPL_NONE */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3, /* IPL_BIO */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3, /* IPL_NET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3, /* IPL_{TTY,SERIAL} */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* IPL_{CLOCK,HIGH} */ +}; + int timer_magnum_intr(mask, cf) u_int mask; @@ -189,12 +237,7 @@ /* * Initialize interrupt priority */ - splvec.splnet = MIPS_INT_MASK_SPL3; - splvec.splbio = MIPS_INT_MASK_SPL3; - splvec.splvm = MIPS_INT_MASK_SPL3; - splvec.spltty = MIPS_INT_MASK_SPL3; - splvec.splclock = MIPS_INT_MASK_SPL5; - splvec.splstatclock = MIPS_INT_MASK_SPL5; + ipl_sr_bits = magnum_ipl_sr_bits; /* * Disable all interrupts. New masks will be set up Index: arc/c_nec_eisa.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/c_nec_eisa.c,v retrieving revision 1.5 diff -u -r1.5 c_nec_eisa.c --- arc/c_nec_eisa.c 2003/01/31 22:07:52 1.5 +++ arc/c_nec_eisa.c 2003/04/28 06:03:52 @@ -73,6 +73,51 @@ isabr_nec_eisa_intr_status, }; +/* + * This is a mask of bits to clear in the SR when we go to a + * given interrupt priority level. + */ +static const u_int32_t nec_eisa_ipl_sr_bits[_IPL_N] = { + 0, /* IPL_NONE */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2, /* IPL_BIO */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2, /* IPL_NET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2, /* IPL_{TTY,SERIAL} */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* IPL_{CLOCK,HIGH} */ +}; + int isabr_nec_eisa_intr_status() { @@ -131,12 +176,7 @@ /* * Initialize interrupt priority */ - splvec.splnet = MIPS_INT_MASK_SPL2; - splvec.splbio = MIPS_INT_MASK_SPL2; - splvec.splvm = MIPS_INT_MASK_SPL2; - splvec.spltty = MIPS_INT_MASK_SPL2; - splvec.splclock = MIPS_INT_MASK_SPL5; - splvec.splstatclock = MIPS_INT_MASK_SPL5; + ipl_sr_bits = nec_eisa_ipl_sr_bits; /* * Disable all interrupts. New masks will be set up Index: arc/c_nec_pci.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/c_nec_pci.c,v retrieving revision 1.4 diff -u -r1.4 c_nec_pci.c --- arc/c_nec_pci.c 2003/01/19 10:06:12 1.4 +++ arc/c_nec_pci.c 2003/04/28 06:03:53 @@ -98,6 +98,51 @@ { mc_nec_pci_read, mc_nec_pci_write } }; +/* + * This is a mask of bits to clear in the SR when we go to a + * given interrupt priority level. + */ +static const u_int32_t nec_pci_ipl_sr_bits[_IPL_N] = { + 0, /* IPL_NONE */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2, /* IPL_BIO */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2, /* IPL_NET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2, /* IPL_{TTY,SERIAL} */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* IPL_{CLOCK,HIGH} */ +}; + u_int mc_nec_pci_read(sc, reg) struct mcclock_softc *sc; @@ -194,12 +239,7 @@ /* * Initialize interrupt priority */ - splvec.splnet = MIPS_INT_MASK_SPL2; - splvec.splbio = MIPS_INT_MASK_SPL2; - splvec.splvm = MIPS_INT_MASK_SPL2; - splvec.spltty = MIPS_INT_MASK_SPL2; - splvec.splclock = MIPS_INT_MASK_SPL5; - splvec.splstatclock = MIPS_INT_MASK_SPL5; + ipl_sr_bits = nec_pci_ipl_sr_bits; /* * Disable all interrupts. New masks will be set up Index: arc/locore_machdep.S =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/locore_machdep.S,v retrieving revision 1.8 diff -u -r1.8 locore_machdep.S --- arc/locore_machdep.S 2000/06/09 05:07:32 1.8 +++ arc/locore_machdep.S 2003/04/28 06:03:53 @@ -392,19 +392,14 @@ /* - * Interrupt counters for vmstat. + * Symbols that vmstat -i wants, even though they're not used. */ .data .globl _C_LABEL(intrcnt) .globl _C_LABEL(eintrcnt) .globl _C_LABEL(intrnames) .globl _C_LABEL(eintrnames) -_C_LABEL(intrnames): - .asciiz "softclock" - .asciiz "softnet" - .asciiz "fpu" -_C_LABEL(eintrnames): - .align 3 _C_LABEL(intrcnt): - .word 0,0,0 _C_LABEL(eintrcnt): +_C_LABEL(intrnames): +_C_LABEL(eintrnames): Index: arc/machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/machdep.c,v retrieving revision 1.77 diff -u -r1.77 machdep.c --- arc/machdep.c 2003/04/27 17:05:56 1.77 +++ arc/machdep.c 2003/04/28 06:03:54 @@ -180,15 +180,6 @@ */ int safepri = MIPS3_PSL_LOWIPL; -struct splvec splvec = { /* XXX will go XXX */ - MIPS_INT_MASK_SPLHIGH, /* splbio */ - MIPS_INT_MASK_SPLHIGH, /* splnet */ - MIPS_INT_MASK_SPLHIGH, /* spltty */ - MIPS_INT_MASK_SPLHIGH, /* splvm */ - MIPS_INT_MASK_SPLHIGH, /* splclock */ - MIPS_INT_MASK_SPLHIGH, /* splstatclock */ -}; - extern char kernel_text[], edata[], end[]; extern struct user *proc0paddr; Index: arc/p_dti_arcstation.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/p_dti_arcstation.c,v retrieving revision 1.1 diff -u -r1.1 p_dti_arcstation.c --- arc/p_dti_arcstation.c 2001/06/13 15:27:17 1.1 +++ arc/p_dti_arcstation.c 2003/04/28 06:03:54 @@ -95,6 +95,61 @@ arc_set_intr, }; +/* + * This is a mask of bits to clear in the SR when we go to a + * given interrupt priority level. + */ +/* XXX see comments in p_dti_arcstation_init() */ +static const u_int32_t dti_arcstation_ipl_sr_bits[_IPL_N] = { + 0, /* IPL_NONE */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_BIO */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_NET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_{TTY,SERIAL} */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_{CLOCK,HIGH} */ +}; + #if NPC_ISA > 0 || NOPMS_ISA > 0 /* * platform-dependent pccons configuration @@ -202,6 +257,7 @@ * or * - use MIP3_INTERNAL_TIMER_INTERRUPT for clock */ + ipl_sr_bits = dti_arcstation_ipl_sr_bits; /* * common configuration for DTI platforms Index: arc/p_dti_tyne.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/p_dti_tyne.c,v retrieving revision 1.1 diff -u -r1.1 p_dti_tyne.c --- arc/p_dti_tyne.c 2001/06/13 15:27:18 1.1 +++ arc/p_dti_tyne.c 2003/04/28 06:03:54 @@ -97,6 +97,61 @@ arc_set_intr, }; +/* + * This is a mask of bits to clear in the SR when we go to a + * given interrupt priority level. + */ +/* XXX see comments in p_dti_tyne_init() */ +static const u_int32_t dti_tyne_ipl_sr_bits[_IPL_N] = { + 0, /* IPL_NONE */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_BIO */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_NET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_{TTY,SERIAL} */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_{CLOCK,HIGH} */ +}; + #if NPC_ISA > 0 || NOPMS_ISA > 0 /* * platform-dependent pccons configuration @@ -199,6 +254,7 @@ * or * - use MIP3_INTERNAL_TIMER_INTERRUPT for clock */ + ipl_sr_bits = dti_tyne_ipl_sr_bits; /* * common configuration for DTI platforms Index: arc/p_sni_rm200pci.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/arc/p_sni_rm200pci.c,v retrieving revision 1.1 diff -u -r1.1 p_sni_rm200pci.c --- arc/p_sni_rm200pci.c 2001/06/13 15:36:44 1.1 +++ arc/p_sni_rm200pci.c 2003/04/28 06:03:55 @@ -79,6 +79,61 @@ }; /* + * This is a mask of bits to clear in the SR when we go to a + * given interrupt priority level. + */ +/* XXX lack of hardware info for sni_rm200pci */ +static const u_int32_t sni_rm200pci_ipl_sr_bits[_IPL_N] = { + 0, /* IPL_NONE */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ + + MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_BIO */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_NET */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_{TTY,SERIAL} */ + + MIPS_SOFT_INT_MASK_0| + MIPS_SOFT_INT_MASK_1| + MIPS_INT_MASK_0| + MIPS_INT_MASK_1| + MIPS_INT_MASK_2| + MIPS_INT_MASK_3| + MIPS_INT_MASK_4| + MIPS_INT_MASK_5, /* XXX IPL_{CLOCK,HIGH} */ +}; + +/* * critial i/o space, interrupt, and other chipset related initialization. */ void @@ -109,6 +164,7 @@ /* * Initialize interrupt priority */ + ipl_sr_bits = sni_rm200pci_ipl_sr_bits; } void Index: conf/std.arc =================================================================== RCS file: /cvsroot/src/sys/arch/arc/conf/std.arc,v retrieving revision 1.14 diff -u -r1.14 std.arc --- conf/std.arc 2003/04/28 05:03:44 1.14 +++ conf/std.arc 2003/04/28 06:03:55 @@ -18,6 +18,4 @@ options MIPS3_L2CACHE_ABSENT # may not have L2 cache -options __NO_SOFT_SERIAL_INTERRUPT # for "com" driver - makeoptions DEFTEXTADDR="0x80200000" Index: include/intr.h =================================================================== RCS file: /cvsroot/src/sys/arch/arc/include/intr.h,v retrieving revision 1.10 diff -u -r1.10 intr.h --- include/intr.h 2001/06/13 15:08:06 1.10 +++ include/intr.h 2003/04/28 06:03:55 @@ -1,7 +1,11 @@ /* $NetBSD: intr.h,v 1.10 2001/06/13 15:08:06 soda Exp $ */ -/* - * Copyright (c) 1998 Jonathan Stone. All rights reserved. +/*- + * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -13,125 +17,158 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by Jonathan Stone for - * the NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ #ifndef _ARC_INTR_H_ #define _ARC_INTR_H_ #define IPL_NONE 0 /* disable only this interrupt */ -#define IPL_BIO 1 /* disable block I/O interrupts */ -#define IPL_NET 2 /* disable network interrupts */ -#define IPL_TTY 3 /* disable terminal interrupts */ -#define IPL_IMP 4 /* memory allocation */ -#define IPL_CLOCK 5 /* disable clock interrupts */ -#define IPL_STATCLOCK 6 /* disable profiling interrupts */ -#if 0 /* XXX */ + +#define IPL_SOFT 1 /* generic software interrupts (SI 0) */ +#define IPL_SOFTCLOCK 2 /* clock software interrupts (SI 0) */ +#define IPL_SOFTNET 3 /* network software interrupts (SI 1) */ +#define IPL_SOFTSERIAL 4 /* serial software interrupts (SI 1) */ + +#define IPL_BIO 5 /* disable block I/O interrupts */ +#define IPL_NET 6 /* disable network interrupts */ +#define IPL_TTY 7 /* disable terminal interrupts */ #define IPL_SERIAL 7 /* disable serial hardware interrupts */ -#endif +#define IPL_CLOCK 8 /* disable clock interrupts */ +#define IPL_STATCLOCK 8 /* disable profiling interrupts */ #define IPL_HIGH 8 /* disable all interrupts */ -#define NIPL 9 +#define _IPL_NSOFT 4 +#define _IPL_N 9 + +#define _IPL_SI0_FIRST IPL_SOFT +#define _IPL_SI0_LAST IPL_SOFTCLOCK + +#define _IPL_SI1_FIRST IPL_SOFTNET +#define _IPL_SI1_LAST IPL_SOFTSERIAL + +#define IPL_SOFTNAMES { \ + "misc", \ + "clock", \ + "net", \ + "serial", \ +} + /* Interrupt sharing types. */ #define IST_NONE 0 /* none */ #define IST_PULSE 1 /* pulsed */ #define IST_EDGE 2 /* edge-triggered */ #define IST_LEVEL 3 /* level-triggered */ -/* Soft interrupt masks. */ -/* XXX - revisit here */ -#define SIR_CLOCK 31 -#define SIR_NET 30 -#define SIR_CLOCKMASK ((1 << SIR_CLOCK)) -#define SIR_NETMASK ((1 << SIR_NET) | SIR_CLOCKMASK) -#define SIR_ALLMASK (SIR_CLOCKMASK | SIR_NETMASK) - #ifdef _KERNEL #ifndef _LOCORE -#include <mips/cpuregs.h> +#include <sys/device.h> +#include <sys/lock.h> -extern int _splraise __P((int)); -extern int _spllower __P((int)); -extern int _splset __P((int)); -extern int _splget __P((void)); -extern void _splnone __P((void)); -extern void _setsoftintr __P((int)); -extern void _clrsoftintr __P((int)); - -#define setsoftclock() _setsoftintr(MIPS_SOFT_INT_MASK_0) -#define setsoftnet() _setsoftintr(MIPS_SOFT_INT_MASK_1) -#define clearsoftclock() _clrsoftintr(MIPS_SOFT_INT_MASK_0) -#define clearsoftnet() _clrsoftintr(MIPS_SOFT_INT_MASK_1) +extern const u_int32_t *ipl_sr_bits; +extern const u_int32_t ipl_si_to_sr[_IPL_NSOFT]; -/* - * nesting interrupt masks. - */ -#define MIPS_INT_MASK_SPL_SOFT0 MIPS_SOFT_INT_MASK_0 -#define MIPS_INT_MASK_SPL_SOFT1 (MIPS_SOFT_INT_MASK_1|MIPS_INT_MASK_SPL_SOFT0) -#define MIPS_INT_MASK_SPL0 (MIPS_INT_MASK_0|MIPS_INT_MASK_SPL_SOFT1) -#define MIPS_INT_MASK_SPL1 (MIPS_INT_MASK_1|MIPS_INT_MASK_SPL0) -#define MIPS_INT_MASK_SPL2 (MIPS_INT_MASK_2|MIPS_INT_MASK_SPL1) -#define MIPS_INT_MASK_SPL3 (MIPS_INT_MASK_3|MIPS_INT_MASK_SPL2) -#define MIPS_INT_MASK_SPL4 (MIPS_INT_MASK_4|MIPS_INT_MASK_SPL3) -#define MIPS_INT_MASK_SPL5 (MIPS_INT_MASK_5|MIPS_INT_MASK_SPL4) -#define MIPS_INT_MASK_SPLHIGH MIPS_INT_MASK_SPL5 +extern int _splraise(int); +extern int _spllower(int); +extern int _splset(int); +extern int _splget(void); +extern void _splnone(void); +extern void _setsoftintr(int); +extern void _clrsoftintr(int); +#define splhigh() _splraise(ipl_sr_bits[IPL_HIGH]) #define spl0() (void)_spllower(0) #define splx(s) (void)_splset(s) -#define splbio() (_splraise(splvec.splbio)) -#define splnet() (_splraise(splvec.splnet)) -#define spltty() (_splraise(splvec.spltty)) -#define splvm() (_splraise(splvec.splvm)) -#define splclock() (_splraise(splvec.splclock)) -#define splstatclock() (_splraise(splvec.splstatclock)) -#define splhigh() _splraise(MIPS_INT_MASK_SPLHIGH) - -#define splsoftclock() _splraise(MIPS_INT_MASK_SPL_SOFT0) -#define splsoftnet() _splraise(MIPS_INT_MASK_SPL_SOFT1) -#define spllowersoftclock() _spllower(MIPS_INT_MASK_SPL_SOFT0) +#define splbio() _splraise(ipl_sr_bits[IPL_BIO]) +#define splnet() _splraise(ipl_sr_bits[IPL_NET]) +#define spltty() _splraise(ipl_sr_bits[IPL_TTY]) +#define splserial() _splraise(ipl_sr_bits[IPL_SERIAL]) +#define splvm() spltty() +#define splclock() _splraise(ipl_sr_bits[IPL_CLOCK]) +#define splstatclock() splclock() -#define splsched() splhigh() -#define spllock() splhigh() +#define splsched() splclock() +#define spllock() splhigh() #define spllpt() spltty() /* lpt driver */ + +#define splsoft() _splraise(ipl_sr_bits[IPL_SOFT]) +#define splsoftclock() _splraise(ipl_sr_bits[IPL_SOFTCLOCK]) +#define splsoftnet() _splraise(ipl_sr_bits[IPL_SOFTNET]) +#define splsoftserial() _splraise(ipl_sr_bits[IPL_SOFTSERIAL]) + +#define spllowersoftclock() _spllower(ipl_sr_bits[IPL_SOFTCLOCK]) + +#define setsoft(x) \ +do { \ + _setsoftintr(ipl_si_to_sr[(x) - IPL_SOFT]); \ +} while (/*CONSTCOND*/0) + +struct arc_soft_intrhand { + TAILQ_ENTRY(arc_soft_intrhand) sih_q; + struct arc_soft_intr *sih_intrhead; + void (*sih_func)(void *); + void *sih_arg; + int sih_pending; +}; -struct splvec { - int splbio; - int splnet; - int spltty; - int splvm; - int splclock; - int splstatclock; +struct arc_soft_intr { + TAILQ_HEAD(,arc_soft_intrhand) softintr_q; + struct evcnt softintr_evcnt; + struct simplelock softintr_slock; + unsigned long softintr_ipl; }; -extern struct splvec splvec; +void *softintr_establish(int, void (*)(void *), void *); +void softintr_disestablish(void *); +void softintr_init(void); +void softintr_dispatch(void); + +#define softintr_schedule(arg) \ +do { \ + struct arc_soft_intrhand *__sih = (arg); \ + struct arc_soft_intr *__si = __sih->sih_intrhead; \ + int __s; \ + \ + __s = splhigh(); \ + simple_lock(&__si->softintr_slock); \ + if (__sih->sih_pending == 0) { \ + TAILQ_INSERT_TAIL(&__si->softintr_q, __sih, sih_q); \ + __sih->sih_pending = 1; \ + setsoft(__si->softintr_ipl); \ + } \ + simple_unlock(&__si->softintr_slock); \ + splx(__s); \ +} while (/*CONSTCOND*/0) + +/* XXX For legacy software interrupts. */ +extern struct arc_soft_intrhand *softnet_intrhand; + +#define setsoftnet() softintr_schedule(softnet_intrhand) + /* * Index into intrcnt[], which is defined in locore */ -#define SOFTCLOCK_INTR 0 -#define SOFTNET_INTR 1 -#define FPU_INTR 2 extern u_long intrcnt[]; struct clockframe; -void arc_set_intr __P((int, int(*)(u_int, struct clockframe *), int)); - -/* XXX - revisit here */ -int imask[NIPL]; +void arc_set_intr(int, int(*)(u_int, struct clockframe *), int); #endif /* !_LOCORE */ #endif /* _KERNEL */ Index: include/types.h =================================================================== RCS file: /cvsroot/src/sys/arch/arc/include/types.h,v retrieving revision 1.13 diff -u -r1.13 types.h --- include/types.h 2002/03/05 16:12:36 1.13 +++ include/types.h 2003/04/28 06:03:55 @@ -6,6 +6,7 @@ #include <mips/types.h> +#define __HAVE_GENERIC_SOFT_INTERRUPTS #define __HAVE_DEVICE_REGISTER #define __HAVE_NWSCONS Index: isa/isabus.c =================================================================== RCS file: /cvsroot/src/sys/arch/arc/isa/isabus.c,v retrieving revision 1.19 diff -u -r1.19 isabus.c --- isa/isabus.c 2003/04/27 17:05:58 1.19 +++ isa/isabus.c 2003/04/28 06:03:55 @@ -133,6 +133,7 @@ int fakeintr __P((void *a)); struct isabr_config *isabr_conf = NULL; +u_int32_t imask[_IPL_N]; /* XXX */ void isabrattach(sc) @@ -217,39 +218,47 @@ } /* Then figure out which IRQs use each level. */ - for (level = 0; level < 5; level++) { + for (level = 0; level < _IPL_N; level++) { int irqs = 0; for (irq = 0; irq < ICU_LEN; irq++) if (intrlevel[irq] & (1 << level)) irqs |= 1 << irq; - imask[level] = irqs | SIR_ALLMASK; + imask[level] = irqs; } - /* - * There are tty, network and disk drivers that use free() at interrupt - * time, so imp > (tty | net | bio). - */ - imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO]; + imask[IPL_NONE] = 0; + + imask[IPL_SOFT] |= imask[IPL_NONE]; + imask[IPL_SOFTCLOCK] |= imask[IPL_SOFT]; + imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK]; + imask[IPL_SOFTSERIAL] |= imask[IPL_SOFTNET]; /* * Enforce a hierarchy that gives slow devices a better chance at not * dropping data. */ - imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO]; + imask[IPL_BIO] |= imask[IPL_SOFTSERIAL]; imask[IPL_NET] |= imask[IPL_BIO]; + imask[IPL_TTY] |= imask[IPL_NET]; + + /* + * Since run queues may be manipulated by both the statclock and tty, + * network, and diskdrivers, clock > tty. + */ + imask[IPL_CLOCK] |= imask[IPL_TTY]; + imask[IPL_STATCLOCK] |= imask[IPL_CLOCK]; /* - * These are pseudo-levels. + * IPL_HIGH must block everything that can manipulate a run queue. */ - imask[IPL_NONE] = 0x00000000; - imask[IPL_HIGH] = 0xffffffff; + imask[IPL_HIGH] |= imask[IPL_STATCLOCK]; /* And eventually calculate the complete masks. */ for (irq = 0; irq < ICU_LEN; irq++) { int irqs = 1 << irq; for (q = intrhand[irq]; q; q = q->ih_next) irqs |= imask[q->ih_level]; - intrmask[irq] = irqs | SIR_ALLMASK; + intrmask[irq] = irqs; } /* Lastly, determine which IRQs are actually in use. */