Annotation of sys/arch/i386/i386/vector.s, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: vector.s,v 1.10 2007/04/12 20:22:58 art Exp $ */
! 2: /* $NetBSD: vector.s,v 1.32 1996/01/07 21:29:47 mycroft Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Charles M. Hannum.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: #include <machine/i8259.h>
! 34: #include <dev/isa/isareg.h>
! 35:
! 36: #define MY_COUNT _C_LABEL(uvmexp)
! 37:
! 38: /*
! 39: * Macros for interrupt entry, call to handler, and exit.
! 40: *
! 41: * XXX
! 42: * The interrupt frame is set up to look like a trap frame. This may be a
! 43: * waste. The only handler which needs a frame is the clock handler, and it
! 44: * only needs a few bits. Xdoreti() needs a trap frame for handling ASTs, but
! 45: * it could easily convert the frame on demand.
! 46: *
! 47: * The direct costs of setting up a trap frame are two pushl's (error code and
! 48: * trap number), an addl to get rid of these, and pushing and popping the
! 49: * callee-saved registers %esi, %edi, %ebx, and %ebp twice.
! 50: *
! 51: * If the interrupt frame is made more flexible, INTR can push %eax first and
! 52: * decide the ipending case with less overhead, e.g., by avoiding loading the
! 53: * segment registers.
! 54: *
! 55: * XXX
! 56: * Should we do a cld on every system entry to avoid the requirement for
! 57: * scattered cld's?
! 58: */
! 59:
! 60: .globl _C_LABEL(isa_strayintr)
! 61:
! 62: #ifdef MULTIPROCESSOR
! 63: #define LOCK_KERNEL(ipl) pushl ipl; call _C_LABEL(i386_intlock); addl $4,%esp
! 64: #define UNLOCK_KERNEL(ipl) pushl ipl; call _C_LABEL(i386_intunlock); addl $4,%esp
! 65: #else
! 66: #define LOCK_KERNEL(ipl)
! 67: #define UNLOCK_KERNEL(ipl)
! 68: #endif
! 69:
! 70: #define voidop(num)
! 71:
! 72: /*
! 73: * Normal vectors.
! 74: *
! 75: * We cdr down the intrhand chain, calling each handler with its appropriate
! 76: * argument (0 meaning a pointer to the frame, for clock interrupts).
! 77: *
! 78: * The handler returns one of three values:
! 79: * 0 - This interrupt wasn't for me.
! 80: * 1 - This interrupt was for me.
! 81: * -1 - This interrupt might have been for me, but I don't know.
! 82: * If there are no handlers, or they all return 0, we flag it as a `stray'
! 83: * interrupt. On a system with level-triggered interrupts, we could terminate
! 84: * immediately when one of them returns 1; but this is a PC.
! 85: *
! 86: * On exit, we jump to Xdoreti(), to process soft interrupts and ASTs.
! 87: */
! 88: #define INTRSTUB(name, num, early_ack, late_ack, mask, unmask, level_mask) \
! 89: IDTVEC(resume_/**/name/**/num) ;\
! 90: push %ebx ;\
! 91: cli ;\
! 92: jmp 1f ;\
! 93: IDTVEC(recurse_/**/name/**/num) ;\
! 94: pushfl ;\
! 95: pushl %cs ;\
! 96: pushl %esi ;\
! 97: pushl $0 /* dummy error code */ ;\
! 98: pushl $T_ASTFLT /* trap # for doing ASTs */ ;\
! 99: movl %ebx,%esi ;\
! 100: INTRENTRY ;\
! 101: MAKE_FRAME ;\
! 102: push %esi ;\
! 103: cli ;\
! 104: jmp 1f ;\
! 105: _C_LABEL(Xintr_/**/name/**/num): ;\
! 106: pushl $0 /* dummy error code */ ;\
! 107: pushl $T_ASTFLT /* trap # for doing ASTs */ ;\
! 108: INTRENTRY ;\
! 109: MAKE_FRAME ;\
! 110: mask(num) /* mask it in hardware */ ;\
! 111: early_ack(num) /* and allow other intrs */ ;\
! 112: incl MY_COUNT+V_INTR /* statistical info */ ;\
! 113: movl _C_LABEL(iminlevel) + (num) * 4, %eax ;\
! 114: movl CPL,%ebx ;\
! 115: cmpl %eax,%ebx ;\
! 116: jae _C_LABEL(Xhold_/**/name/**/num)/* currently masked; hold it */;\
! 117: pushl %ebx /* cpl to restore on exit */ ;\
! 118: 1: ;\
! 119: movl _C_LABEL(imaxlevel) + (num) * 4,%eax ;\
! 120: movl %eax,CPL /* block enough for this irq */ ;\
! 121: sti /* safe to take intrs now */ ;\
! 122: movl _C_LABEL(intrhand) + (num) * 4,%ebx /* head of chain */ ;\
! 123: testl %ebx,%ebx ;\
! 124: jz _C_LABEL(Xstray_/**/name/**/num) /* no handlers; we're stray */ ;\
! 125: STRAY_INITIALIZE /* nobody claimed it yet */ ;\
! 126: LOCK_KERNEL(IF_PPL(%esp)) ;\
! 127: 7: movl IH_ARG(%ebx),%eax /* get handler arg */ ;\
! 128: testl %eax,%eax ;\
! 129: jnz 4f ;\
! 130: movl %esp,%eax /* 0 means frame pointer */ ;\
! 131: 4: pushl %eax ;\
! 132: call *IH_FUN(%ebx) /* call it */ ;\
! 133: addl $4,%esp /* toss the arg */ ;\
! 134: STRAY_INTEGRATE /* maybe he claimed it */ ;\
! 135: orl %eax,%eax /* should it be counted? */ ;\
! 136: jz 5f /* no, skip it */ ;\
! 137: addl $1,IH_COUNT(%ebx) /* count the intrs */ ;\
! 138: adcl $0,IH_COUNT+4(%ebx) ;\
! 139: 5: movl IH_NEXT(%ebx),%ebx /* next handler in chain */ ;\
! 140: testl %ebx,%ebx ;\
! 141: jnz 7b ;\
! 142: UNLOCK_KERNEL(IF_PPL(%esp)) ;\
! 143: STRAY_TEST(name,num) /* see if it's a stray */ ;\
! 144: 6: unmask(num) /* unmask it in hardware */ ;\
! 145: late_ack(num) ;\
! 146: jmp _C_LABEL(Xdoreti) /* lower spl and do ASTs */ ;\
! 147: IDTVEC(stray_/**/name/**/num) ;\
! 148: pushl $num ;\
! 149: call _C_LABEL(isa_strayintr) ;\
! 150: addl $4,%esp ;\
! 151: jmp 6b ;\
! 152: IDTVEC(hold_/**/name/**/num) ;\
! 153: orb $IRQ_BIT(num),_C_LABEL(ipending) + IRQ_BYTE(num) ;\
! 154: INTRFASTEXIT
! 155:
! 156: #if defined(DEBUG)
! 157: #define STRAY_INITIALIZE \
! 158: xorl %esi,%esi
! 159: #define STRAY_INTEGRATE \
! 160: orl %eax,%esi
! 161: #define STRAY_TEST(name,num) \
! 162: testl %esi,%esi ;\
! 163: jz _C_LABEL(Xstray_/**/name/**/num)
! 164: #else /* !DEBUG */
! 165: #define STRAY_INITIALIZE
! 166: #define STRAY_INTEGRATE
! 167: #define STRAY_TEST(name,num)
! 168: #endif /* DEBUG */
! 169:
! 170: #ifdef DDB
! 171: #define MAKE_FRAME \
! 172: leal -8(%esp),%ebp
! 173: #else /* !DDB */
! 174: #define MAKE_FRAME
! 175: #endif /* DDB */
! 176:
! 177: #define ICUADDR IO_ICU1
! 178:
! 179: INTRSTUB(legacy,0, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
! 180: voidop)
! 181: INTRSTUB(legacy,1, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
! 182: voidop)
! 183: INTRSTUB(legacy,2, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
! 184: voidop)
! 185: INTRSTUB(legacy,3, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
! 186: voidop)
! 187: INTRSTUB(legacy,4, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
! 188: voidop)
! 189: INTRSTUB(legacy,5, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
! 190: voidop)
! 191: INTRSTUB(legacy,6, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
! 192: voidop)
! 193: INTRSTUB(legacy,7, i8259_asm_ack1, voidop, i8259_asm_mask, i8259_asm_unmask,
! 194: voidop)
! 195:
! 196: #undef ICUADDR
! 197: #define ICUADDR IO_ICU2
! 198:
! 199: INTRSTUB(legacy,8, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
! 200: voidop)
! 201: INTRSTUB(legacy,9, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
! 202: voidop)
! 203: INTRSTUB(legacy,10, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
! 204: voidop)
! 205: INTRSTUB(legacy,11, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
! 206: voidop)
! 207: INTRSTUB(legacy,12, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
! 208: voidop)
! 209: INTRSTUB(legacy,13, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
! 210: voidop)
! 211: INTRSTUB(legacy,14, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
! 212: voidop)
! 213: INTRSTUB(legacy,15, i8259_asm_ack2, voidop, i8259_asm_mask, i8259_asm_unmask,
! 214: voidop)
! 215:
! 216: /*
! 217: * These tables are used by the ISA configuration code.
! 218: */
! 219: /* interrupt service routine entry points */
! 220: IDTVEC(intr)
! 221: .long _C_LABEL(Xintr_legacy0), _C_LABEL(Xintr_legacy1)
! 222: .long _C_LABEL(Xintr_legacy2), _C_LABEL(Xintr_legacy3)
! 223: .long _C_LABEL(Xintr_legacy4), _C_LABEL(Xintr_legacy5)
! 224: .long _C_LABEL(Xintr_legacy6), _C_LABEL(Xintr_legacy7)
! 225: .long _C_LABEL(Xintr_legacy8), _C_LABEL(Xintr_legacy9)
! 226: .long _C_LABEL(Xintr_legacy10), _C_LABEL(Xintr_legacy11)
! 227: .long _C_LABEL(Xintr_legacy12), _C_LABEL(Xintr_legacy13)
! 228: .long _C_LABEL(Xintr_legacy14), _C_LABEL(Xintr_legacy15)
! 229:
! 230: /*
! 231: * These tables are used by Xdoreti() and Xspllower().
! 232: */
! 233: /* resume points for suspended interrupts */
! 234: IDTVEC(resume)
! 235: .long _C_LABEL(Xresume_legacy0), _C_LABEL(Xresume_legacy1)
! 236: .long _C_LABEL(Xresume_legacy2), _C_LABEL(Xresume_legacy3)
! 237: .long _C_LABEL(Xresume_legacy4), _C_LABEL(Xresume_legacy5)
! 238: .long _C_LABEL(Xresume_legacy6), _C_LABEL(Xresume_legacy7)
! 239: .long _C_LABEL(Xresume_legacy8), _C_LABEL(Xresume_legacy9)
! 240: .long _C_LABEL(Xresume_legacy10), _C_LABEL(Xresume_legacy11)
! 241: .long _C_LABEL(Xresume_legacy12), _C_LABEL(Xresume_legacy13)
! 242: .long _C_LABEL(Xresume_legacy14), _C_LABEL(Xresume_legacy15)
! 243: /* for soft interrupts */
! 244: .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
! 245: .long _C_LABEL(Xsoftast), _C_LABEL(Xsofttty)
! 246: .long _C_LABEL(Xsoftnet), _C_LABEL(Xsoftclock)
! 247: .long 0, 0
! 248: /* fake interrupts to resume from splx() */
! 249: IDTVEC(recurse)
! 250: .long _C_LABEL(Xrecurse_legacy0), _C_LABEL(Xrecurse_legacy1)
! 251: .long _C_LABEL(Xrecurse_legacy2), _C_LABEL(Xrecurse_legacy3)
! 252: .long _C_LABEL(Xrecurse_legacy4), _C_LABEL(Xrecurse_legacy5)
! 253: .long _C_LABEL(Xrecurse_legacy6), _C_LABEL(Xrecurse_legacy7)
! 254: .long _C_LABEL(Xrecurse_legacy8), _C_LABEL(Xrecurse_legacy9)
! 255: .long _C_LABEL(Xrecurse_legacy10), _C_LABEL(Xrecurse_legacy11)
! 256: .long _C_LABEL(Xrecurse_legacy12), _C_LABEL(Xrecurse_legacy13)
! 257: .long _C_LABEL(Xrecurse_legacy14), _C_LABEL(Xrecurse_legacy15)
! 258: /* for soft interrupts */
! 259: .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
! 260: .long _C_LABEL(Xsoftast), _C_LABEL(Xsofttty)
! 261: .long _C_LABEL(Xsoftnet), _C_LABEL(Xsoftclock)
! 262: .long 0, 0
CVSweb