--- Net2/arch/i386/isa/icu.s 2018/04/24 18:07:13 1.1.1.2 +++ Net2/arch/i386/isa/icu.s 2018/04/24 18:20:12 1.1.1.4 @@ -10,17 +10,17 @@ * 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. + * 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. + * 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: + * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -34,7 +34,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)icu.s 7.2 (Berkeley) 5/21/91 + * from: @(#)icu.s 7.2 (Berkeley) 5/21/91 + * icu.s,v 1.19 1993/07/11 14:12:40 mycroft Exp */ /* @@ -42,342 +43,333 @@ * Vector interrupt control section */ +/* + * XXX - this file is now misnamed. All spls are now soft and the only thing + * related to the hardware icu is that the bit numbering is the same in the + * soft priority masks as in the hard ones. + */ + +#ifdef notyet +#include "sio.h" +#else +#define NSIO 0 +#endif + +#define HIGHMASK 0xffff +#define SOFTCLOCKMASK 0x8000 + .data - .globl _imen .globl _cpl -_cpl: .long 0xffff # current priority level (all off) +_cpl: .long 0xffff # current priority (all off) + .globl _imen _imen: .long 0xffff # interrupt mask enable (all off) .globl _highmask -_highmask: .long 0xffff +_highmask: .long HIGHMASK .globl _ttymask _ttymask: .long 0 .globl _biomask _biomask: .long 0 .globl _netmask _netmask: .long 0 - .globl _isa_intr -_isa_intr: .space 16*4 + .globl _impmask +_impmask: .long 0 + .globl _ipending +_ipending: .long 0 +vec: + .long INTRLOCAL(vec0), INTRLOCAL(vec1), INTRLOCAL(vec2) + .long INTRLOCAL(vec3), INTRLOCAL(vec4), INTRLOCAL(vec5) + .long INTRLOCAL(vec6), INTRLOCAL(vec7), INTRLOCAL(vec8) + .long INTRLOCAL(vec9), INTRLOCAL(vec10), INTRLOCAL(vec11) + .long INTRLOCAL(vec12), INTRLOCAL(vec13), INTRLOCAL(vec14) + .long INTRLOCAL(vec15) + +#define GENSPL(name, mask, event) \ + .globl _spl/**/name ; \ + ALIGN_TEXT ; \ +_spl/**/name: ; \ + COUNT_EVENT(_intrcnt_spl, event) ; \ + movl _cpl,%eax ; \ + movl %eax,%edx ; \ + orl mask,%edx ; \ + movl %edx,_cpl ; \ + SHOW_CPL ; \ + ret + +#define FASTSPL(mask) \ + movl mask,_cpl ; \ + SHOW_CPL + +#define FASTSPL_VARMASK(varmask) \ + movl varmask,%eax ; \ + movl %eax,_cpl ; \ + SHOW_CPL .text + + ALIGN_TEXT +INTRLOCAL(unpend_v): + COUNT_EVENT(_intrcnt_spl, 0) + bsfl %eax,%eax # slow, but not worth optimizing + btrl %eax,_ipending + jnc INTRLOCAL(unpend_v_next) # some intr cleared the in-memory bit + SHOW_IPENDING + movl Vresume(,%eax,4),%eax + testl %eax,%eax + je INTRLOCAL(noresume) + jmp %eax + + ALIGN_TEXT +/* + * XXX - must be some fastintr, need to register those too. + */ +INTRLOCAL(noresume): +#if NSIO > 0 + call _softsio1 +#endif +INTRLOCAL(unpend_v_next): + movl _cpl,%eax + movl %eax,%edx + notl %eax + andl _ipending,%eax + je INTRLOCAL(none_to_unpend) + jmp INTRLOCAL(unpend_v) + /* * Handle return from interrupt after device handler finishes */ + ALIGN_TEXT doreti: - cli - popl %ebx # remove intr number - NOP - popl %eax # get previous priority - # now interrupt frame is a trap frame! - movw %ax,%cx - movw %ax,_cpl - orw _imen,%ax - outb %al,$ IO_ICU1+1 # re-enable intr? - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP - - cmpw $0x1f,13*4(%esp) # to user? - je 1f # nope, leave - andw $0xffff,%cx - cmpw $0,%cx # returning to zero? - je 1f - - pop %es # nope, going to non-zero level - pop %ds - popa + COUNT_EVENT(_intrcnt_spl, 1) + addl $4,%esp # discard unit arg + popl %eax # get previous priority +/* + * Now interrupt frame is a trap frame! + * + * XXX - setting up the interrupt frame to be almost a stack frame is mostly + * a waste of time. + */ + movl %eax,_cpl + SHOW_CPL + movl %eax,%edx + notl %eax + andl _ipending,%eax + jne INTRLOCAL(unpend_v) +INTRLOCAL(none_to_unpend): + testl %edx,%edx # returning to zero priority? + jne 1f # nope, going to non-zero priority + movl _netisr,%eax + testl %eax,%eax # check for softint s/traps + jne 2f # there are some + jmp test_resched # XXX - schedule jumps better + COUNT_EVENT(_intrcnt_spl, 2) # XXX + + ALIGN_TEXT # XXX +1: # XXX + COUNT_EVENT(_intrcnt_spl, 3) + popl %es + popl %ds + popal addl $8,%esp iret -1: cmpl $0,_netisr # check for softint s/traps - jne 1f - cmpl $0,_want_resched - jne 1f - - pop %es # none, going back to base pri - pop %ds - popa - addl $8,%esp - iret - #include "../net/netisr.h" -1: - -#define DONET(s, c) ; \ - .globl c ; \ - btrl $ s ,_netisr ; \ - jnb 1f ; \ +#define DONET(s, c, event) ; \ + .globl c ; \ + btrl $s,_netisr ; \ + jnc 1f ; \ + COUNT_EVENT(_intrcnt_spl, event) ; \ call c ; \ 1: - call _splnet - - DONET(NETISR_RAW,_rawintr) + ALIGN_TEXT +2: + COUNT_EVENT(_intrcnt_spl, 4) +/* + * XXX - might need extra locking while testing reg copy of netisr, but + * interrupt routines setting it would not cause any new problems (since we + * don't loop, fresh bits will not be processed until the next doreti or spl0) + */ + testl $~((1 << NETISR_SCLK) | (1 << NETISR_AST)),%eax + je test_ASTs # no net stuff, just temporary AST's + FASTSPL_VARMASK(_netmask) + DONET(NETISR_RAW, _rawintr, 5) #ifdef INET - DONET(NETISR_IP,_ipintr) + DONET(NETISR_IP, _ipintr, 6) #endif #ifdef IMP - DONET(NETISR_IMP,_impintr) + DONET(NETISR_IMP, _impintr, 7) #endif #ifdef NS - DONET(NETISR_NS,_nsintr) + DONET(NETISR_NS, _nsintr, 8) #endif - -#ifdef notdef - NOP - popl %eax - movw %ax,_cpl - orw _imen,%ax - outb %al,$ IO_ICU1+1 # re-enable intr? - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP -#else - call _spl0 +#ifdef ISO + DONET(NETISR_ISO, _clnlintr, 25) #endif - - btrl $ NETISR_SCLK,_netisr - jnb 1f - # back to an interrupt frame for a moment - call _splsoftclock - pushl $0xff # dummy intr + FASTSPL($0) +test_ASTs: + btrl $NETISR_SCLK,_netisr + jnc test_resched + COUNT_EVENT(_intrcnt_spl, 9) + FASTSPL($SOFTCLOCKMASK) +/* + * Back to an interrupt frame for a moment. + */ + pushl $0 # previous cpl (probably not used) + pushl $0x7f # dummy unit number call _softclock - popl %eax - call _spl0 - - # jmp 2f - -1: - cmpw $0x1f,13*4(%esp) # to user? - jne 2f # nope, leave + addl $8,%esp # discard dummies + FASTSPL($0) +test_resched: +#ifdef notused1 + btrl $NETISR_AST,_netisr + jnc 2f +#endif +#ifdef notused2 cmpl $0,_want_resched je 2f +#endif + cmpl $0,_astpending # XXX - put it back in netisr to + je 2f # reduce the number of tests + testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) + # to non-kernel (i.e., user)? + je 2f # nope, leave + COUNT_EVENT(_intrcnt_spl, 10) + movl $0,_astpending call _trap - -2: pop %es - pop %ds +2: + COUNT_EVENT(_intrcnt_spl, 11) + popl %es + popl %ds popal addl $8,%esp iret /* * Interrupt priority mechanism - * - * Two flavors -- imlXX masks relative to ISA noemenclature (for PC compat sw) - * -- splXX masks with group mechanism for BSD purposes + * -- soft splXX masks with group mechanism (cpl) + * -- h/w masks for currently active or unused interrupts (imen) + * -- ipending = active interrupts currently masked by cpl */ - .globl _splhigh - .globl _splclock -_splhigh: -_splclock: - cli # disable interrupts - NOP - movw $0xffff,%ax # set new priority level - movw %ax,%dx - # orw _imen,%ax # mask off those not enabled yet - movw %ax,%cx - outb %al,$ IO_ICU1+1 /* update icu's */ - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP - movzwl _cpl,%eax # return old priority - movw %dx,_cpl # set new priority level - sti # enable interrupts - ret - - .globl _spltty # block clists -_spltty: - cli # disable interrupts - NOP - movw _cpl,%ax - orw _ttymask,%ax - movw %ax,%dx - orw _imen,%ax # mask off those not enabled yet - movw %ax,%cx - outb %al,$ IO_ICU1+1 /* update icu's */ - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP - movzwl _cpl,%eax # return old priority - movw %dx,_cpl # set new priority level - sti # enable interrupts - ret - - .globl _splimp - .globl _splnet -_splimp: -_splnet: - cli # disable interrupts - NOP - movw _cpl,%ax - orw _netmask,%ax - movw %ax,%dx - orw _imen,%ax # mask off those not enabled yet - movw %ax,%cx - outb %al,$ IO_ICU1+1 /* update icu's */ - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP - movzwl _cpl,%eax # return old priority - movw %dx,_cpl # set new priority level - sti # enable interrupts - ret - - .globl _splbio -_splbio: - cli # disable interrupts - NOP - movw _cpl,%ax - orw _biomask,%ax - movw %ax,%dx - orw _imen,%ax # mask off those not enabled yet - movw %ax,%cx - outb %al,$ IO_ICU1+1 /* update icu's */ - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP - movzwl _cpl,%eax # return old priority - movw %dx,_cpl # set new priority level - sti # enable interrupts - ret - - .globl _splsoftclock -_splsoftclock: - cli # disable interrupts - NOP - movw _cpl,%ax - orw $0x8000,%ax # set new priority level - movw %ax,%dx - orw _imen,%ax # mask off those not enabled yet - movw %ax,%cx - outb %al,$ IO_ICU1+1 /* update icu's */ - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP - movzwl _cpl,%eax # return old priority - movw %dx,_cpl # set new priority level - sti # enable interrupts - ret + GENSPL(bio, _biomask, 12) + GENSPL(clock, $HIGHMASK, 13) /* splclock == splhigh ex for count */ + GENSPL(high, $HIGHMASK, 14) + GENSPL(imp, _impmask, 15) + GENSPL(net, _netmask, 16) + GENSPL(softclock, $SOFTCLOCKMASK, 17) + GENSPL(tty, _ttymask, 18) .globl _splnone .globl _spl0 + ALIGN_TEXT _splnone: _spl0: - cli # disable interrupts - NOP - pushl _cpl # save old priority - movw _cpl,%ax - orw _netmask,%ax # mask off those network devices - movw %ax,_cpl # set new priority level - orw _imen,%ax # mask off those not enabled yet - outb %al,$ IO_ICU1+1 /* update icu's */ - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP - sti # enable interrupts - - DONET(NETISR_RAW,_rawintr) + COUNT_EVENT(_intrcnt_spl, 19) +in_spl0: + movl _cpl,%eax + pushl %eax # save old priority + testl $~((1 << NETISR_SCLK) | (1 << NETISR_AST)),_netisr + jz INTRLOCAL(over_net_stuff_for_spl0) + movl _netmask,%eax # mask off those network devices + movl %eax,_cpl # set new priority + SHOW_CPL + DONET(NETISR_RAW, _rawintr, 20) #ifdef INET - DONET(NETISR_IP,_ipintr) + DONET(NETISR_IP, _ipintr, 21) +#endif +#ifdef IMP + DONET(NETISR_IMP, _impintr, 26) +#endif +#ifdef NS + DONET(NETISR_NS, _nsintr, 27) #endif - cli # disable interrupts - popl _cpl # save old priority - NOP - movw $0,%ax # set new priority level - movw %ax,%dx - orw _imen,%ax # mask off those not enabled yet - movw %ax,%cx - outb %al,$ IO_ICU1+1 /* update icu's */ - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP - movzwl _cpl,%eax # return old priority - movw %dx,_cpl # set new priority level - sti # enable interrupts +#ifdef ISO + DONET(NETISR_ISO, _clnlintr, 28) +#endif +INTRLOCAL(over_net_stuff_for_spl0): + movl $0,_cpl # set new priority + SHOW_CPL + movl _ipending,%eax + testl %eax,%eax + jne INTRLOCAL(unpend_V) + popl %eax # return old priority ret - + .globl _splx + ALIGN_TEXT _splx: - cli # disable interrupts - NOP - movw 4(%esp),%ax # new priority level - movw %ax,%dx - cmpw $0,%dx - je _spl0 # going to "zero level" is special - - orw _imen,%ax # mask off those not enabled yet - movw %ax,%cx - outb %al,$ IO_ICU1+1 /* update icu's */ - NOP - movb %ah,%al - outb %al,$ IO_ICU2+1 - NOP - movzwl _cpl,%eax # return old priority - movw %dx,_cpl # set new priority level - sti # enable interrupts + COUNT_EVENT(_intrcnt_spl, 22) + movl 4(%esp),%eax # new priority + testl %eax,%eax + je in_spl0 # going to "zero level" is special + COUNT_EVENT(_intrcnt_spl, 23) + movl _cpl,%edx # save old priority + movl %eax,_cpl # set new priority + SHOW_CPL + notl %eax + andl _ipending,%eax + jne INTRLOCAL(unpend_V_result_edx) + movl %edx,%eax # return old priority ret - /* hardware interrupt catcher (IDT 32 - 47) */ - .globl _isa_strayintr - -IDTVEC(intr0) - INTRSTRAY(0, _highmask, 0) ; call _isa_strayintr ; INTREXIT1 - -IDTVEC(intr1) - INTRSTRAY(1, _highmask, 1) ; call _isa_strayintr ; INTREXIT1 - -IDTVEC(intr2) - INTRSTRAY(2, _highmask, 2) ; call _isa_strayintr ; INTREXIT1 - -IDTVEC(intr3) - INTRSTRAY(3, _highmask, 3) ; call _isa_strayintr ; INTREXIT1 - -IDTVEC(intr4) - INTRSTRAY(4, _highmask, 4) ; call _isa_strayintr ; INTREXIT1 - -IDTVEC(intr5) - INTRSTRAY(5, _highmask, 5) ; call _isa_strayintr ; INTREXIT1 - -IDTVEC(intr6) - INTRSTRAY(6, _highmask, 6) ; call _isa_strayintr ; INTREXIT1 - -IDTVEC(intr7) - INTRSTRAY(7, _highmask, 7) ; call _isa_strayintr ; INTREXIT1 - - -IDTVEC(intr8) - INTRSTRAY(8, _highmask, 8) ; call _isa_strayintr ; INTREXIT2 - -IDTVEC(intr9) - INTRSTRAY(9, _highmask, 9) ; call _isa_strayintr ; INTREXIT2 - -IDTVEC(intr10) - INTRSTRAY(10, _highmask, 10) ; call _isa_strayintr ; INTREXIT2 - -IDTVEC(intr11) - INTRSTRAY(11, _highmask, 11) ; call _isa_strayintr ; INTREXIT2 - -IDTVEC(intr12) - INTRSTRAY(12, _highmask, 12) ; call _isa_strayintr ; INTREXIT2 + ALIGN_TEXT +INTRLOCAL(unpend_V_result_edx): + pushl %edx +INTRLOCAL(unpend_V): + COUNT_EVENT(_intrcnt_spl, 24) + bsfl %eax,%eax + btrl %eax,_ipending + jnc INTRLOCAL(unpend_V_next) + SHOW_IPENDING + movl Vresume(,%eax,4),%edx + testl %edx,%edx + je INTRLOCAL(noresumeV) +/* + * We would prefer to call the intr handler directly here but that doesn't + * work for badly behaved handlers that want the interrupt frame. Also, + * there's a problem determining the unit number. We should change the + * interface so that the unit number is not determined at config time. + */ + jmp *vec(,%eax,4) -IDTVEC(intr13) - INTRSTRAY(13, _highmask, 13) ; call _isa_strayintr ; INTREXIT2 + ALIGN_TEXT +/* + * XXX - must be some fastintr, need to register those too. + */ +INTRLOCAL(noresumeV): +#if NSIO > 0 + call _softsio1 +#endif +INTRLOCAL(unpend_V_next): + movl _cpl,%eax + notl %eax + andl _ipending,%eax + jne INTRLOCAL(unpend_V) + popl %eax + ret -IDTVEC(intr14) - INTRSTRAY(14, _highmask, 14) ; call _isa_strayintr ; INTREXIT2 +#define BUILD_VEC(irq_num) \ + ALIGN_TEXT ; \ +INTRLOCAL(vec/**/irq_num): ; \ + int $ICU_OFFSET + (irq_num) ; \ + popl %eax ; \ + ret -IDTVEC(intr15) - INTRSTRAY(15, _highmask, 15) ; call _isa_strayintr ; INTREXIT2 + BUILD_VEC(0) + BUILD_VEC(1) + BUILD_VEC(2) + BUILD_VEC(3) + BUILD_VEC(4) + BUILD_VEC(5) + BUILD_VEC(6) + BUILD_VEC(7) + BUILD_VEC(8) + BUILD_VEC(9) + BUILD_VEC(10) + BUILD_VEC(11) + BUILD_VEC(12) + BUILD_VEC(13) + BUILD_VEC(14) + BUILD_VEC(15) -IDTVEC(intrdefault) - INTRSTRAY(255, _highmask, 255) ; call _isa_strayintr ; INTREXIT2