Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / i386 / isa / ipl.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  *      @(#)ipl.s
38  *
39  * $FreeBSD: src/sys/i386/isa/ipl.s,v 1.32.2.3 2002/05/16 16:03:56 bde Exp $
40  * $DragonFly: src/sys/i386/isa/Attic/ipl.s,v 1.2 2003/06/17 04:28:37 dillon Exp $
41  */
42
43
44 /*
45  * AT/386
46  * Vector interrupt control section
47  *
48  *  cpl         - Current interrupt disable mask
49  *  *_imask     - Interrupt masks for various spl*() functions
50  *  ipending    - Pending interrupts (set when a masked interrupt occurs)
51  */
52
53         .data
54         ALIGN_DATA
55
56 /* current priority (all off) */
57         .globl  _cpl
58 _cpl:   .long   HWI_MASK | SWI_MASK
59
60         .globl  _tty_imask
61 _tty_imask:     .long   SWI_TTY_MASK
62         .globl  _bio_imask
63 _bio_imask:     .long   SWI_CLOCK_MASK | SWI_CAMBIO_MASK
64         .globl  _net_imask
65 _net_imask:     .long   SWI_NET_MASK | SWI_CAMNET_MASK
66         .globl  _cam_imask
67 _cam_imask:     .long   SWI_CAMBIO_MASK | SWI_CAMNET_MASK
68         .globl  _soft_imask
69 _soft_imask:    .long   SWI_MASK
70         .globl  _softnet_imask
71 _softnet_imask: .long   SWI_NET_MASK
72         .globl  _softtty_imask
73 _softtty_imask: .long   SWI_TTY_MASK
74
75 /* pending interrupts blocked by splxxx() */
76         .globl  _ipending
77 _ipending:      .long   0
78
79 /* set with bits for which queue to service */
80         .globl  _netisr
81 _netisr:        .long   0
82
83         .globl _netisrs
84 _netisrs:
85         .long   dummynetisr, dummynetisr, dummynetisr, dummynetisr
86         .long   dummynetisr, dummynetisr, dummynetisr, dummynetisr
87         .long   dummynetisr, dummynetisr, dummynetisr, dummynetisr
88         .long   dummynetisr, dummynetisr, dummynetisr, dummynetisr
89         .long   dummynetisr, dummynetisr, dummynetisr, dummynetisr
90         .long   dummynetisr, dummynetisr, dummynetisr, dummynetisr
91         .long   dummynetisr, dummynetisr, dummynetisr, dummynetisr
92         .long   dummynetisr, dummynetisr, dummynetisr, dummynetisr
93
94         .text
95
96 /*
97  * Handle return from interrupts, traps and syscalls.
98  */
99         SUPERALIGN_TEXT
100         .type   _doreti,@function
101 _doreti:
102         FAKE_MCOUNT(_bintr)             /* init "from" _bintr -> _doreti */
103         addl    $4,%esp                 /* discard unit number */
104         popl    %eax                    /* cpl or cml to restore */
105 doreti_next:
106         /*
107          * Check for pending HWIs and SWIs atomically with restoring cpl
108          * and exiting.  The check has to be atomic with exiting to stop
109          * (ipending & ~cpl) changing from zero to nonzero while we're
110          * looking at it (this wouldn't be fatal but it would increase
111          * interrupt latency).  Restoring cpl has to be atomic with exiting
112          * so that the stack cannot pile up (the nesting level of interrupt
113          * handlers is limited by the number of bits in cpl).
114          */
115 #ifdef SMP
116         cli                             /* early to prevent INT deadlock */
117 doreti_next2:
118 #endif
119         movl    %eax,%ecx
120         notl    %ecx                    /* set bit = unmasked level */
121 #ifndef SMP
122         cli
123 #endif
124         andl    _ipending,%ecx          /* set bit = unmasked pending INT */
125         jne     doreti_unpend
126         movl    %eax,_cpl
127         decb    _intr_nesting_level
128
129         /* Check for ASTs that can be handled now. */
130         testl   $AST_PENDING,_astpending
131         je      doreti_exit
132         testl   $PSL_VM,TF_EFLAGS(%esp)
133         jz      doreti_notvm86
134         cmpl    $1,_in_vm86call
135         jne     doreti_ast
136         jmp     doreti_exit     
137
138 doreti_notvm86:
139         testb   $SEL_RPL_MASK,TF_CS(%esp)
140         jnz     doreti_ast
141
142         /*
143          * doreti_exit -        release MP lock, pop registers, iret.
144          *
145          *      Note that the syscall trap shotcuts to doreti_syscall_ret.
146          *      The segment register pop is a special case, since it may
147          *      fault if (for example) a sigreturn specifies bad segment
148          *      registers.  The fault is handled in trap.c
149          */
150
151 doreti_exit:
152         MEXITCOUNT
153
154 #ifdef SMP
155         /* release the kernel lock */
156         movl    $_mp_lock, %edx         /* GIANT_LOCK */
157         call    _MPrellock_edx
158 #endif /* SMP */
159
160         .globl  doreti_popl_fs
161         .globl  doreti_syscall_ret
162 doreti_syscall_ret:
163 doreti_popl_fs:
164         popl    %fs
165         .globl  doreti_popl_es
166 doreti_popl_es:
167         popl    %es
168         .globl  doreti_popl_ds
169 doreti_popl_ds:
170         popl    %ds
171         popal
172         addl    $8,%esp
173         .globl  doreti_iret
174 doreti_iret:
175         iret
176
177         ALIGN_TEXT
178         .globl  doreti_iret_fault
179 doreti_iret_fault:
180         subl    $8,%esp
181         pushal
182         pushl   %ds
183         .globl  doreti_popl_ds_fault
184 doreti_popl_ds_fault:
185         pushl   %es
186         .globl  doreti_popl_es_fault
187 doreti_popl_es_fault:
188         pushl   %fs
189         .globl  doreti_popl_fs_fault
190 doreti_popl_fs_fault:
191         movl    $0,TF_ERR(%esp) /* XXX should be the error code */
192         movl    $T_PROTFLT,TF_TRAPNO(%esp)
193         jmp     alltraps_with_regs_pushed
194
195         ALIGN_TEXT
196 doreti_unpend:
197         /*
198          * Enabling interrupts is safe because we haven't restored cpl yet.
199          * %ecx contains the next probable ready interrupt (~cpl & ipending)
200          */
201 #ifdef SMP
202         bsfl    %ecx, %ecx              /* locate the next dispatchable int */
203         lock
204         btrl    %ecx, _ipending         /* is it really still pending? */
205         jnc     doreti_next2            /* some intr cleared memory copy */
206         sti                             /* late to prevent INT deadlock */
207 #else
208         sti
209         bsfl    %ecx,%ecx               /* slow, but not worth optimizing */
210         btrl    %ecx,_ipending
211         jnc     doreti_next             /* some intr cleared memory copy */
212 #endif /* SMP */
213         /*
214          * Execute handleable interrupt
215          *
216          * Set up JUMP to _ihandlers[%ecx] for HWIs.
217          * Set up CALL of _ihandlers[%ecx] for SWIs.
218          * This is a bit early for the SMP case - we have to push %ecx and
219          * %edx, but could push only %ecx and load %edx later.
220          */
221         movl    _ihandlers(,%ecx,4),%edx
222         cmpl    $NHWI,%ecx
223         jae     doreti_swi              /* software interrupt handling */
224         cli                             /* else hardware int handling */
225 #ifdef SMP
226         movl    %eax,_cpl               /* same as non-smp case right now */
227 #else
228         movl    %eax,_cpl
229 #endif
230         MEXITCOUNT
231 #ifdef APIC_INTR_DIAGNOSTIC
232         lock
233         incl    CNAME(apic_itrace_doreti)(,%ecx,4)
234 #ifdef APIC_INTR_DIAGNOSTIC_IRQ 
235         cmpl    $APIC_INTR_DIAGNOSTIC_IRQ,%ecx
236         jne     9f
237         pushl   %eax
238         pushl   %ecx
239         pushl   %edx
240         pushl   $APIC_ITRACE_DORETI
241         call    log_intr_event
242         addl    $4,%esp
243         popl    %edx
244         popl    %ecx
245         popl    %eax
246 9:      
247 #endif
248 #endif
249         jmp     *%edx
250
251         ALIGN_TEXT
252 doreti_swi:
253         pushl   %eax
254         /*
255          * At least the SWI_CLOCK handler has to run at a possibly strictly
256          * lower cpl, so we have to restore
257          * all the h/w bits in cpl now and have to worry about stack growth.
258          * The worst case is currently (30 Jan 1994) 2 SWI handlers nested
259          * in dying interrupt frames and about 12 HWIs nested in active
260          * interrupt frames.  There are only 4 different SWIs and the HWI
261          * and SWI masks limit the nesting further.
262          *
263          * The SMP case is currently the same as the non-SMP case.
264          */
265 #ifdef SMP
266         orl     imasks(,%ecx,4), %eax   /* or in imasks */
267         movl    %eax,_cpl               /* set cpl for call */
268 #else
269         orl     imasks(,%ecx,4),%eax
270         movl    %eax,_cpl
271 #endif
272         call    *%edx
273         popl    %eax                    /* cpl to restore */
274         jmp     doreti_next
275
276         ALIGN_TEXT
277 doreti_ast:
278         andl    $~AST_PENDING,_astpending
279         sti
280         movl    $T_ASTFLT,TF_TRAPNO(%esp)
281         call    _trap
282         subl    %eax,%eax               /* recover cpl|cml */
283         movb    $1,_intr_nesting_level  /* for doreti_next to decrement */
284         jmp     doreti_next
285
286         ALIGN_TEXT
287 swi_net:
288         MCOUNT
289         bsfl    _netisr,%eax
290         je      swi_net_done
291 swi_net_more:
292         btrl    %eax,_netisr
293         jnc     swi_net_next
294         call    *_netisrs(,%eax,4)
295 swi_net_next:
296         bsfl    _netisr,%eax
297         jne     swi_net_more
298 swi_net_done:
299         ret
300
301         ALIGN_TEXT
302 dummynetisr:
303         MCOUNT
304         ret     
305
306 /*
307  * The arg is in a nonstandard place, so swi_dispatcher() can't be called
308  * directly and swi_generic() can't use ENTRY() or MCOUNT.
309  */
310         ALIGN_TEXT
311         .globl  _swi_generic
312         .type   _swi_generic,@function
313 _swi_generic:
314         pushl   %ecx
315         FAKE_MCOUNT(4(%esp))
316         call    _swi_dispatcher
317         popl    %ecx
318         ret
319
320 ENTRY(swi_null)
321         ret
322
323 #ifdef APIC_IO
324 #include "i386/isa/apic_ipl.s"
325 #else
326 #include "i386/isa/icu_ipl.s"
327 #endif /* APIC_IO */