Annotation of sys/arch/i386/i386/vector.s, Revision 1.1.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