]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/ppc/unix_signal.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / bsd / dev / ppc / unix_signal.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
30 */
31
32#include <mach/mach_types.h>
33#include <mach/exception_types.h>
34
35#include <sys/param.h>
91447636 36#include <sys/proc_internal.h>
1c79356b 37#include <sys/user.h>
9bccf70c 38#include <sys/ucontext.h>
91447636
A
39#include <sys/sysproto.h>
40#include <sys/systm.h>
41#include <sys/ux_exception.h>
1c79356b
A
42
43#include <ppc/signal.h>
44#include <sys/signalvar.h>
9bccf70c
A
45#include <sys/kdebug.h>
46#include <sys/wait.h>
1c79356b 47#include <kern/thread.h>
1c79356b 48#include <mach/ppc/thread_status.h>
9bccf70c 49#include <ppc/proc_reg.h>
1c79356b 50
91447636
A
51// #include <machine/thread.h> XXX include path messed up for some reason...
52
53/* XXX functions not in a Mach headers */
54extern kern_return_t thread_getstatus(register thread_t act, int flavor,
55 thread_state_t tstate, mach_msg_type_number_t *count);
56extern int is_64signalregset(void);
57extern unsigned int get_msr_exportmask(void);
58extern kern_return_t thread_setstatus(thread_t thread, int flavor,
59 thread_state_t tstate, mach_msg_type_number_t count);
60extern void ppc_checkthreadstate(void *, int);
61extern struct savearea_vec *find_user_vec_curr(void);
62extern int thread_enable_fpe(thread_t act, int onoff);
63
64
65
66#define C_32_REDZONE_LEN 224
67#define C_32_STK_ALIGN 16
68#define C_32_PARAMSAVE_LEN 64
69#define C_32_LINKAGE_LEN 48
70
71#define C_64_REDZONE_LEN 320
72#define C_64_STK_ALIGN 32
73#define C_64_PARAMSAVE_LEN 64
74#define C_64_LINKAGE_LEN 48
75
76#define TRUNC_DOWN32(a,b,c) ((((uint32_t)a)-(b)) & ((uint32_t)(-(c))))
77#define TRUNC_DOWN64(a,b,c) ((((uint64_t)a)-(b)) & ((uint64_t)(-(c))))
1c79356b 78
55e303ae
A
79/*
80 * The stack layout possibilities (info style); This needs to mach with signal trampoline code
81 *
82 * Traditional: 1
83 * Traditional64: 20
84 * Traditional64with vec: 25
85 * 32bit context 30
86 * 32bit context with vector 35
87 * 64bit context 40
88 * 64bit context with vector 45
89 * Dual context 50
90 * Dual context with vector 55
91 *
92 */
93
94#define UC_TRAD 1
95#define UC_TRAD_VEC 6
96#define UC_TRAD64 20
97#define UC_TRAD64_VEC 25
98#define UC_FLAVOR 30
99#define UC_FLAVOR_VEC 35
100#define UC_FLAVOR64 40
101#define UC_FLAVOR64_VEC 45
102#define UC_DUAL 50
103#define UC_DUAL_VEC 55
104
105 /* The following are valid mcontext sizes */
106#define UC_FLAVOR_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
107
108#define UC_FLAVOR_VEC_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
109
110#define UC_FLAVOR64_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
111
112#define UC_FLAVOR64_VEC_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
113
114
91447636
A
115/*
116 * NOTE: Source and target may *NOT* overlap!
117 */
118static void
119ucontext_32to64(struct ucontext64 *in, struct user_ucontext64 *out)
120{
121 out->uc_onstack = in->uc_onstack;
122 out->uc_sigmask = in->uc_sigmask;
123
124 /* internal "structure assign" */
125 out->uc_stack.ss_sp = CAST_USER_ADDR_T(in->uc_stack.ss_sp);
126 out->uc_stack.ss_size = in->uc_stack.ss_size;
127 out->uc_stack.ss_flags = in->uc_stack.ss_flags;
128
129 out->uc_link = CAST_USER_ADDR_T(in->uc_link);
130 out->uc_mcsize = in->uc_mcsize;
131 out->uc_mcontext64 = CAST_USER_ADDR_T(in->uc_mcontext64);
132}
133
134/*
135 * This conversion is safe, since if we are converting for a 32 bit process,
136 * then it's values of uc-stack.ss_size and uc_mcsize will never exceed 4G.
137 *
138 * NOTE: Source and target may *NOT* overlap!
139 */
140static void
141ucontext_64to32(struct user_ucontext64 *in, struct ucontext64 *out)
142{
143 out->uc_onstack = in->uc_onstack;
144 out->uc_sigmask = in->uc_sigmask;
145
146 /* internal "structure assign" */
147 out->uc_stack.ss_sp = CAST_DOWN(void *,in->uc_stack.ss_sp);
148 out->uc_stack.ss_size = in->uc_stack.ss_size; /* range reduction */
149 out->uc_stack.ss_flags = in->uc_stack.ss_flags;
150
151 out->uc_link = CAST_DOWN(void *,in->uc_link);
152 out->uc_mcsize = in->uc_mcsize; /* range reduction */
153 out->uc_mcontext64 = CAST_DOWN(void *,in->uc_mcontext64);
154}
155
156/*
157 * NOTE: Source and target may *NOT* overlap!
158 */
159static void
160siginfo_64to32(user_siginfo_t *in, siginfo_t *out)
161{
162 out->si_signo = in->si_signo;
163 out->si_errno = in->si_errno;
164 out->si_code = in->si_code;
165 out->si_pid = in->si_pid;
166 out->si_uid = in->si_uid;
167 out->si_status = in->si_status;
168 out->si_addr = CAST_DOWN(void *,in->si_addr);
169 /* following cast works for sival_int because of padding */
170 out->si_value.sival_ptr = CAST_DOWN(void *,in->si_value.sival_ptr);
171 out->si_band = in->si_band; /* range reduction */
172 out->pad[0] = in->pad[0]; /* mcontext.ss.r1 */
173}
174
175
1c79356b
A
176/*
177 * Arrange for this process to run a signal handler
178 */
179
1c79356b 180void
91447636 181sendsig(struct proc *p, user_addr_t catcher, int sig, int mask, __unused u_long code)
1c79356b 182{
55e303ae 183 kern_return_t kretn;
91447636
A
184 struct mcontext mctx;
185 user_addr_t p_mctx = USER_ADDR_NULL; /* mcontext dest. */
186 struct mcontext64 mctx64;
187 user_addr_t p_mctx64 = USER_ADDR_NULL; /* mcontext dest. */
188 struct user_ucontext64 uctx;
189 user_addr_t p_uctx; /* user stack addr top copy ucontext */
190 user_siginfo_t sinfo;
191 user_addr_t p_sinfo; /* user stack addr top copy siginfo */
1c79356b 192 struct sigacts *ps = p->p_sigacts;
1c79356b 193 int oonstack;
91447636
A
194 user_addr_t sp;
195 mach_msg_type_number_t state_count;
196 thread_t th_act;
9bccf70c 197 struct uthread *ut;
55e303ae
A
198 int infostyle = UC_TRAD;
199 int dualcontext =0;
91447636 200 user_addr_t trampact;
9bccf70c
A
201 int vec_used = 0;
202 int stack_size = 0;
55e303ae
A
203 void * tstate;
204 int flavor;
4452a7af
A
205 int ctx32 = 1;
206 int uthsigaltstack = 0;
207 int altstack = 0;
208
209
91447636 210 th_act = current_thread();
9bccf70c 211 ut = get_bsdthread_info(th_act);
1c79356b 212
55e303ae
A
213
214 if (p->p_sigacts->ps_siginfo & sigmask(sig)) {
215 infostyle = UC_FLAVOR;
216 }
217 if(is_64signalregset() && (infostyle == UC_FLAVOR)) {
218 dualcontext = 1;
219 infostyle = UC_DUAL;
220 }
91447636 221 if (p->p_sigacts->ps_64regset & sigmask(sig)) {
55e303ae
A
222 dualcontext = 0;
223 ctx32 = 0;
224 infostyle = UC_FLAVOR64;
225 }
91447636
A
226 /* treat 64 bit processes as having used 64 bit registers */
227 if ((IS_64BIT_PROCESS(p) || is_64signalregset()) &&
228 (infostyle == UC_TRAD)) {
55e303ae
A
229 ctx32=0;
230 infostyle = UC_TRAD64;
91447636
A
231 }
232 if (IS_64BIT_PROCESS(p)) {
233 ctx32=0;
234 dualcontext = 0;
235 }
55e303ae
A
236
237 /* I need this for SIGINFO anyway */
238 flavor = PPC_THREAD_STATE;
239 tstate = (void *)&mctx.ss;
1c79356b 240 state_count = PPC_THREAD_STATE_COUNT;
55e303ae 241 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
de355530 242 goto bad;
1c79356b 243
55e303ae
A
244 if ((ctx32 == 0) || dualcontext) {
245 flavor = PPC_THREAD_STATE64;
246 tstate = (void *)&mctx64.ss;
247 state_count = PPC_THREAD_STATE64_COUNT;
248 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
249 goto bad;
de355530 250 }
9bccf70c 251
55e303ae
A
252 if ((ctx32 == 1) || dualcontext) {
253 flavor = PPC_EXCEPTION_STATE;
254 tstate = (void *)&mctx.es;
255 state_count = PPC_EXCEPTION_STATE_COUNT;
256 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
257 goto bad;
258 }
259
260 if ((ctx32 == 0) || dualcontext) {
261 flavor = PPC_EXCEPTION_STATE64;
262 tstate = (void *)&mctx64.es;
263 state_count = PPC_EXCEPTION_STATE64_COUNT;
264
265 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
266 goto bad;
267
268 }
269
270
271 if ((ctx32 == 1) || dualcontext) {
272 flavor = PPC_FLOAT_STATE;
273 tstate = (void *)&mctx.fs;
274 state_count = PPC_FLOAT_STATE_COUNT;
275 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
276 goto bad;
277 }
278
279 if ((ctx32 == 0) || dualcontext) {
280 flavor = PPC_FLOAT_STATE;
281 tstate = (void *)&mctx64.fs;
282 state_count = PPC_FLOAT_STATE_COUNT;
283 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
284 goto bad;
285
286 }
287
288
289 if (find_user_vec_curr()) {
290 vec_used = 1;
291
292 if ((ctx32 == 1) || dualcontext) {
293 flavor = PPC_VECTOR_STATE;
294 tstate = (void *)&mctx.vs;
295 state_count = PPC_VECTOR_STATE_COUNT;
296 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
297 goto bad;
91447636 298 infostyle += 5;
55e303ae
A
299 }
300
301 if ((ctx32 == 0) || dualcontext) {
302 flavor = PPC_VECTOR_STATE;
303 tstate = (void *)&mctx64.vs;
304 state_count = PPC_VECTOR_STATE_COUNT;
305 if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS)
306 goto bad;
91447636 307 infostyle += 5;
55e303ae
A
308 }
309 }
310
9bccf70c 311 trampact = ps->ps_trampact[sig];
4452a7af
A
312 uthsigaltstack = p->p_lflag & P_LTHSIGSTACK;
313
314 if (uthsigaltstack != 0 ) {
315 oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;
316 altstack = ut->uu_flag & UT_ALTSTACK;
317 } else {
318 oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK;
319 altstack = ps->ps_flags & SAS_ALTSTACK;
320 }
321
1c79356b
A
322
323 /* figure out where our new stack lives */
4452a7af 324 if (altstack && !oonstack &&
1c79356b 325 (ps->ps_sigonstack & sigmask(sig))) {
4452a7af
A
326 if (uthsigaltstack != 0) {
327 sp = ut->uu_sigstk.ss_sp;
328 sp += ut->uu_sigstk.ss_size;
329 stack_size = ut->uu_sigstk.ss_size;
330 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
331 } else {
332 sp = ps->ps_sigstk.ss_sp;
333 sp += ps->ps_sigstk.ss_size;
334 stack_size = ps->ps_sigstk.ss_size;
335 ps->ps_sigstk.ss_flags |= SA_ONSTACK;
336 }
1c79356b 337 }
55e303ae
A
338 else {
339 if (ctx32 == 0)
91447636 340 sp = mctx64.ss.r1;
55e303ae 341 else
91447636 342 sp = CAST_USER_ADDR_T(mctx.ss.r1);
55e303ae 343 }
1c79356b 344
55e303ae
A
345
346 /* put siginfo on top */
347
9bccf70c 348 /* preserve RED ZONE area */
91447636
A
349 if (IS_64BIT_PROCESS(p))
350 sp = TRUNC_DOWN64(sp, C_64_REDZONE_LEN, C_64_STK_ALIGN);
351 else
352 sp = TRUNC_DOWN32(sp, C_32_REDZONE_LEN, C_32_STK_ALIGN);
1c79356b 353
55e303ae
A
354 /* next are the saved registers */
355 if ((ctx32 == 0) || dualcontext) {
91447636
A
356 sp -= sizeof(struct mcontext64);
357 p_mctx64 = sp;
55e303ae
A
358 }
359 if ((ctx32 == 1) || dualcontext) {
91447636
A
360 sp -= sizeof(struct mcontext);
361 p_mctx = sp;
55e303ae
A
362 }
363
91447636
A
364 if (IS_64BIT_PROCESS(p)) {
365 /* context goes first on stack */
366 sp -= sizeof(struct user_ucontext64);
367 p_uctx = sp;
368
369 /* this is where siginfo goes on stack */
370 sp -= sizeof(user_siginfo_t);
371 p_sinfo = sp;
372
373 sp = TRUNC_DOWN64(sp, C_64_PARAMSAVE_LEN+C_64_LINKAGE_LEN, C_64_STK_ALIGN);
374 } else {
375 /*
376 * struct ucontext and struct ucontext64 are identical in
377 * size and content; the only difference is the internal
378 * pointer type for the last element, which makes no
379 * difference for the copyout().
380 */
381
382 /* context goes first on stack */
383 sp -= sizeof(struct ucontext64);
384 p_uctx = sp;
385
386 /* this is where siginfo goes on stack */
387 sp -= sizeof(siginfo_t);
388 p_sinfo = sp;
389
390 sp = TRUNC_DOWN32(sp, C_32_PARAMSAVE_LEN+C_32_LINKAGE_LEN, C_32_STK_ALIGN);
391 }
1c79356b 392
9bccf70c
A
393 uctx.uc_onstack = oonstack;
394 uctx.uc_sigmask = mask;
91447636 395 uctx.uc_stack.ss_sp = sp;
9bccf70c
A
396 uctx.uc_stack.ss_size = stack_size;
397 if (oonstack)
398 uctx.uc_stack.ss_flags |= SS_ONSTACK;
399
400 uctx.uc_link = 0;
55e303ae
A
401 if (ctx32 == 0)
402 uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE64_COUNT + PPC_THREAD_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int));
403 else
404 uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE_COUNT + PPC_THREAD_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int));
405
9bccf70c
A
406 if (vec_used)
407 uctx.uc_mcsize += (size_t)(PPC_VECTOR_STATE_COUNT * sizeof(int));
55e303ae
A
408
409 if (ctx32 == 0)
91447636 410 uctx.uc_mcontext64 = p_mctx64;
55e303ae 411 else
91447636 412 uctx.uc_mcontext64 = p_mctx;
9bccf70c
A
413
414 /* setup siginfo */
91447636 415 bzero((caddr_t)&sinfo, sizeof(user_siginfo_t));
9bccf70c 416 sinfo.si_signo = sig;
91447636
A
417 if (ctx32 == 0) {
418 sinfo.si_addr = mctx64.ss.srr0;
419 sinfo.pad[0] = mctx64.ss.r1;
420 } else {
421 sinfo.si_addr = CAST_USER_ADDR_T(mctx.ss.srr0);
422 sinfo.pad[0] = CAST_USER_ADDR_T(mctx.ss.r1);
423 }
55e303ae 424
9bccf70c
A
425 switch (sig) {
426 case SIGCHLD:
427 sinfo.si_pid = p->si_pid;
428 p->si_pid =0;
429 sinfo.si_status = p->si_status;
430 p->si_status = 0;
431 sinfo.si_uid = p->si_uid;
432 p->si_uid =0;
433 sinfo.si_code = p->si_code;
434 p->si_code = 0;
435 if (sinfo.si_code == CLD_EXITED) {
436 if (WIFEXITED(sinfo.si_status))
437 sinfo.si_code = CLD_EXITED;
438 else if (WIFSIGNALED(sinfo.si_status)) {
439 if (WCOREDUMP(sinfo.si_status))
440 sinfo.si_code = CLD_DUMPED;
441 else
442 sinfo.si_code = CLD_KILLED;
443 }
444 }
445 break;
446 case SIGILL:
91447636
A
447 /*
448 * If it's 64 bit and not a dual context, mctx will
449 * contain uninitialized data, so we have to use
450 * mctx64 here.
451 */
452 if(ctx32 == 0) {
453 if (mctx64.ss.srr1 & (1 << (31 - SRR1_PRG_ILL_INS_BIT)))
454 sinfo.si_code = ILL_ILLOPC;
455 else if (mctx64.ss.srr1 & (1 << (31 - SRR1_PRG_PRV_INS_BIT)))
456 sinfo.si_code = ILL_PRVOPC;
457 else if (mctx64.ss.srr1 & (1 << (31 - SRR1_PRG_TRAP_BIT)))
458 sinfo.si_code = ILL_ILLTRP;
459 else
460 sinfo.si_code = ILL_NOOP;
461 } else {
462 if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_ILL_INS_BIT)))
463 sinfo.si_code = ILL_ILLOPC;
464 else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_PRV_INS_BIT)))
465 sinfo.si_code = ILL_PRVOPC;
466 else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_TRAP_BIT)))
467 sinfo.si_code = ILL_ILLTRP;
468 else
469 sinfo.si_code = ILL_NOOP;
470 }
9bccf70c
A
471 break;
472 case SIGFPE:
473#define FPSCR_VX 2
474#define FPSCR_OX 3
475#define FPSCR_UX 4
476#define FPSCR_ZX 5
477#define FPSCR_XX 6
91447636
A
478 /*
479 * If it's 64 bit and not a dual context, mctx will
480 * contain uninitialized data, so we have to use
481 * mctx64 here.
482 */
483 if(ctx32 == 0) {
484 if (mctx64.fs.fpscr & (1 << (31 - FPSCR_VX)))
485 sinfo.si_code = FPE_FLTINV;
486 else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_OX)))
487 sinfo.si_code = FPE_FLTOVF;
488 else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_UX)))
489 sinfo.si_code = FPE_FLTUND;
490 else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_ZX)))
491 sinfo.si_code = FPE_FLTDIV;
492 else if (mctx64.fs.fpscr & (1 << (31 - FPSCR_XX)))
493 sinfo.si_code = FPE_FLTRES;
494 else
495 sinfo.si_code = FPE_NOOP;
496 } else {
497 if (mctx.fs.fpscr & (1 << (31 - FPSCR_VX)))
498 sinfo.si_code = FPE_FLTINV;
499 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_OX)))
500 sinfo.si_code = FPE_FLTOVF;
501 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_UX)))
502 sinfo.si_code = FPE_FLTUND;
503 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_ZX)))
504 sinfo.si_code = FPE_FLTDIV;
505 else if (mctx.fs.fpscr & (1 << (31 - FPSCR_XX)))
506 sinfo.si_code = FPE_FLTRES;
507 else
508 sinfo.si_code = FPE_NOOP;
509 }
9bccf70c
A
510 break;
511
512 case SIGBUS:
91447636
A
513 if (ctx32 == 0) {
514 sinfo.si_addr = mctx64.es.dar;
515 } else {
516 sinfo.si_addr = CAST_USER_ADDR_T(mctx.es.dar);
517 }
9bccf70c
A
518 /* on ppc we generate only if EXC_PPC_UNALIGNED */
519 sinfo.si_code = BUS_ADRALN;
520 break;
521
522 case SIGSEGV:
91447636
A
523 /*
524 * If it's 64 bit and not a dual context, mctx will
525 * contain uninitialized data, so we have to use
526 * mctx64 here.
527 */
528 if (ctx32 == 0) {
529 sinfo.si_addr = mctx64.es.dar;
530 /* First check in srr1 and then in dsisr */
531 if (mctx64.ss.srr1 & (1 << (31 - DSISR_PROT_BIT)))
532 sinfo.si_code = SEGV_ACCERR;
533 else if (mctx64.es.dsisr & (1 << (31 - DSISR_PROT_BIT)))
534 sinfo.si_code = SEGV_ACCERR;
535 else
536 sinfo.si_code = SEGV_MAPERR;
537 } else {
538 sinfo.si_addr = CAST_USER_ADDR_T(mctx.es.dar);
539 /* First check in srr1 and then in dsisr */
540 if (mctx.ss.srr1 & (1 << (31 - DSISR_PROT_BIT)))
541 sinfo.si_code = SEGV_ACCERR;
542 else if (mctx.es.dsisr & (1 << (31 - DSISR_PROT_BIT)))
543 sinfo.si_code = SEGV_ACCERR;
544 else
545 sinfo.si_code = SEGV_MAPERR;
546 }
9bccf70c
A
547 break;
548 default:
549 break;
550 }
1c79356b 551
55e303ae 552
1c79356b 553 /* copy info out to user space */
91447636
A
554 if (IS_64BIT_PROCESS(p)) {
555 if (copyout(&uctx, p_uctx, sizeof(struct user_ucontext64)))
e5568f75 556 goto bad;
91447636 557 if (copyout(&sinfo, p_sinfo, sizeof(user_siginfo_t)))
e5568f75 558 goto bad;
91447636
A
559 } else {
560 struct ucontext64 uctx32;
561 siginfo_t sinfo32;
55e303ae 562
91447636
A
563 ucontext_64to32(&uctx, &uctx32);
564 if (copyout(&uctx32, p_uctx, sizeof(struct ucontext64)))
565 goto bad;
1c79356b 566
91447636
A
567 siginfo_64to32(&sinfo,&sinfo32);
568 if (copyout(&sinfo32, p_sinfo, sizeof(siginfo_t)))
569 goto bad;
570 }
571 if ((ctx32 == 0) || dualcontext) {
572 /*
573 * NOTE: Size of mcontext is not variant between 64bit and
574 * 32bit programs usng 64bit registers.
575 */
576 if (copyout(&mctx64, p_mctx64, (vec_used? UC_FLAVOR64_VEC_SIZE: UC_FLAVOR64_SIZE)))
577 goto bad;
578 }
579 if ((ctx32 == 1) || dualcontext) {
580 if (copyout(&mctx, p_mctx, uctx.uc_mcsize))
581 goto bad;
582 }
1c79356b 583
1c79356b 584
91447636
A
585 /* Place our arguments in arg registers: rtm dependent */
586 if(IS_64BIT_PROCESS(p)) {
587 mctx64.ss.r3 = catcher;
588 mctx64.ss.r4 = CAST_USER_ADDR_T(infostyle);
589 mctx64.ss.r5 = CAST_USER_ADDR_T(sig);
590 mctx64.ss.r6 = p_sinfo;
591 mctx64.ss.r7 = p_uctx;
592
593 mctx64.ss.srr0 = trampact;
594 /* MSR_EXPORT_MASK_SET */
595 mctx64.ss.srr1 = CAST_USER_ADDR_T(get_msr_exportmask());
596 mctx64.ss.r1 = sp;
597 state_count = PPC_THREAD_STATE64_COUNT;
598 if ((kretn = thread_setstatus(th_act, PPC_THREAD_STATE64, (void *)&mctx64.ss, state_count)) != KERN_SUCCESS) {
599 panic("sendsig: thread_setstatus failed, ret = %08X\n", kretn);
600 }
601 } else {
602 mctx.ss.r3 = CAST_DOWN(unsigned long,catcher);
603 mctx.ss.r4 = (unsigned long)infostyle;
604 mctx.ss.r5 = (unsigned long)sig;
605 mctx.ss.r6 = CAST_DOWN(unsigned long,p_sinfo);
606 mctx.ss.r7 = CAST_DOWN(unsigned long,p_uctx);
607
608 mctx.ss.srr0 = CAST_DOWN(unsigned long,trampact);
609 /* MSR_EXPORT_MASK_SET */
610 mctx.ss.srr1 = get_msr_exportmask();
611 mctx.ss.r1 = CAST_DOWN(unsigned long,sp);
612 state_count = PPC_THREAD_STATE_COUNT;
613 if ((kretn = thread_setstatus(th_act, PPC_THREAD_STATE, (void *)&mctx.ss, state_count)) != KERN_SUCCESS) {
614 panic("sendsig: thread_setstatus failed, ret = %08X\n", kretn);
615 }
616 }
1c79356b
A
617 return;
618
619bad:
620 SIGACTION(p, SIGILL) = SIG_DFL;
621 sig = sigmask(SIGILL);
622 p->p_sigignore &= ~sig;
623 p->p_sigcatch &= ~sig;
9bccf70c 624 ut->uu_sigmask &= ~sig;
1c79356b 625 /* sendsig is called with signal lock held */
9bccf70c 626 psignal_lock(p, SIGILL, 0);
1c79356b
A
627 return;
628}
629
630/*
631 * System call to cleanup state after a signal
632 * has been taken. Reset signal mask and
633 * stack state from context left by sendsig (above).
634 * Return to previous pc and psl as specified by
635 * context left by sendsig. Check carefully to
636 * make sure that the user has not modified the
637 * psl to gain improper priviledges or to cause
638 * a machine fault.
639 */
55e303ae 640
55e303ae
A
641/* ARGSUSED */
642int
91447636 643sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
55e303ae 644{
91447636 645 struct user_ucontext64 uctx;
55e303ae 646
91447636
A
647 char mactx[sizeof(struct mcontext64)];
648 struct mcontext *p_mctx;
55e303ae 649 struct mcontext64 *p_64mctx;
1c79356b 650 int error;
91447636 651 thread_t th_act;
9bccf70c
A
652 struct sigacts *ps = p->p_sigacts;
653 sigset_t mask;
91447636 654 user_addr_t action;
1c79356b 655 unsigned long state_count;
55e303ae 656 unsigned int state_flavor;
9bccf70c
A
657 struct uthread * ut;
658 int vec_used = 0;
55e303ae 659 void *tsptr, *fptr, *vptr;
4452a7af
A
660 int infostyle = uap->infostyle;
661 int uthsigaltstack = 0;
662
91447636 663 th_act = current_thread();
1c79356b 664
9bccf70c 665 ut = (struct uthread *)get_bsdthread_info(th_act);
91447636
A
666 if (IS_64BIT_PROCESS(p)) {
667 error = copyin(uap->uctx, &uctx, sizeof(struct user_ucontext64));
668 if (error)
669 return(error);
670 } else {
671 struct ucontext64 uctx32;
672
673 /*
674 * struct ucontext and struct ucontext64 are identical in
675 * size and content; the only difference is the internal
676 * pointer type for the last element, which makes no
677 * difference for the copyin().
678 */
679 error = copyin(uap->uctx, &uctx32, sizeof(struct ucontext));
680 if (error)
681 return(error);
682 ucontext_32to64(&uctx32, &uctx);
1c79356b 683 }
55e303ae 684
91447636 685
e5568f75
A
686 /* validate the machine context size */
687 switch (uctx.uc_mcsize) {
688 case UC_FLAVOR64_VEC_SIZE:
689 case UC_FLAVOR64_SIZE:
690 case UC_FLAVOR_VEC_SIZE:
691 case UC_FLAVOR_SIZE:
692 break;
693 default:
694 return(EINVAL);
695 }
91447636
A
696
697 /*
698 * The 64 bit process mcontext is identical to the mcontext64, so
699 * there is no conversion necessary.
700 */
701 error = copyin(uctx.uc_mcontext64, mactx, uctx.uc_mcsize);
702 if (error)
9bccf70c 703 return(error);
4452a7af
A
704
705 uthsigaltstack = p->p_lflag & P_LTHSIGSTACK;
706
707
708 if (uctx.uc_onstack & 01) {
709 if (uthsigaltstack != 0)
710 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
711 else
9bccf70c 712 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
4452a7af
A
713 } else {
714 if (uthsigaltstack != 0)
715 ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
716 else
717 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
718 }
de355530 719
55e303ae 720 ut->uu_sigmask = uctx.uc_sigmask & ~sigcantmask;
9bccf70c 721 if (ut->uu_siglist & ~ut->uu_sigmask)
91447636 722 signal_setast(current_thread());
9bccf70c 723
55e303ae
A
724 vec_used = 0;
725 switch (infostyle) {
726 case UC_FLAVOR64_VEC:
727 case UC_TRAD64_VEC:
728 vec_used = 1;
729 case UC_TRAD64:
730 case UC_FLAVOR64: {
731 p_64mctx = (struct mcontext64 *)mactx;
732 tsptr = (void *)&p_64mctx->ss;
733 fptr = (void *)&p_64mctx->fs;
734 vptr = (void *)&p_64mctx->vs;
735 state_flavor = PPC_THREAD_STATE64;
736 state_count = PPC_THREAD_STATE64_COUNT;
737 }
738 break;
739 case UC_FLAVOR_VEC :
740 case UC_TRAD_VEC :
741 vec_used = 1;
742 case UC_FLAVOR :
743 case UC_TRAD :
744 default: {
745 p_mctx = (struct mcontext *)mactx;
746 tsptr = (void *)&p_mctx->ss;
747 fptr = (void *)&p_mctx->fs;
748 vptr = (void *)&p_mctx->vs;
749 state_flavor = PPC_THREAD_STATE;
750 state_count = PPC_THREAD_STATE_COUNT;
751 }
752 break;
753 } /* switch () */
1c79356b 754
55e303ae
A
755 /* validate the thread state, set/reset appropriate mode bits in srr1 */
756 (void)ppc_checkthreadstate(tsptr, state_flavor);
1c79356b 757
91447636 758 if (thread_setstatus(th_act, state_flavor, tsptr, state_count) != KERN_SUCCESS) {
1c79356b
A
759 return(EINVAL);
760 }
761
762 state_count = PPC_FLOAT_STATE_COUNT;
91447636 763 if (thread_setstatus(th_act, PPC_FLOAT_STATE, fptr, state_count) != KERN_SUCCESS) {
1c79356b
A
764 return(EINVAL);
765 }
9bccf70c
A
766
767 mask = sigmask(SIGFPE);
768 if (((ut->uu_sigmask & mask) == 0) && (p->p_sigcatch & mask) && ((p->p_sigignore & mask) == 0)) {
769 action = ps->ps_sigact[SIGFPE];
770 if((action != SIG_DFL) && (action != SIG_IGN)) {
771 thread_enable_fpe(th_act, 1);
772 }
773 }
774
775 if (vec_used) {
776 state_count = PPC_VECTOR_STATE_COUNT;
91447636 777 if (thread_setstatus(th_act, PPC_VECTOR_STATE, vptr, state_count) != KERN_SUCCESS) {
9bccf70c
A
778 return(EINVAL);
779 }
780 }
1c79356b
A
781 return (EJUSTRETURN);
782}
783
784/*
785 * machine_exception() performs MD translation
786 * of a mach exception to a unix signal and code.
787 */
788
789boolean_t
790machine_exception(
791 int exception,
792 int code,
91447636 793 __unused int subcode,
1c79356b
A
794 int *unix_signal,
795 int *unix_code
796)
797{
798 switch(exception) {
799
800 case EXC_BAD_INSTRUCTION:
801 *unix_signal = SIGILL;
802 *unix_code = code;
803 break;
804
805 case EXC_ARITHMETIC:
806 *unix_signal = SIGFPE;
807 *unix_code = code;
808 break;
809
810 case EXC_SOFTWARE:
811 if (code == EXC_PPC_TRAP) {
812 *unix_signal = SIGTRAP;
813 *unix_code = code;
814 break;
815 } else
816 return(FALSE);
817
818 default:
819 return(FALSE);
820 }
821
822 return(TRUE);
823}
824