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