4443de04e31785a0eea7cf2cfcee126c2e06f9db
[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.6 2003/07/01 20:31:38 dillon Exp $
41  */
42
43
44 /*
45  * AT/386
46  * Vector interrupt control section
47  *
48  *  *_imask     - Interrupt masks for various spl*() functions
49  *  ipending    - Pending interrupts (set when a masked interrupt occurs)
50  */
51
52         .data
53         ALIGN_DATA
54
55 /* current priority (all off) */
56
57         .globl  tty_imask
58 tty_imask:      .long   SWI_TTY_MASK
59         .globl  bio_imask
60 bio_imask:      .long   SWI_CLOCK_MASK | SWI_CAMBIO_MASK
61         .globl  net_imask
62 net_imask:      .long   SWI_NET_MASK | SWI_CAMNET_MASK
63         .globl  cam_imask
64 cam_imask:      .long   SWI_CAMBIO_MASK | SWI_CAMNET_MASK
65         .globl  soft_imask
66 soft_imask:     .long   SWI_MASK
67         .globl  softnet_imask
68 softnet_imask:  .long   SWI_NET_MASK
69         .globl  softtty_imask
70 softtty_imask:  .long   SWI_TTY_MASK
71         .globl  last_splz
72 last_splz:      .long   0
73         .globl  last_splz2
74 last_splz2:     .long   0
75
76         .text
77
78         /*
79          * DORETI
80          *
81          * Handle return from interrupts, traps and syscalls.  This function
82          * checks the cpl for unmasked pending interrupts (fast, normal, or
83          * soft) and schedules them if appropriate, then irets.
84          */
85         SUPERALIGN_TEXT
86         .type   doreti,@function
87 doreti:
88         FAKE_MCOUNT(bintr)              /* init "from" bintr -> doreti */
89         popl    %eax                    /* cpl to restore */
90         movl    PCPU(curthread),%ebx
91         cli                             /* interlock with TDPRI_CRIT */
92         movl    %eax,TD_CPL(%ebx)       /* save cpl being restored */
93         cmpl    $TDPRI_CRIT,TD_PRI(%ebx) /* can't unpend if in critical sec */
94         jge     5f
95         addl    $TDPRI_CRIT,TD_PRI(%ebx) /* force all ints to pending */
96 doreti_next:
97         sti                             /* allow new interrupts */
98         movl    %eax,%ecx               /* cpl being restored */
99         notl    %ecx
100         cli                             /* disallow YYY remove */
101         testl   PCPU(fpending),%ecx     /* check for an unmasked fast int */
102         jne     doreti_fast
103
104         movl    PCPU(irunning),%edx     /* check for an unmasked normal int */
105         notl    %edx                    /* that isn't already running */
106         andl    %edx, %ecx
107         testl   PCPU(ipending),%ecx
108         jne     doreti_intr
109         testl   $AST_PENDING,PCPU(astpending) /* any pending ASTs? */
110         jz      2f
111         testl   $PSL_VM,TF_EFLAGS(%esp)
112         jz      1f
113         cmpl    $1,in_vm86call          /* YYY make per 'cpu' */
114         jnz     doreti_ast
115 1:
116         testb   $SEL_RPL_MASK,TF_CS(%esp)
117         jnz     doreti_ast
118
119         /*
120          * Nothing left to do, finish up.  Interrupts are still disabled.
121          */
122 2:
123         subl    $TDPRI_CRIT,TD_PRI(%ebx)        /* interlocked with cli */
124 5:
125         decl    PCPU(intr_nesting_level)
126         MEXITCOUNT
127         .globl  doreti_popl_fs
128         .globl  doreti_popl_es
129         .globl  doreti_popl_ds
130         .globl  doreti_iret
131         .globl  doreti_syscall_ret
132 doreti_syscall_ret:
133 doreti_popl_fs:
134         popl    %fs
135 doreti_popl_es:
136         popl    %es
137 doreti_popl_ds:
138         popl    %ds
139         popal
140         addl    $8,%esp
141 doreti_iret:
142         iret
143
144         ALIGN_TEXT
145         .globl  doreti_iret_fault
146 doreti_iret_fault:
147         subl    $8,%esp
148         pushal
149         pushl   %ds
150         .globl  doreti_popl_ds_fault
151 doreti_popl_ds_fault:
152         pushl   %es
153         .globl  doreti_popl_es_fault
154 doreti_popl_es_fault:
155         pushl   %fs
156         .globl  doreti_popl_fs_fault
157 doreti_popl_fs_fault:
158         movl    $0,TF_ERR(%esp) /* XXX should be the error code */
159         movl    $T_PROTFLT,TF_TRAPNO(%esp)
160         jmp     alltraps_with_regs_pushed
161
162         /*
163          * FAST interrupt pending
164          */
165         ALIGN_TEXT
166 doreti_fast:
167         andl    PCPU(fpending),%ecx     /* only check fast ints */
168         bsfl    %ecx, %ecx              /* locate the next dispatchable int */
169         btrl    %ecx, PCPU(fpending)    /* is it really still pending? */
170         jnc     doreti_next
171         pushl   %eax                    /* YYY cpl */
172         call    *fastunpend(,%ecx,4)
173         popl    %eax
174         jmp     doreti_next
175
176         /*
177          *  INTR interrupt pending
178          */
179         ALIGN_TEXT
180 doreti_intr:
181         andl    PCPU(ipending),%ecx     /* only check normal ints */
182         bsfl    %ecx, %ecx              /* locate the next dispatchable int */
183         btrl    %ecx, PCPU(ipending)    /* is it really still pending? */
184         jnc     doreti_next
185         pushl   %eax
186         pushl   %ecx
187         call    sched_ithd              /* YYY must pull in imasks */
188         addl    $4,%esp
189         popl    %eax
190         jmp     doreti_next
191
192         /*
193          * AST pending
194          */
195 doreti_ast:
196         andl    $~AST_PENDING,PCPU(astpending)
197         sti
198         movl    $T_ASTFLT,TF_TRAPNO(%esp)
199         decl    PCPU(intr_nesting_level)
200         call    trap
201         incl    PCPU(intr_nesting_level)
202         movl    TD_CPL(%ebx),%eax       /* retrieve cpl again for loop */
203         jmp     doreti_next
204
205
206         /*
207          * SPLZ() a C callable procedure to dispatch any unmasked pending
208          *        interrupts regardless of critical section nesting.  ASTs
209          *        are not dispatched.
210          *
211          *      YYY at the moment I leave us in a critical section so as
212          *      not to have to mess with the cpls which will soon be obsolete.
213          */
214         SUPERALIGN_TEXT
215
216 ENTRY(splz)
217         pushfl
218         pushl   %ebx
219         movl    PCPU(curthread),%ebx
220         movl    TD_CPL(%ebx),%eax
221         addl    $TDPRI_CRIT,TD_PRI(%ebx)
222
223 splz_next:
224         cli
225         movl    %eax,%ecx               /* ecx = ~CPL */
226         notl    %ecx
227         testl   PCPU(fpending),%ecx     /* check for an unmasked fast int */
228         jne     splz_fast
229
230         movl    PCPU(irunning),%edx     /* check for an unmasked normal int */
231         notl    %edx                    /* that isn't already running */
232         andl    %edx, %ecx
233         testl   PCPU(ipending),%ecx
234         jne     splz_intr
235
236         subl    $TDPRI_CRIT,TD_PRI(%ebx)
237         popl    %ebx
238         popfl
239         ret
240
241         /*
242          * FAST interrupt pending
243          */
244         ALIGN_TEXT
245 splz_fast:
246         andl    PCPU(fpending),%ecx     /* only check fast ints */
247         bsfl    %ecx, %ecx              /* locate the next dispatchable int */
248         btrl    %ecx, PCPU(fpending)    /* is it really still pending? */
249         jnc     splz_next
250         movl    $1,last_splz
251         movl    %ecx,last_splz2
252         pushl   %eax
253         call    *fastunpend(,%ecx,4)
254         popl    %eax
255         movl    $-1,last_splz
256         jmp     splz_next
257
258         /*
259          *  INTR interrupt pending
260          */
261         ALIGN_TEXT
262 splz_intr:
263         andl    PCPU(ipending),%ecx     /* only check normal ints */
264         bsfl    %ecx, %ecx              /* locate the next dispatchable int */
265         btrl    %ecx, PCPU(ipending)    /* is it really still pending? */
266         jnc     splz_next
267         sti
268         movl    $2,last_splz
269         pushl   %eax
270         pushl   %ecx
271         movl    %ecx,last_splz2
272         call    sched_ithd              /* YYY must pull in imasks */
273         addl    $4,%esp
274         popl    %eax
275         movl    $-2,last_splz
276         jmp     splz_next
277
278         /*
279          * APIC/ICU specific ipl functions provide masking and unmasking
280          * calls for userland.
281          */
282
283 #ifdef APIC_IO
284 #include "i386/isa/apic_ipl.s"
285 #else
286 #include "i386/isa/icu_ipl.s"
287 #endif /* APIC_IO */