|
|
1.1 root 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:
53: #define UDATA_SEL USER_DS
54: #define UCODE_SEL USER_CS
55:
56: #define valid_user_code_selector(x) (TRUE)
57: #define valid_user_data_selector(x) (TRUE)
58: #define valid_user_stack_selector(x) (TRUE)
59:
60:
61: #define NULL_SEG 0
62:
63: /*
64: * Send an interrupt to process.
65: *
66: * Stack is set up to allow sigcode stored
67: * in u. to call routine, followed by chmk
68: * to sigreturn routine below. After sigreturn
69: * resets the signal mask, the stack, the frame
70: * pointer, and the argument pointer, it returns
71: * to the user specified pc, psl.
72: */
73:
74: void
75: sendsig(p, catcher, sig, mask, code)
76: struct proc *p;
77: sig_t catcher;
78: int sig, mask;
79: u_long code;
80: {
81: struct sigframe {
82: int retaddr;
83: int sig;
84: int code;
85: struct sigcontext * scp;
86: } frame, *fp;
87: struct sigcontext context, *scp;
88: struct sigacts *ps = p->p_sigacts;
89: int oonstack;
90: thread_t thread = current_thread();
91: thread_act_t th_act = current_act();
92: struct i386_saved_state * saved_state = get_user_regs(th_act);
93:
94: oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK;
95: if ((ps->ps_flags & SAS_ALTSTACK) && !oonstack &&
96: (ps->ps_sigonstack & sigmask(sig))) {
97: scp = ((struct sigcontext *)ps->ps_sigstk.ss_sp) - 1;
98: ps->ps_sigstk.ss_flags |= SA_ONSTACK;
99: } else
100: scp = ((struct sigcontext *)saved_state->uesp) - 1;
101: fp = ((struct sigframe *)scp) - 1;
102:
103: /*
104: * Build the argument list for the signal handler.
105: */
106:
107: frame.retaddr = 0xffffffff; /* Handler should call sigreturn to get out of it */
108: frame.sig = sig;
109:
110: if (sig == SIGILL || sig == SIGFPE) {
111: frame.code = code;
112: } else
113: frame.code = 0;
114: frame.scp = scp;
115: if (copyout((caddr_t)&frame, (caddr_t)fp, sizeof (frame)))
116: goto bad;
117:
118: #if PC_SUPPORT
119: {
120: PCcontext_t context = threadPCContext(thread);
121:
122: if (context && context->running) {
123: oonstack |= 02;
124: context->running = FALSE;
125: }
126: }
127: #endif
128: /*
129: * Build the signal context to be used by sigreturn.
130: */
131: context.sc_onstack = oonstack;
132: context.sc_mask = mask;
133: context.sc_eax = saved_state->eax;
134: context.sc_ebx = saved_state->ebx;
135: context.sc_ecx = saved_state->ecx;
136: context.sc_edx = saved_state->edx;
137: context.sc_edi = saved_state->edi;
138: context.sc_esi = saved_state->esi;
139: context.sc_ebp = saved_state->ebp;
140: context.sc_esp = saved_state->uesp;
141: context.sc_ss = saved_state->ss;
142: context.sc_eflags = saved_state->efl;
143: context.sc_eip = saved_state->eip;
144: context.sc_cs = saved_state->cs;
145: if (saved_state->efl & EFL_VM) {
146: context.sc_ds = saved_state->v86_segs.v86_ds;
147: context.sc_es = saved_state->v86_segs.v86_es;
148: context.sc_fs = saved_state->v86_segs.v86_fs;
149: context.sc_gs = saved_state->v86_segs.v86_gs;
150:
151: saved_state->efl &= ~EFL_VM;
152: }
153: else {
154: context.sc_ds = saved_state->ds;
155: context.sc_es = saved_state->es;
156: context.sc_fs = saved_state->fs;
157: context.sc_gs = saved_state->gs;
158: }
159: if (copyout((caddr_t)&context, (caddr_t)scp, sizeof (context)))
160: goto bad;
161:
162: saved_state->eip = (unsigned int)catcher;
163: saved_state->cs = UCODE_SEL;
164:
165: saved_state->uesp = (unsigned int)fp;
166: saved_state->ss = UDATA_SEL;
167:
168: saved_state->ds = UDATA_SEL;
169: saved_state->es = UDATA_SEL;
170: saved_state->fs = NULL_SEG;
171: saved_state->gs = NULL_SEG;
172: return;
173:
174: bad:
175: SIGACTION(p, SIGILL) = SIG_DFL;
176: sig = sigmask(SIGILL);
177: p->p_sigignore &= ~sig;
178: p->p_sigcatch &= ~sig;
179: p->p_sigmask &= ~sig;
180: psignal(p, SIGILL);
181: return;
182: }
183:
184: /*
185: * System call to cleanup state after a signal
186: * has been taken. Reset signal mask and
187: * stack state from context left by sendsig (above).
188: * Return to previous pc and psl as specified by
189: * context left by sendsig. Check carefully to
190: * make sure that the user has not modified the
191: * psl to gain improper priviledges or to cause
192: * a machine fault.
193: */
194: struct sigreturn_args {
195: struct sigcontext *sigcntxp;
196: };
197: /* ARGSUSED */
198: int
199: sigreturn(p, uap, retval)
200: struct proc *p;
201: struct sigreturn_args *uap;
202: int *retval;
203: {
204: struct sigcontext context;
205: thread_t thread = current_thread();
206: thread_act_t th_act = current_act();
207: int error;
208: struct i386_saved_state* saved_state = get_user_regs(th_act);
209:
210: if (saved_state == NULL)
211: return EINVAL;
212:
213: if (error = copyin((caddr_t)uap->sigcntxp, (caddr_t)&context,
214: sizeof (context)))
215: return(error);
216:
217: #if 0 /*FIXME*/
218: if ((context.sc_eflags & EFL_VM) == 0 &&
219: (!valid_user_code_selector(context.sc_cs) ||
220: !valid_user_data_selector(context.sc_ds) ||
221: !valid_user_data_selector(context.sc_es) ||
222: !valid_user_data_selector(context.sc_fs) ||
223: !valid_user_data_selector(context.sc_gs) ||
224: !valid_user_stack_selector(context.sc_ss))
225: )
226: return(EINVAL);
227: #endif
228:
229: if (context.sc_onstack & 01)
230: p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
231: else
232: p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
233: p->p_sigmask = context.sc_mask &~ sigcantmask;
234: saved_state->eax = context.sc_eax;
235: saved_state->ebx = context.sc_ebx;
236: saved_state->ecx = context.sc_ecx;
237: saved_state->edx = context.sc_edx;
238: saved_state->edi = context.sc_edi;
239: saved_state->esi = context.sc_esi;
240: saved_state->ebp = context.sc_ebp;
241: saved_state->uesp = context.sc_esp;
242: saved_state->ss = context.sc_ss;
243: saved_state->efl = context.sc_eflags;
244: saved_state->efl &= ~EFL_USERCLR;
245: saved_state->efl |= EFL_USERSET;
246: saved_state->eip = context.sc_eip;
247: saved_state->cs = context.sc_cs;
248:
249: if (context.sc_eflags & EFL_VM) {
250: saved_state->ds = NULL_SEG;
251: saved_state->es = NULL_SEG;
252: saved_state->fs = NULL_SEG;
253: saved_state->gs = NULL_SEG;
254: saved_state->v86_segs.v86_ds = context.sc_ds;
255: saved_state->v86_segs.v86_es = context.sc_es;
256: saved_state->v86_segs.v86_fs = context.sc_fs;
257: saved_state->v86_segs.v86_gs = context.sc_gs;
258:
259: saved_state->efl |= EFL_VM;
260: }
261: else {
262: saved_state->ds = context.sc_ds;
263: saved_state->es = context.sc_es;
264: saved_state->fs = context.sc_fs;
265: saved_state->gs = context.sc_gs;
266: }
267:
268: #if PC_SUPPORT
269: if (context.sc_onstack & 02) {
270: PCcontext_t context = threadPCContext(thread);
271:
272: if (context)
273: context->running = TRUE;
274: }
275: #endif
276:
277: return (EJUSTRETURN);
278: }
279:
280: /*
281: * machine_exception() performs MD translation
282: * of a mach exception to a unix signal and code.
283: */
284:
285: boolean_t
286: machine_exception(
287: int exception,
288: int code,
289: int subcode,
290: int *unix_signal,
291: int *unix_code
292: )
293: {
294:
295: switch(exception) {
296:
297: case EXC_BAD_INSTRUCTION:
298: *unix_signal = SIGILL;
299: *unix_code = code;
300: break;
301:
302: case EXC_ARITHMETIC:
303: *unix_signal = SIGFPE;
304: *unix_code = code;
305: break;
306:
307: default:
308: return(FALSE);
309: }
310:
311: return(TRUE);
312: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.