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 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 4. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD: releng/6.0/sys/i386/i386/exception.s 148469 2005-07-28 03:30:53Z jkoshy $
31 */
32
33 #include "opt_apic.h"
34 #include "opt_npx.h"
35
36 #include <machine/asmacros.h>
37 #include <machine/psl.h>
38 #include <machine/trap.h>
39
40 #include "assym.s"
41
42 #define SEL_RPL_MASK 0x0003
43
44 .text
45
46 /*****************************************************************************/
47 /* Trap handling */
48 /*****************************************************************************/
49 /*
50 * Trap and fault vector routines.
51 *
52 * Most traps are 'trap gates', SDT_SYS386TGT. A trap gate pushes state on
53 * the stack that mostly looks like an interrupt, but does not disable
54 * interrupts. A few of the traps we are use are interrupt gates,
55 * SDT_SYS386IGT, which are nearly the same thing except interrupts are
56 * disabled on entry.
57 *
58 * The cpu will push a certain amount of state onto the kernel stack for
59 * the current process. The amount of state depends on the type of trap
60 * and whether the trap crossed rings or not. See i386/include/frame.h.
61 * At the very least the current EFLAGS (status register, which includes
62 * the interrupt disable state prior to the trap), the code segment register,
63 * and the return instruction pointer are pushed by the cpu. The cpu
64 * will also push an 'error' code for certain traps. We push a dummy
65 * error code for those traps where the cpu doesn't in order to maintain
66 * a consistent frame. We also push a contrived 'trap number'.
67 *
68 * The cpu does not push the general registers, we must do that, and we
69 * must restore them prior to calling 'iret'. The cpu adjusts the %cs and
70 * %ss segment registers, but does not mess with %ds, %es, or %fs. Thus we
71 * must load them with appropriate values for supervisor mode operation.
72 */
73
74 MCOUNT_LABEL(user)
75 MCOUNT_LABEL(btrap)
76
77 IDTVEC(div)
78 pushl $0; TRAP(T_DIVIDE)
79 IDTVEC(dbg)
80 pushl $0; TRAP(T_TRCTRAP)
81 IDTVEC(nmi)
82 pushl $0; TRAP(T_NMI)
83 IDTVEC(bpt)
84 pushl $0; TRAP(T_BPTFLT)
85 IDTVEC(ofl)
86 pushl $0; TRAP(T_OFLOW)
87 IDTVEC(bnd)
88 pushl $0; TRAP(T_BOUND)
89 IDTVEC(ill)
90 pushl $0; TRAP(T_PRIVINFLT)
91 IDTVEC(dna)
92 pushl $0; TRAP(T_DNA)
93 IDTVEC(fpusegm)
94 pushl $0; TRAP(T_FPOPFLT)
95 IDTVEC(tss)
96 TRAP(T_TSSFLT)
97 IDTVEC(missing)
98 TRAP(T_SEGNPFLT)
99 IDTVEC(stk)
100 TRAP(T_STKFLT)
101 IDTVEC(prot)
102 TRAP(T_PROTFLT)
103 IDTVEC(page)
104 TRAP(T_PAGEFLT)
105 IDTVEC(mchk)
106 pushl $0; TRAP(T_MCHK)
107 IDTVEC(rsvd)
108 pushl $0; TRAP(T_RESERVED)
109 IDTVEC(fpu)
110 pushl $0; TRAP(T_ARITHTRAP)
111 IDTVEC(align)
112 TRAP(T_ALIGNFLT)
113 IDTVEC(xmm)
114 pushl $0; TRAP(T_XMMFLT)
115
116 /*
117 * alltraps entry point. Interrupts are enabled if this was a trap
118 * gate (TGT), else disabled if this was an interrupt gate (IGT).
119 * Note that int0x80_syscall is a trap gate. Only page faults
120 * use an interrupt gate.
121 */
122
123 SUPERALIGN_TEXT
124 .globl alltraps
125 .type alltraps,@function
126 alltraps:
127 pushal
128 pushl %ds
129 pushl %es
130 pushl %fs
131 alltraps_with_regs_pushed:
132 movl $KDSEL,%eax
133 movl %eax,%ds
134 movl %eax,%es
135 movl $KPSEL,%eax
136 movl %eax,%fs
137 FAKE_MCOUNT(TF_EIP(%esp))
138 calltrap:
139 call trap
140
141 /*
142 * Return via doreti to handle ASTs.
143 */
144 MEXITCOUNT
145 jmp doreti
146
147 /*
148 * SYSCALL CALL GATE (old entry point for a.out binaries)
149 *
150 * The intersegment call has been set up to specify one dummy parameter.
151 *
152 * This leaves a place to put eflags so that the call frame can be
153 * converted to a trap frame. Note that the eflags is (semi-)bogusly
154 * pushed into (what will be) tf_err and then copied later into the
155 * final spot. It has to be done this way because esp can't be just
156 * temporarily altered for the pushfl - an interrupt might come in
157 * and clobber the saved cs/eip.
158 */
159 SUPERALIGN_TEXT
160 IDTVEC(lcall_syscall)
161 pushfl /* save eflags */
162 popl 8(%esp) /* shuffle into tf_eflags */
163 pushl $7 /* sizeof "lcall 7,0" */
164 subl $4,%esp /* skip over tf_trapno */
165 pushal
166 pushl %ds
167 pushl %es
168 pushl %fs
169 movl $KDSEL,%eax /* switch to kernel segments */
170 movl %eax,%ds
171 movl %eax,%es
172 movl $KPSEL,%eax
173 movl %eax,%fs
174 FAKE_MCOUNT(TF_EIP(%esp))
175 call syscall
176 MEXITCOUNT
177 jmp doreti
178
179 /*
180 * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
181 *
182 * Even though the name says 'int0x80', this is actually a TGT (trap gate)
183 * rather then an IGT (interrupt gate). Thus interrupts are enabled on
184 * entry just as they are for a normal syscall.
185 */
186 SUPERALIGN_TEXT
187 IDTVEC(int0x80_syscall)
188 pushl $2 /* sizeof "int 0x80" */
189 subl $4,%esp /* skip over tf_trapno */
190 pushal
191 pushl %ds
192 pushl %es
193 pushl %fs
194 movl $KDSEL,%eax /* switch to kernel segments */
195 movl %eax,%ds
196 movl %eax,%es
197 movl $KPSEL,%eax
198 movl %eax,%fs
199 FAKE_MCOUNT(TF_EIP(%esp))
200 call syscall
201 MEXITCOUNT
202 jmp doreti
203
204 ENTRY(fork_trampoline)
205 pushl %esp /* trapframe pointer */
206 pushl %ebx /* arg1 */
207 pushl %esi /* function */
208 call fork_exit
209 addl $12,%esp
210 /* cut from syscall */
211
212 /*
213 * Return via doreti to handle ASTs.
214 */
215 MEXITCOUNT
216 jmp doreti
217
218
219 /*
220 * To efficiently implement classification of trap and interrupt handlers
221 * for profiling, there must be only trap handlers between the labels btrap
222 * and bintr, and only interrupt handlers between the labels bintr and
223 * eintr. This is implemented (partly) by including files that contain
224 * some of the handlers. Before including the files, set up a normal asm
225 * environment so that the included files doen't need to know that they are
226 * included.
227 */
228
229 .data
230 .p2align 4
231 .text
232 SUPERALIGN_TEXT
233 MCOUNT_LABEL(bintr)
234
235 #include <i386/isa/atpic_vector.s>
236
237 #ifdef DEV_APIC
238 .data
239 .p2align 4
240 .text
241 SUPERALIGN_TEXT
242
243 #include <i386/i386/apic_vector.s>
244 #endif
245
246 .data
247 .p2align 4
248 .text
249 SUPERALIGN_TEXT
250 #include <i386/i386/vm86bios.s>
251
252 .text
253 MCOUNT_LABEL(eintr)
254
255 /*
256 * void doreti(struct trapframe)
257 *
258 * Handle return from interrupts, traps and syscalls.
259 */
260 .text
261 SUPERALIGN_TEXT
262 .type doreti,@function
263 doreti:
264 FAKE_MCOUNT($bintr) /* init "from" bintr -> doreti */
265 doreti_next:
266 /*
267 * Check if ASTs can be handled now. PSL_VM must be checked first
268 * since segment registers only have an RPL in non-VM86 mode.
269 */
270 testl $PSL_VM,TF_EFLAGS(%esp) /* are we in vm86 mode? */
271 jz doreti_notvm86
272 movl PCPU(CURPCB),%ecx
273 testl $PCB_VM86CALL,PCB_FLAGS(%ecx) /* are we in a vm86 call? */
274 jz doreti_ast /* can handle ASTS now if not */
275 jmp doreti_exit
276
277 doreti_notvm86:
278 testb $SEL_RPL_MASK,TF_CS(%esp) /* are we returning to user mode? */
279 jz doreti_exit /* can't handle ASTs now if not */
280
281 doreti_ast:
282 /*
283 * Check for ASTs atomically with returning. Disabling CPU
284 * interrupts provides sufficient locking even in the SMP case,
285 * since we will be informed of any new ASTs by an IPI.
286 */
287 cli
288 movl PCPU(CURTHREAD),%eax
289 testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%eax)
290 je doreti_exit
291 sti
292 pushl %esp /* pass a pointer to the trapframe */
293 call ast
294 add $4,%esp
295 jmp doreti_ast
296
297 /*
298 * doreti_exit: pop registers, iret.
299 *
300 * The segment register pop is a special case, since it may
301 * fault if (for example) a sigreturn specifies bad segment
302 * registers. The fault is handled in trap.c.
303 */
304 doreti_exit:
305 MEXITCOUNT
306
307 .globl doreti_popl_fs
308 doreti_popl_fs:
309 popl %fs
310 .globl doreti_popl_es
311 doreti_popl_es:
312 popl %es
313 .globl doreti_popl_ds
314 doreti_popl_ds:
315 popl %ds
316 popal
317 addl $8,%esp
318 .globl doreti_iret
319 doreti_iret:
320 iret
321
322 /*
323 * doreti_iret_fault and friends. Alternative return code for
324 * the case where we get a fault in the doreti_exit code
325 * above. trap() (i386/i386/trap.c) catches this specific
326 * case, sends the process a signal and continues in the
327 * corresponding place in the code below.
328 */
329 ALIGN_TEXT
330 .globl doreti_iret_fault
331 doreti_iret_fault:
332 subl $8,%esp
333 pushal
334 pushl %ds
335 .globl doreti_popl_ds_fault
336 doreti_popl_ds_fault:
337 pushl %es
338 .globl doreti_popl_es_fault
339 doreti_popl_es_fault:
340 pushl %fs
341 .globl doreti_popl_fs_fault
342 doreti_popl_fs_fault:
343 movl $0,TF_ERR(%esp) /* XXX should be the error code */
344 movl $T_PROTFLT,TF_TRAPNO(%esp)
345 jmp alltraps_with_regs_pushed
Cache object: 332cd675e5264b8d9cfd9c62bd069055
|