FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/icu.s
1 /*-
2 * Copyright (c) 1989, 1990 William F. Jolitz.
3 * Copyright (c) 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * William Jolitz.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)icu.s 7.2 (Berkeley) 5/21/91
38 *
39 * $FreeBSD: src/sys/i386/isa/icu.s,v 1.26.2.4 1999/09/05 08:12:40 peter Exp $
40 */
41
42 /*
43 * AT/386
44 * Vector interrupt control section
45 */
46
47 /*
48 * XXX this file should be named ipl.s. All spls are now soft and the
49 * only thing related to the hardware icu is that the h/w interrupt
50 * numbers are used without translation in the masks.
51 */
52
53 .data
54 .globl _cpl
55 _cpl: .long HWI_MASK | SWI_MASK /* current priority (all off) */
56 .globl _imen
57 _imen: .long HWI_MASK /* interrupt mask enable (all h/w off) */
58 .globl _tty_imask
59 _tty_imask: .long 0
60 .globl _bio_imask
61 _bio_imask: .long SWI_CAMBIO_MASK
62 .globl _cam_imask
63 _cam_imask: .long SWI_CAMBIO_MASK | SWI_CAMNET_MASK
64 .globl _net_imask
65 _net_imask: .long SWI_CAMNET_MASK
66 .globl _ipending
67 _ipending: .long 0
68 .globl _netisr
69 _netisr: .long 0 /* set with bits for which queue to service */
70 .globl _netisrs
71 _netisrs:
72 .long dummynetisr, dummynetisr, dummynetisr, dummynetisr
73 .long dummynetisr, dummynetisr, dummynetisr, dummynetisr
74 .long dummynetisr, dummynetisr, dummynetisr, dummynetisr
75 .long dummynetisr, dummynetisr, dummynetisr, dummynetisr
76 .long dummynetisr, dummynetisr, dummynetisr, dummynetisr
77 .long dummynetisr, dummynetisr, dummynetisr, dummynetisr
78 .long dummynetisr, dummynetisr, dummynetisr, dummynetisr
79 .long dummynetisr, dummynetisr, dummynetisr, dummynetisr
80 vec:
81 .long vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7
82 .long vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15
83
84 .text
85
86 /*
87 * Handle return from interrupts, traps and syscalls.
88 */
89 SUPERALIGN_TEXT
90 _doreti:
91 FAKE_MCOUNT(_bintr) /* init "from" _bintr -> _doreti */
92 addl $4,%esp /* discard unit number */
93 popl %eax /* cpl to restore */
94 doreti_next:
95 /*
96 * Check for pending HWIs and SWIs atomically with restoring cpl
97 * and exiting. The check has to be atomic with exiting to stop
98 * (ipending & ~cpl) changing from zero to nonzero while we're
99 * looking at it (this wouldn't be fatal but it would increase
100 * interrupt latency). Restoring cpl has to be atomic with exiting
101 * so that the stack cannot pile up (the nesting level of interrupt
102 * handlers is limited by the number of bits in cpl).
103 */
104 movl %eax,%ecx
105 notl %ecx
106 cli
107 andl _ipending,%ecx
108 jne doreti_unpend
109 doreti_exit:
110 movl %eax,_cpl
111 decb _intr_nesting_level
112 MEXITCOUNT
113 .globl doreti_popl_es
114 doreti_popl_es:
115 popl %es
116 .globl doreti_popl_ds
117 doreti_popl_ds:
118 popl %ds
119 popal
120 addl $8,%esp
121 .globl doreti_iret
122 doreti_iret:
123 iret
124
125 ALIGN_TEXT
126 .globl doreti_iret_fault
127 doreti_iret_fault:
128 subl $8,%esp
129 pushal
130 pushl %ds
131 .globl doreti_popl_ds_fault
132 doreti_popl_ds_fault:
133 pushl %es
134 .globl doreti_popl_es_fault
135 doreti_popl_es_fault:
136 movl $0,4+4+32+4(%esp) /* XXX should be the error code */
137 movl $T_PROTFLT,4+4+32+0(%esp)
138 jmp alltraps_with_regs_pushed
139
140 ALIGN_TEXT
141 doreti_unpend:
142 /*
143 * Enabling interrupts is safe because we haven't restored cpl yet.
144 * The locking from the "btrl" test is probably no longer necessary.
145 * We won't miss any new pending interrupts because we will check
146 * for them again.
147 */
148 sti
149 bsfl %ecx,%ecx /* slow, but not worth optimizing */
150 btrl %ecx,_ipending
151 jnc doreti_next /* some intr cleared memory copy */
152 movl ihandlers(,%ecx,4),%edx
153 testl %edx,%edx
154 je doreti_next /* "can't happen" */
155 cmpl $NHWI,%ecx
156 jae doreti_swi
157 cli
158 movl %eax,_cpl
159 MEXITCOUNT
160 jmp %edx
161
162 ALIGN_TEXT
163 doreti_swi:
164 pushl %eax
165 /*
166 * The SWI_AST handler has to run at cpl = SWI_AST_MASK and the
167 * SWI_CLOCK handler at cpl = SWI_CLOCK_MASK, so we have to restore
168 * all the h/w bits in cpl now and have to worry about stack growth.
169 * The worst case is currently (30 Jan 1994) 2 SWI handlers nested
170 * in dying interrupt frames and about 12 HWIs nested in active
171 * interrupt frames. There are only 4 different SWIs and the HWI
172 * and SWI masks limit the nesting further.
173 */
174 orl imasks(,%ecx,4),%eax
175 movl %eax,_cpl
176 call %edx
177 popl %eax
178 jmp doreti_next
179
180 ALIGN_TEXT
181 swi_ast:
182 addl $8,%esp /* discard raddr & cpl to get trap frame */
183 testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp)
184 je swi_ast_phantom
185 movl $T_ASTFLT,(2+8+0)*4(%esp)
186 movb $0,_intr_nesting_level /* finish becoming a trap handler */
187 call _trap
188 subl %eax,%eax /* recover cpl */
189 movb $1,_intr_nesting_level /* for doreti_next to decrement */
190 jmp doreti_next
191
192 ALIGN_TEXT
193 swi_ast_phantom:
194 /*
195 * These happen when there is an interrupt in a trap handler before
196 * ASTs can be masked or in an lcall handler before they can be
197 * masked or after they are unmasked. They could be avoided for
198 * trap entries by using interrupt gates, and for lcall exits by
199 * using by using cli, but they are unavoidable for lcall entries.
200 */
201 cli
202 orl $SWI_AST_PENDING,_ipending
203 subl %eax,%eax
204 jmp doreti_exit /* SWI_AST is highest so we must be done */
205
206 /*
207 * Interrupt priority mechanism
208 * -- soft splXX masks with group mechanism (cpl)
209 * -- h/w masks for currently active or unused interrupts (imen)
210 * -- ipending = active interrupts currently masked by cpl
211 */
212
213 ENTRY(splz)
214 /*
215 * The caller has restored cpl and checked that (ipending & ~cpl)
216 * is nonzero. We have to repeat the check since if there is an
217 * interrupt while we're looking, _doreti processing for the
218 * interrupt will handle all the unmasked pending interrupts
219 * because we restored early. We're repeating the calculation
220 * of (ipending & ~cpl) anyway so that the caller doesn't have
221 * to pass it, so this only costs one "jne". "bsfl %ecx,%ecx"
222 * is undefined when %ecx is 0 so we can't rely on the secondary
223 * btrl tests.
224 */
225 movl _cpl,%eax
226 splz_next:
227 /*
228 * We don't need any locking here. (ipending & ~cpl) cannot grow
229 * while we're looking at it - any interrupt will shrink it to 0.
230 */
231 movl %eax,%ecx
232 notl %ecx
233 andl _ipending,%ecx
234 jne splz_unpend
235 ret
236
237 ALIGN_TEXT
238 splz_unpend:
239 bsfl %ecx,%ecx
240 btrl %ecx,_ipending
241 jnc splz_next
242 movl ihandlers(,%ecx,4),%edx
243 testl %edx,%edx
244 je splz_next /* "can't happen" */
245 cmpl $NHWI,%ecx
246 jae splz_swi
247 /*
248 * We would prefer to call the intr handler directly here but that
249 * doesn't work for badly behaved handlers that want the interrupt
250 * frame. Also, there's a problem determining the unit number.
251 * We should change the interface so that the unit number is not
252 * determined at config time.
253 */
254 jmp *vec(,%ecx,4)
255
256 ALIGN_TEXT
257 splz_swi:
258 cmpl $SWI_AST,%ecx
259 je splz_next /* "can't happen" */
260 pushl %eax
261 orl imasks(,%ecx,4),%eax
262 movl %eax,_cpl
263 call %edx
264 popl %eax
265 movl %eax,_cpl
266 jmp splz_next
267
268 /*
269 * Fake clock interrupt(s) so that they appear to come from our caller instead
270 * of from here, so that system profiling works.
271 * XXX do this more generally (for all vectors; look up the C entry point).
272 * XXX frame bogusness stops us from just jumping to the C entry point.
273 */
274 ALIGN_TEXT
275 vec0:
276 popl %eax /* return address */
277 pushfl
278 #define KCSEL 8
279 pushl $KCSEL
280 pushl %eax
281 cli
282 MEXITCOUNT
283 jmp _Xintr0 /* XXX might need _Xfastintr0 */
284
285 #ifndef PC98
286 ALIGN_TEXT
287 vec8:
288 popl %eax
289 pushfl
290 pushl $KCSEL
291 pushl %eax
292 cli
293 MEXITCOUNT
294 jmp _Xintr8 /* XXX might need _Xfastintr8 */
295 #endif
296
297 #define BUILD_VEC(irq_num) \
298 ALIGN_TEXT ; \
299 __CONCAT(vec,irq_num): ; \
300 int $ICU_OFFSET + (irq_num) ; \
301 ret
302
303 BUILD_VEC(1)
304 BUILD_VEC(2)
305 BUILD_VEC(3)
306 BUILD_VEC(4)
307 BUILD_VEC(5)
308 BUILD_VEC(6)
309 BUILD_VEC(7)
310 #ifdef PC98
311 BUILD_VEC(8)
312 #endif
313 BUILD_VEC(9)
314 BUILD_VEC(10)
315 BUILD_VEC(11)
316 BUILD_VEC(12)
317 BUILD_VEC(13)
318 BUILD_VEC(14)
319 BUILD_VEC(15)
320
321 ALIGN_TEXT
322 swi_net:
323 MCOUNT
324 bsfl _netisr,%eax
325 je swi_net_done
326 swi_net_more:
327 btrl %eax,_netisr
328 jnc swi_net_next
329 call *_netisrs(,%eax,4)
330 swi_net_next:
331 bsfl _netisr,%eax
332 jne swi_net_more
333 swi_net_done:
334 ret
335
336 ALIGN_TEXT
337 dummynetisr:
338 MCOUNT
339 ret
340
341 ALIGN_TEXT
342 dummycamisr:
343 MCOUNT
344 ret
345
346 /*
347 * XXX there should be a registration function to put the handler for the
348 * attached driver directly in ihandlers. Then this function will go away.
349 */
350 ALIGN_TEXT
351 swi_tty:
352 MCOUNT
353 #include "cy.h"
354 #if NCY > 0
355 call _cypoll
356 #endif
357 #include "rc.h"
358 #if NRC > 0
359 call _rcpoll
360 #endif
361 #include "sio.h"
362 #if NSIO > 0
363 jmp _siopoll
364 #else
365 ret
366 #endif
Cache object: 5d9dd0a2ff5861053a8ea4ab0f49c616
|