Deleted Added
full compact
1/*-
2 * Copyright (c) 2004 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/ia64/ia32/ia32_trap.c 160798 2006-07-28 19:05:28Z jhb $");
28__FBSDID("$FreeBSD: head/sys/ia64/ia32/ia32_trap.c 160801 2006-07-28 20:22:58Z jhb $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/ktr.h>
33#include <sys/sysproto.h>
34#include <sys/kernel.h>
35#include <sys/lock.h>
36#include <sys/mutex.h>
37#include <sys/pioctl.h>
38#include <sys/proc.h>
39#include <sys/ptrace.h>
40#include <sys/signalvar.h>
41#include <sys/syscall.h>
42#include <sys/sysent.h>
43#include <machine/cpu.h>
44#include <machine/fpu.h>
45#include <machine/frame.h>
46#include <machine/md_var.h>
47#include <i386/include/psl.h>
48
49extern char *syscallnames[];
50
51static void
52ia32_syscall(struct trapframe *tf)
53{
54 uint64_t args64[8];
55 uint32_t args[8];
56 struct thread *td;
57 struct proc *p;
58 struct sysent *callp;
59 caddr_t params;
60 register_t eflags;
61 u_int code;
62 int error, i, narg;
63 ksiginfo_t ksi;
64
65 PCPU_LAZY_INC(cnt.v_syscall);
66
67 td = curthread;
68 params = (caddr_t)(tf->tf_special.sp & ((1L<<32)-1)) +
69 sizeof(uint32_t);
70 code = tf->tf_scratch.gr8; /* eax */
71 eflags = ia64_get_eflag();
72 p = td->td_proc;
73
74 if (p->p_sysent->sv_prepsyscall == NULL) {
75 if (code == SYS_syscall) {
76 /* Code is first argument, followed by actual args. */
77 code = fuword32(params);
78 params += sizeof(int);
79 } else if (code == SYS___syscall) {
80 /*
81 * Like syscall, but code is a quad, so as to maintain
82 * quad alignment for the rest of the arguments. We
83 * use a 32-bit fetch in case params is not aligned.
84 */
85 code = fuword32(params);
86 params += sizeof(quad_t);
87 }
88 } else
89 (*p->p_sysent->sv_prepsyscall)(tf, args, &code, &params);
90
91 if (p->p_sysent->sv_mask)
92 code &= p->p_sysent->sv_mask;
93
94 if (code >= p->p_sysent->sv_size)
95 callp = &p->p_sysent->sv_table[0];
96 else
97 callp = &p->p_sysent->sv_table[code];
98
99 narg = callp->sy_narg & SYF_ARGMASK;
99 narg = callp->sy_narg;
100
101 /* copyin and the ktrsyscall()/ktrsysret() code is MP-aware */
102 if (params != NULL && narg != 0)
103 error = copyin(params, (caddr_t)args, narg * sizeof(int));
104 else
105 error = 0;
106
107 for (i = 0; i < narg; i++)
108 args64[i] = args[i];
109
110#ifdef KTRACE
111 if (KTRPOINT(td, KTR_SYSCALL))
112 ktrsyscall(code, narg, args64);
113#endif
114 CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
115 td->td_proc->p_pid, td->td_proc->p_comm, code);
116
117 if (error == 0) {
118 td->td_retval[0] = 0;
119 td->td_retval[1] = tf->tf_scratch.gr10; /* edx */
120
121 STOPEVENT(p, S_SCE, narg);
122
123 PTRACESTOP_SC(p, td, S_PT_SCE);
124
125 error = (*callp->sy_call)(td, args64);
126 }
127
128 switch (error) {
129 case 0:
130 tf->tf_scratch.gr8 = td->td_retval[0]; /* eax */
131 tf->tf_scratch.gr10 = td->td_retval[1]; /* edx */
132 ia64_set_eflag(ia64_get_eflag() & ~PSL_C);
133 break;
134
135 case ERESTART:
136 /*
137 * Reconstruct pc, assuming lcall $X,y is 7 bytes,
138 * int 0x80 is 2 bytes. XXX Assume int 0x80.
139 */
140 tf->tf_special.iip -= 2;
141 break;
142
143 case EJUSTRETURN:
144 break;
145
146 default:
147 if (p->p_sysent->sv_errsize) {
148 if (error >= p->p_sysent->sv_errsize)
149 error = -1; /* XXX */
150 else
151 error = p->p_sysent->sv_errtbl[error];
152 }
153 tf->tf_scratch.gr8 = error;
154 ia64_set_eflag(ia64_get_eflag() | PSL_C);
155 break;
156 }
157
158 /*
159 * Traced syscall.
160 */
161 if ((eflags & PSL_T) && !(eflags & PSL_VM)) {
162 ia64_set_eflag(ia64_get_eflag() & ~PSL_T);
163 ksiginfo_init_trap(&ksi);
164 ksi.ksi_signo = SIGTRAP;
165 ksi.ksi_code = TRAP_TRACE;
166 ksi.ksi_addr = (void *)tf->tf_special.iip;
167 trapsignal(td, &ksi);
168 }
169
170 /*
171 * Check for misbehavior.
172 */
173 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
174 (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
175 KASSERT(td->td_critnest == 0,
176 ("System call %s returning in a critical section",
177 (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
178 KASSERT(td->td_locks == 0,
179 ("System call %s returning with %d locks held",
180 (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
181 td->td_locks));
182
183 /*
184 * End of syscall tracing.
185 */
186 CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
187 td->td_proc->p_pid, td->td_proc->p_comm, code);
188#ifdef KTRACE
189 if (KTRPOINT(td, KTR_SYSRET))
190 ktrsysret(code, error, td->td_retval[0]);
191#endif
192
193 /*
194 * This works because errno is findable through the
195 * register set. If we ever support an emulation where this
196 * is not the case, this code will need to be revisited.
197 */
198 STOPEVENT(p, S_SCX, code);
199
200 PTRACESTOP_SC(p, td, S_PT_SCX);
201}
202
203/*
204 * ia32_trap() is called from exception.S to handle the IA-32 specific
205 * interruption vectors.
206 */
207void
208ia32_trap(int vector, struct trapframe *tf)
209{
210 struct proc *p;
211 struct thread *td;
212 uint64_t ucode;
213 int sig;
214 ksiginfo_t ksi;
215
216 KASSERT(TRAPF_USERMODE(tf), ("%s: In kernel mode???", __func__));
217
218 ia64_set_fpsr(IA64_FPSR_DEFAULT);
219 PCPU_LAZY_INC(cnt.v_trap);
220
221 td = curthread;
222 td->td_frame = tf;
223 td->td_pticks = 0;
224 p = td->td_proc;
225 if (td->td_ucred != p->p_ucred)
226 cred_update_thread(td);
227 sig = 0;
228 ucode = 0;
229 switch (vector) {
230 case IA64_VEC_IA32_EXCEPTION:
231 switch ((tf->tf_special.isr >> 16) & 0xffff) {
232 case IA32_EXCEPTION_DIVIDE:
233 ucode = FPE_INTDIV;
234 sig = SIGFPE;
235 break;
236 case IA32_EXCEPTION_DEBUG:
237 case IA32_EXCEPTION_BREAK:
238 sig = SIGTRAP;
239 break;
240 case IA32_EXCEPTION_OVERFLOW:
241 ucode = FPE_INTOVF;
242 sig = SIGFPE;
243 break;
244 case IA32_EXCEPTION_BOUND:
245 ucode = FPE_FLTSUB;
246 sig = SIGFPE;
247 break;
248 case IA32_EXCEPTION_DNA:
249 ucode = 0;
250 sig = SIGFPE;
251 break;
252 case IA32_EXCEPTION_NOT_PRESENT:
253 case IA32_EXCEPTION_STACK_FAULT:
254 case IA32_EXCEPTION_GPFAULT:
255 ucode = (tf->tf_special.isr & 0xffff) + BUS_SEGM_FAULT;
256 sig = SIGBUS;
257 break;
258 case IA32_EXCEPTION_FPERROR:
259 ucode = 0; /* XXX */
260 sig = SIGFPE;
261 break;
262 case IA32_EXCEPTION_ALIGNMENT_CHECK:
263 ucode = tf->tf_special.ifa; /* VA */
264 sig = SIGBUS;
265 break;
266 case IA32_EXCEPTION_STREAMING_SIMD:
267 ucode = 0; /* XXX */
268 sig = SIGFPE;
269 break;
270 default:
271 trap_panic(vector, tf);
272 break;
273 }
274 break;
275
276 case IA64_VEC_IA32_INTERCEPT:
277 /* XXX Maybe need to emulate ia32 instruction. */
278 trap_panic(vector, tf);
279
280 case IA64_VEC_IA32_INTERRUPT:
281 /* INT n instruction - probably a syscall. */
282 if (((tf->tf_special.isr >> 16) & 0xffff) == 0x80) {
283 ia32_syscall(tf);
284 goto out;
285 }
286 ucode = (tf->tf_special.isr >> 16) & 0xffff;
287 sig = SIGILL;
288 break;
289
290 default:
291 /* Should never happen of course. */
292 trap_panic(vector, tf);
293 break;
294 }
295
296 KASSERT(sig != 0, ("%s: signal not set", __func__));
297
298 ksiginfo_init_trap(&ksi);
299 ksi.ksi_signo = sig;
300 ksi.ksi_code = (int)ucode; /* XXX */
301 /* ksi.ksi_addr */
302 trapsignal(td, &ksi);
303
304out:
305 userret(td, tf);
306 mtx_assert(&Giant, MA_NOTOWNED);
307 do_ast(tf);
308}