]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/i386/unix_signal.c
xnu-517.12.7.tar.gz
[apple/xnu.git] / bsd / dev / i386 / unix_signal.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright (c) 1992 NeXT, Inc.
24 *
25 * HISTORY
26 * 13 May 1992 ? at NeXT
27 * Created.
28 */
29
30 #include <mach/mach_types.h>
31 #include <mach/exception.h>
32
33 #include <kern/thread.h>
34 #include <kern/thread_act.h>
35
36 #include <sys/param.h>
37 #include <sys/proc.h>
38 #include <sys/user.h>
39
40 #include <i386/psl.h>
41
42 #include <mach/i386/thread_status.h>
43 #include <dev/i386/sel_inline.h>
44
45
46 /*
47 * FIXME.. should be included from mach_kernel/i386/seg.h
48 */
49
50 #define USER_CS 0x17
51 #define USER_DS 0x1f
52 #define USER_CTHREAD 0x27
53
54 #define UDATA_SEL USER_DS
55 #define UCODE_SEL USER_CS
56 #define UCTHREAD_SEL USER_CTHREAD
57
58 #define valid_user_code_selector(x) (TRUE)
59 #define valid_user_data_selector(x) (TRUE)
60 #define valid_user_stack_selector(x) (TRUE)
61
62
63 #define NULL_SEG 0
64
65 /* Signal handler flavors supported */
66 /* These defns should match the Libc implmn */
67 #define UC_TRAD 1
68
69 /*
70 * Send an interrupt to process.
71 *
72 * Stack is set up to allow sigcode stored
73 * in u. to call routine, followed by chmk
74 * to sigreturn routine below. After sigreturn
75 * resets the signal mask, the stack, the frame
76 * pointer, and the argument pointer, it returns
77 * to the user specified pc, psl.
78 */
79
80 void
81 sendsig(p, catcher, sig, mask, code)
82 struct proc *p;
83 sig_t catcher;
84 int sig, mask;
85 u_long code;
86 {
87 struct sigframe {
88 int retaddr;
89 sig_t catcher;
90 int sigstyle;
91 int sig;
92 int code;
93 struct sigcontext * scp;
94 } frame, *fp;
95 struct sigcontext context, *scp;
96 struct sigacts *ps = p->p_sigacts;
97 int oonstack;
98 thread_t thread = current_thread();
99 thread_act_t th_act = current_act();
100 struct uthread * ut;
101 struct i386_saved_state * saved_state = (struct i386_saved_state *)
102 get_user_regs(th_act);
103 sig_t trampact;
104
105 ut = get_bsdthread_info(th_act);
106 oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK;
107 if ((ps->ps_flags & SAS_ALTSTACK) && !oonstack &&
108 (ps->ps_sigonstack & sigmask(sig))) {
109 scp = ((struct sigcontext *)ps->ps_sigstk.ss_sp) - 1;
110 ps->ps_sigstk.ss_flags |= SA_ONSTACK;
111 } else
112 scp = ((struct sigcontext *)saved_state->uesp) - 1;
113 fp = ((struct sigframe *)scp) - 1;
114
115 /*
116 * Build the argument list for the signal handler.
117 */
118
119 trampact = ps->ps_trampact[sig];
120 /* Handler should call sigreturn to get out of it */
121 frame.retaddr = 0xffffffff;
122 frame.catcher = catcher;
123 frame.sigstyle = UC_TRAD;
124 frame.sig = sig;
125
126 if (sig == SIGILL || sig == SIGFPE) {
127 frame.code = code;
128 } else
129 frame.code = 0;
130 frame.scp = scp;
131 if (copyout((caddr_t)&frame, (caddr_t)fp, sizeof (frame)))
132 goto bad;
133
134 #if PC_SUPPORT
135 {
136 PCcontext_t context = threadPCContext(thread);
137
138 if (context && context->running) {
139 oonstack |= 02;
140 context->running = FALSE;
141 }
142 }
143 #endif
144 /*
145 * Build the signal context to be used by sigreturn.
146 */
147 context.sc_onstack = oonstack;
148 context.sc_mask = mask;
149 context.sc_eax = saved_state->eax;
150 context.sc_ebx = saved_state->ebx;
151 context.sc_ecx = saved_state->ecx;
152 context.sc_edx = saved_state->edx;
153 context.sc_edi = saved_state->edi;
154 context.sc_esi = saved_state->esi;
155 context.sc_ebp = saved_state->ebp;
156 context.sc_esp = saved_state->uesp;
157 context.sc_ss = saved_state->ss;
158 context.sc_eflags = saved_state->efl;
159 context.sc_eip = saved_state->eip;
160 context.sc_cs = saved_state->cs;
161 if (saved_state->efl & EFL_VM) {
162 context.sc_ds = saved_state->v86_segs.v86_ds;
163 context.sc_es = saved_state->v86_segs.v86_es;
164 context.sc_fs = saved_state->v86_segs.v86_fs;
165 context.sc_gs = saved_state->v86_segs.v86_gs;
166
167 saved_state->efl &= ~EFL_VM;
168 } else {
169 context.sc_ds = saved_state->ds;
170 context.sc_es = saved_state->es;
171 context.sc_fs = saved_state->fs;
172 context.sc_gs = saved_state->gs;
173 }
174 if (copyout((caddr_t)&context, (caddr_t)scp, sizeof (context)))
175 goto bad;
176
177 saved_state->eip = (unsigned int)trampact;
178 saved_state->cs = UCODE_SEL;
179
180 saved_state->uesp = (unsigned int)fp;
181 saved_state->ss = UDATA_SEL;
182
183 saved_state->ds = UDATA_SEL;
184 saved_state->es = UDATA_SEL;
185 saved_state->fs = NULL_SEG;
186 saved_state->gs = USER_CTHREAD;
187 return;
188
189 bad:
190 SIGACTION(p, SIGILL) = SIG_DFL;
191 sig = sigmask(SIGILL);
192 p->p_sigignore &= ~sig;
193 p->p_sigcatch &= ~sig;
194 ut->uu_sigmask &= ~sig;
195 /* sendsig is called with signal lock held */
196 psignal_lock(p, SIGILL, 0);
197 return;
198 }
199
200 /*
201 * System call to cleanup state after a signal
202 * has been taken. Reset signal mask and
203 * stack state from context left by sendsig (above).
204 * Return to previous pc and psl as specified by
205 * context left by sendsig. Check carefully to
206 * make sure that the user has not modified the
207 * psl to gain improper priviledges or to cause
208 * a machine fault.
209 */
210 struct sigreturn_args {
211 struct sigcontext *sigcntxp;
212 };
213 /* ARGSUSED */
214 int
215 sigreturn(p, uap, retval)
216 struct proc *p;
217 struct sigreturn_args *uap;
218 int *retval;
219 {
220 struct sigcontext context;
221 thread_t thread = current_thread();
222 thread_act_t th_act = current_act();
223 int error;
224 struct i386_saved_state* saved_state = (struct i386_saved_state*)
225 get_user_regs(th_act);
226 struct uthread * ut;
227
228
229
230 if (saved_state == NULL)
231 return EINVAL;
232
233 if (error = copyin((caddr_t)uap->sigcntxp, (caddr_t)&context,
234 sizeof (context)))
235 return(error);
236 ut = (struct uthread *)get_bsdthread_info(th_act);
237
238 if (context.sc_onstack & 01)
239 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
240 else
241 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
242 ut->uu_sigmask = context.sc_mask &~ sigcantmask;
243 if(ut->uu_siglist & ~ut->uu_sigmask)
244 signal_setast(current_act());
245 saved_state->eax = context.sc_eax;
246 saved_state->ebx = context.sc_ebx;
247 saved_state->ecx = context.sc_ecx;
248 saved_state->edx = context.sc_edx;
249 saved_state->edi = context.sc_edi;
250 saved_state->esi = context.sc_esi;
251 saved_state->ebp = context.sc_ebp;
252 saved_state->uesp = context.sc_esp;
253 saved_state->ss = context.sc_ss;
254 saved_state->efl = context.sc_eflags;
255 saved_state->efl &= ~EFL_USERCLR;
256 saved_state->efl |= EFL_USERSET;
257 saved_state->eip = context.sc_eip;
258 saved_state->cs = context.sc_cs;
259
260 if (context.sc_eflags & EFL_VM) {
261 saved_state->ds = NULL_SEG;
262 saved_state->es = NULL_SEG;
263 saved_state->fs = NULL_SEG;
264 saved_state->gs = NULL_SEG;
265 saved_state->v86_segs.v86_ds = context.sc_ds;
266 saved_state->v86_segs.v86_es = context.sc_es;
267 saved_state->v86_segs.v86_fs = context.sc_fs;
268 saved_state->v86_segs.v86_gs = context.sc_gs;
269
270 saved_state->efl |= EFL_VM;
271 }
272 else {
273 saved_state->ds = context.sc_ds;
274 saved_state->es = context.sc_es;
275 saved_state->fs = context.sc_fs;
276 saved_state->gs = context.sc_gs;
277 }
278
279 #if PC_SUPPORT
280 if (context.sc_onstack & 02) {
281 PCcontext_t context = threadPCContext(thread);
282
283 if (context)
284 context->running = TRUE;
285 }
286 #endif
287
288 return (EJUSTRETURN);
289 }
290
291 /*
292 * machine_exception() performs MD translation
293 * of a mach exception to a unix signal and code.
294 */
295
296 boolean_t
297 machine_exception(
298 int exception,
299 int code,
300 int subcode,
301 int *unix_signal,
302 int *unix_code
303 )
304 {
305
306 switch(exception) {
307
308 case EXC_BAD_INSTRUCTION:
309 *unix_signal = SIGILL;
310 *unix_code = code;
311 break;
312
313 case EXC_ARITHMETIC:
314 *unix_signal = SIGFPE;
315 *unix_code = code;
316 break;
317
318 default:
319 return(FALSE);
320 }
321
322 return(TRUE);
323 }