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