2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
34 #include <mach/mach_types.h>
35 #include <mach/exception_types.h>
37 #include <sys/param.h>
38 #include <sys/proc_internal.h>
40 #include <sys/ucontext.h>
41 #include <sys/sysproto.h>
42 #include <sys/systm.h>
43 #include <sys/ux_exception.h>
45 #include <ppc/signal.h>
46 #include <sys/signalvar.h>
47 #include <sys/kdebug.h>
49 #include <kern/thread.h>
50 #include <mach/ppc/thread_status.h>
51 #include <ppc/proc_reg.h>
53 // #include <machine/thread.h> XXX include path messed up for some reason...
55 /* XXX functions not in a Mach headers */
56 extern kern_return_t
thread_getstatus(register thread_t act
, int flavor
,
57 thread_state_t tstate
, mach_msg_type_number_t
*count
);
58 extern int is_64signalregset(void);
59 extern unsigned int get_msr_exportmask(void);
60 extern kern_return_t
thread_setstatus(thread_t thread
, int flavor
,
61 thread_state_t tstate
, mach_msg_type_number_t count
);
62 extern void ppc_checkthreadstate(void *, int);
63 extern struct savearea_vec
*find_user_vec_curr(void);
64 extern int thread_enable_fpe(thread_t act
, int onoff
);
68 #define C_32_REDZONE_LEN 224
69 #define C_32_STK_ALIGN 16
70 #define C_32_PARAMSAVE_LEN 64
71 #define C_32_LINKAGE_LEN 48
73 #define C_64_REDZONE_LEN 320
74 #define C_64_STK_ALIGN 32
75 #define C_64_PARAMSAVE_LEN 64
76 #define C_64_LINKAGE_LEN 48
78 #define TRUNC_DOWN32(a,b,c) ((((uint32_t)a)-(b)) & ((uint32_t)(-(c))))
79 #define TRUNC_DOWN64(a,b,c) ((((uint64_t)a)-(b)) & ((uint64_t)(-(c))))
82 * The stack layout possibilities (info style); This needs to mach with signal trampoline code
86 * Traditional64with vec: 25
88 * 32bit context with vector 35
90 * 64bit context with vector 45
92 * Dual context with vector 55
99 #define UC_TRAD64_VEC 25
101 #define UC_FLAVOR_VEC 35
102 #define UC_FLAVOR64 40
103 #define UC_FLAVOR64_VEC 45
105 #define UC_DUAL_VEC 55
107 /* The following are valid mcontext sizes */
108 #define UC_FLAVOR_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
110 #define UC_FLAVOR_VEC_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
112 #define UC_FLAVOR64_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int))
114 #define UC_FLAVOR64_VEC_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int))
118 * NOTE: Source and target may *NOT* overlap!
121 ucontext_32to64(struct ucontext64
*in
, struct user_ucontext64
*out
)
123 out
->uc_onstack
= in
->uc_onstack
;
124 out
->uc_sigmask
= in
->uc_sigmask
;
126 /* internal "structure assign" */
127 out
->uc_stack
.ss_sp
= CAST_USER_ADDR_T(in
->uc_stack
.ss_sp
);
128 out
->uc_stack
.ss_size
= in
->uc_stack
.ss_size
;
129 out
->uc_stack
.ss_flags
= in
->uc_stack
.ss_flags
;
131 out
->uc_link
= CAST_USER_ADDR_T(in
->uc_link
);
132 out
->uc_mcsize
= in
->uc_mcsize
;
133 out
->uc_mcontext64
= CAST_USER_ADDR_T(in
->uc_mcontext64
);
137 * This conversion is safe, since if we are converting for a 32 bit process,
138 * then it's values of uc-stack.ss_size and uc_mcsize will never exceed 4G.
140 * NOTE: Source and target may *NOT* overlap!
143 ucontext_64to32(struct user_ucontext64
*in
, struct ucontext64
*out
)
145 out
->uc_onstack
= in
->uc_onstack
;
146 out
->uc_sigmask
= in
->uc_sigmask
;
148 /* internal "structure assign" */
149 out
->uc_stack
.ss_sp
= CAST_DOWN(void *,in
->uc_stack
.ss_sp
);
150 out
->uc_stack
.ss_size
= in
->uc_stack
.ss_size
; /* range reduction */
151 out
->uc_stack
.ss_flags
= in
->uc_stack
.ss_flags
;
153 out
->uc_link
= CAST_DOWN(void *,in
->uc_link
);
154 out
->uc_mcsize
= in
->uc_mcsize
; /* range reduction */
155 out
->uc_mcontext64
= CAST_DOWN(void *,in
->uc_mcontext64
);
159 * NOTE: Source and target may *NOT* overlap!
162 siginfo_64to32(user_siginfo_t
*in
, siginfo_t
*out
)
164 out
->si_signo
= in
->si_signo
;
165 out
->si_errno
= in
->si_errno
;
166 out
->si_code
= in
->si_code
;
167 out
->si_pid
= in
->si_pid
;
168 out
->si_uid
= in
->si_uid
;
169 out
->si_status
= in
->si_status
;
170 out
->si_addr
= CAST_DOWN(void *,in
->si_addr
);
171 /* following cast works for sival_int because of padding */
172 out
->si_value
.sival_ptr
= CAST_DOWN(void *,in
->si_value
.sival_ptr
);
173 out
->si_band
= in
->si_band
; /* range reduction */
174 out
->pad
[0] = in
->pad
[0]; /* mcontext.ss.r1 */
179 * Arrange for this process to run a signal handler
183 sendsig(struct proc
*p
, user_addr_t catcher
, int sig
, int mask
, __unused u_long code
)
186 struct mcontext mctx
;
187 user_addr_t p_mctx
= USER_ADDR_NULL
; /* mcontext dest. */
188 struct mcontext64 mctx64
;
189 user_addr_t p_mctx64
= USER_ADDR_NULL
; /* mcontext dest. */
190 struct user_ucontext64 uctx
;
191 user_addr_t p_uctx
; /* user stack addr top copy ucontext */
192 user_siginfo_t sinfo
;
193 user_addr_t p_sinfo
; /* user stack addr top copy siginfo */
194 struct sigacts
*ps
= p
->p_sigacts
;
197 mach_msg_type_number_t state_count
;
200 int infostyle
= UC_TRAD
;
202 user_addr_t trampact
;
208 int uthsigaltstack
= 0;
212 th_act
= current_thread();
213 ut
= get_bsdthread_info(th_act
);
216 if (p
->p_sigacts
->ps_siginfo
& sigmask(sig
)) {
217 infostyle
= UC_FLAVOR
;
219 if(is_64signalregset() && (infostyle
== UC_FLAVOR
)) {
223 if (p
->p_sigacts
->ps_64regset
& sigmask(sig
)) {
226 infostyle
= UC_FLAVOR64
;
228 /* treat 64 bit processes as having used 64 bit registers */
229 if ((IS_64BIT_PROCESS(p
) || is_64signalregset()) &&
230 (infostyle
== UC_TRAD
)) {
232 infostyle
= UC_TRAD64
;
234 if (IS_64BIT_PROCESS(p
)) {
239 /* I need this for SIGINFO anyway */
240 flavor
= PPC_THREAD_STATE
;
241 tstate
= (void *)&mctx
.ss
;
242 state_count
= PPC_THREAD_STATE_COUNT
;
243 if (thread_getstatus(th_act
, flavor
, (thread_state_t
)tstate
, &state_count
) != KERN_SUCCESS
)
246 if ((ctx32
== 0) || dualcontext
) {
247 flavor
= PPC_THREAD_STATE64
;
248 tstate
= (void *)&mctx64
.ss
;
249 state_count
= PPC_THREAD_STATE64_COUNT
;
250 if (thread_getstatus(th_act
, flavor
, (thread_state_t
)tstate
, &state_count
) != KERN_SUCCESS
)
254 if ((ctx32
== 1) || dualcontext
) {
255 flavor
= PPC_EXCEPTION_STATE
;
256 tstate
= (void *)&mctx
.es
;
257 state_count
= PPC_EXCEPTION_STATE_COUNT
;
258 if (thread_getstatus(th_act
, flavor
, (thread_state_t
)tstate
, &state_count
) != KERN_SUCCESS
)
262 if ((ctx32
== 0) || dualcontext
) {
263 flavor
= PPC_EXCEPTION_STATE64
;
264 tstate
= (void *)&mctx64
.es
;
265 state_count
= PPC_EXCEPTION_STATE64_COUNT
;
267 if (thread_getstatus(th_act
, flavor
, (thread_state_t
)tstate
, &state_count
) != KERN_SUCCESS
)
273 if ((ctx32
== 1) || dualcontext
) {
274 flavor
= PPC_FLOAT_STATE
;
275 tstate
= (void *)&mctx
.fs
;
276 state_count
= PPC_FLOAT_STATE_COUNT
;
277 if (thread_getstatus(th_act
, flavor
, (thread_state_t
)tstate
, &state_count
) != KERN_SUCCESS
)
281 if ((ctx32
== 0) || dualcontext
) {
282 flavor
= PPC_FLOAT_STATE
;
283 tstate
= (void *)&mctx64
.fs
;
284 state_count
= PPC_FLOAT_STATE_COUNT
;
285 if (thread_getstatus(th_act
, flavor
, (thread_state_t
)tstate
, &state_count
) != KERN_SUCCESS
)
291 if (find_user_vec_curr()) {
294 if ((ctx32
== 1) || dualcontext
) {
295 flavor
= PPC_VECTOR_STATE
;
296 tstate
= (void *)&mctx
.vs
;
297 state_count
= PPC_VECTOR_STATE_COUNT
;
298 if (thread_getstatus(th_act
, flavor
, (thread_state_t
)tstate
, &state_count
) != KERN_SUCCESS
)
303 if ((ctx32
== 0) || dualcontext
) {
304 flavor
= PPC_VECTOR_STATE
;
305 tstate
= (void *)&mctx64
.vs
;
306 state_count
= PPC_VECTOR_STATE_COUNT
;
307 if (thread_getstatus(th_act
, flavor
, (thread_state_t
)tstate
, &state_count
) != KERN_SUCCESS
)
313 trampact
= ps
->ps_trampact
[sig
];
314 uthsigaltstack
= p
->p_lflag
& P_LTHSIGSTACK
;
316 if (uthsigaltstack
!= 0 ) {
317 oonstack
= ut
->uu_sigstk
.ss_flags
& SA_ONSTACK
;
318 altstack
= ut
->uu_flag
& UT_ALTSTACK
;
320 oonstack
= ps
->ps_sigstk
.ss_flags
& SA_ONSTACK
;
321 altstack
= ps
->ps_flags
& SAS_ALTSTACK
;
325 /* figure out where our new stack lives */
326 if (altstack
&& !oonstack
&&
327 (ps
->ps_sigonstack
& sigmask(sig
))) {
328 if (uthsigaltstack
!= 0) {
329 sp
= ut
->uu_sigstk
.ss_sp
;
330 sp
+= ut
->uu_sigstk
.ss_size
;
331 stack_size
= ut
->uu_sigstk
.ss_size
;
332 ut
->uu_sigstk
.ss_flags
|= SA_ONSTACK
;
334 sp
= ps
->ps_sigstk
.ss_sp
;
335 sp
+= ps
->ps_sigstk
.ss_size
;
336 stack_size
= ps
->ps_sigstk
.ss_size
;
337 ps
->ps_sigstk
.ss_flags
|= SA_ONSTACK
;
344 sp
= CAST_USER_ADDR_T(mctx
.ss
.r1
);
348 /* put siginfo on top */
350 /* preserve RED ZONE area */
351 if (IS_64BIT_PROCESS(p
))
352 sp
= TRUNC_DOWN64(sp
, C_64_REDZONE_LEN
, C_64_STK_ALIGN
);
354 sp
= TRUNC_DOWN32(sp
, C_32_REDZONE_LEN
, C_32_STK_ALIGN
);
356 /* next are the saved registers */
357 if ((ctx32
== 0) || dualcontext
) {
358 sp
-= sizeof(struct mcontext64
);
361 if ((ctx32
== 1) || dualcontext
) {
362 sp
-= sizeof(struct mcontext
);
366 if (IS_64BIT_PROCESS(p
)) {
367 /* context goes first on stack */
368 sp
-= sizeof(struct user_ucontext64
);
371 /* this is where siginfo goes on stack */
372 sp
-= sizeof(user_siginfo_t
);
375 sp
= TRUNC_DOWN64(sp
, C_64_PARAMSAVE_LEN
+C_64_LINKAGE_LEN
, C_64_STK_ALIGN
);
378 * struct ucontext and struct ucontext64 are identical in
379 * size and content; the only difference is the internal
380 * pointer type for the last element, which makes no
381 * difference for the copyout().
384 /* context goes first on stack */
385 sp
-= sizeof(struct ucontext64
);
388 /* this is where siginfo goes on stack */
389 sp
-= sizeof(siginfo_t
);
392 sp
= TRUNC_DOWN32(sp
, C_32_PARAMSAVE_LEN
+C_32_LINKAGE_LEN
, C_32_STK_ALIGN
);
395 uctx
.uc_onstack
= oonstack
;
396 uctx
.uc_sigmask
= mask
;
397 uctx
.uc_stack
.ss_sp
= sp
;
398 uctx
.uc_stack
.ss_size
= stack_size
;
400 uctx
.uc_stack
.ss_flags
|= SS_ONSTACK
;
404 uctx
.uc_mcsize
= (size_t)((PPC_EXCEPTION_STATE64_COUNT
+ PPC_THREAD_STATE64_COUNT
+ PPC_FLOAT_STATE_COUNT
) * sizeof(int));
406 uctx
.uc_mcsize
= (size_t)((PPC_EXCEPTION_STATE_COUNT
+ PPC_THREAD_STATE_COUNT
+ PPC_FLOAT_STATE_COUNT
) * sizeof(int));
409 uctx
.uc_mcsize
+= (size_t)(PPC_VECTOR_STATE_COUNT
* sizeof(int));
412 uctx
.uc_mcontext64
= p_mctx64
;
414 uctx
.uc_mcontext64
= p_mctx
;
417 bzero((caddr_t
)&sinfo
, sizeof(user_siginfo_t
));
418 sinfo
.si_signo
= sig
;
420 sinfo
.si_addr
= mctx64
.ss
.srr0
;
421 sinfo
.pad
[0] = mctx64
.ss
.r1
;
423 sinfo
.si_addr
= CAST_USER_ADDR_T(mctx
.ss
.srr0
);
424 sinfo
.pad
[0] = CAST_USER_ADDR_T(mctx
.ss
.r1
);
429 sinfo
.si_pid
= p
->si_pid
;
431 sinfo
.si_status
= p
->si_status
;
433 sinfo
.si_uid
= p
->si_uid
;
435 sinfo
.si_code
= p
->si_code
;
437 if (sinfo
.si_code
== CLD_EXITED
) {
438 if (WIFEXITED(sinfo
.si_status
))
439 sinfo
.si_code
= CLD_EXITED
;
440 else if (WIFSIGNALED(sinfo
.si_status
)) {
441 if (WCOREDUMP(sinfo
.si_status
))
442 sinfo
.si_code
= CLD_DUMPED
;
444 sinfo
.si_code
= CLD_KILLED
;
450 * If it's 64 bit and not a dual context, mctx will
451 * contain uninitialized data, so we have to use
455 if (mctx64
.ss
.srr1
& (1 << (31 - SRR1_PRG_ILL_INS_BIT
)))
456 sinfo
.si_code
= ILL_ILLOPC
;
457 else if (mctx64
.ss
.srr1
& (1 << (31 - SRR1_PRG_PRV_INS_BIT
)))
458 sinfo
.si_code
= ILL_PRVOPC
;
459 else if (mctx64
.ss
.srr1
& (1 << (31 - SRR1_PRG_TRAP_BIT
)))
460 sinfo
.si_code
= ILL_ILLTRP
;
462 sinfo
.si_code
= ILL_NOOP
;
464 if (mctx
.ss
.srr1
& (1 << (31 - SRR1_PRG_ILL_INS_BIT
)))
465 sinfo
.si_code
= ILL_ILLOPC
;
466 else if (mctx
.ss
.srr1
& (1 << (31 - SRR1_PRG_PRV_INS_BIT
)))
467 sinfo
.si_code
= ILL_PRVOPC
;
468 else if (mctx
.ss
.srr1
& (1 << (31 - SRR1_PRG_TRAP_BIT
)))
469 sinfo
.si_code
= ILL_ILLTRP
;
471 sinfo
.si_code
= ILL_NOOP
;
481 * If it's 64 bit and not a dual context, mctx will
482 * contain uninitialized data, so we have to use
486 if (mctx64
.fs
.fpscr
& (1 << (31 - FPSCR_VX
)))
487 sinfo
.si_code
= FPE_FLTINV
;
488 else if (mctx64
.fs
.fpscr
& (1 << (31 - FPSCR_OX
)))
489 sinfo
.si_code
= FPE_FLTOVF
;
490 else if (mctx64
.fs
.fpscr
& (1 << (31 - FPSCR_UX
)))
491 sinfo
.si_code
= FPE_FLTUND
;
492 else if (mctx64
.fs
.fpscr
& (1 << (31 - FPSCR_ZX
)))
493 sinfo
.si_code
= FPE_FLTDIV
;
494 else if (mctx64
.fs
.fpscr
& (1 << (31 - FPSCR_XX
)))
495 sinfo
.si_code
= FPE_FLTRES
;
497 sinfo
.si_code
= FPE_NOOP
;
499 if (mctx
.fs
.fpscr
& (1 << (31 - FPSCR_VX
)))
500 sinfo
.si_code
= FPE_FLTINV
;
501 else if (mctx
.fs
.fpscr
& (1 << (31 - FPSCR_OX
)))
502 sinfo
.si_code
= FPE_FLTOVF
;
503 else if (mctx
.fs
.fpscr
& (1 << (31 - FPSCR_UX
)))
504 sinfo
.si_code
= FPE_FLTUND
;
505 else if (mctx
.fs
.fpscr
& (1 << (31 - FPSCR_ZX
)))
506 sinfo
.si_code
= FPE_FLTDIV
;
507 else if (mctx
.fs
.fpscr
& (1 << (31 - FPSCR_XX
)))
508 sinfo
.si_code
= FPE_FLTRES
;
510 sinfo
.si_code
= FPE_NOOP
;
516 sinfo
.si_addr
= mctx64
.es
.dar
;
518 sinfo
.si_addr
= CAST_USER_ADDR_T(mctx
.es
.dar
);
520 /* on ppc we generate only if EXC_PPC_UNALIGNED */
521 sinfo
.si_code
= BUS_ADRALN
;
526 * If it's 64 bit and not a dual context, mctx will
527 * contain uninitialized data, so we have to use
531 sinfo
.si_addr
= mctx64
.es
.dar
;
532 /* First check in srr1 and then in dsisr */
533 if (mctx64
.ss
.srr1
& (1 << (31 - DSISR_PROT_BIT
)))
534 sinfo
.si_code
= SEGV_ACCERR
;
535 else if (mctx64
.es
.dsisr
& (1 << (31 - DSISR_PROT_BIT
)))
536 sinfo
.si_code
= SEGV_ACCERR
;
538 sinfo
.si_code
= SEGV_MAPERR
;
540 sinfo
.si_addr
= CAST_USER_ADDR_T(mctx
.es
.dar
);
541 /* First check in srr1 and then in dsisr */
542 if (mctx
.ss
.srr1
& (1 << (31 - DSISR_PROT_BIT
)))
543 sinfo
.si_code
= SEGV_ACCERR
;
544 else if (mctx
.es
.dsisr
& (1 << (31 - DSISR_PROT_BIT
)))
545 sinfo
.si_code
= SEGV_ACCERR
;
547 sinfo
.si_code
= SEGV_MAPERR
;
555 /* copy info out to user space */
556 if (IS_64BIT_PROCESS(p
)) {
557 if (copyout(&uctx
, p_uctx
, sizeof(struct user_ucontext64
)))
559 if (copyout(&sinfo
, p_sinfo
, sizeof(user_siginfo_t
)))
562 struct ucontext64 uctx32
;
565 ucontext_64to32(&uctx
, &uctx32
);
566 if (copyout(&uctx32
, p_uctx
, sizeof(struct ucontext64
)))
569 siginfo_64to32(&sinfo
,&sinfo32
);
570 if (copyout(&sinfo32
, p_sinfo
, sizeof(siginfo_t
)))
573 if ((ctx32
== 0) || dualcontext
) {
575 * NOTE: Size of mcontext is not variant between 64bit and
576 * 32bit programs usng 64bit registers.
578 if (copyout(&mctx64
, p_mctx64
, (vec_used
? UC_FLAVOR64_VEC_SIZE
: UC_FLAVOR64_SIZE
)))
581 if ((ctx32
== 1) || dualcontext
) {
582 if (copyout(&mctx
, p_mctx
, uctx
.uc_mcsize
))
587 /* Place our arguments in arg registers: rtm dependent */
588 if(IS_64BIT_PROCESS(p
)) {
589 mctx64
.ss
.r3
= catcher
;
590 mctx64
.ss
.r4
= CAST_USER_ADDR_T(infostyle
);
591 mctx64
.ss
.r5
= CAST_USER_ADDR_T(sig
);
592 mctx64
.ss
.r6
= p_sinfo
;
593 mctx64
.ss
.r7
= p_uctx
;
595 mctx64
.ss
.srr0
= trampact
;
596 /* MSR_EXPORT_MASK_SET */
597 mctx64
.ss
.srr1
= CAST_USER_ADDR_T(get_msr_exportmask());
599 state_count
= PPC_THREAD_STATE64_COUNT
;
600 if ((kretn
= thread_setstatus(th_act
, PPC_THREAD_STATE64
, (void *)&mctx64
.ss
, state_count
)) != KERN_SUCCESS
) {
601 panic("sendsig: thread_setstatus failed, ret = %08X\n", kretn
);
604 mctx
.ss
.r3
= CAST_DOWN(unsigned long,catcher
);
605 mctx
.ss
.r4
= (unsigned long)infostyle
;
606 mctx
.ss
.r5
= (unsigned long)sig
;
607 mctx
.ss
.r6
= CAST_DOWN(unsigned long,p_sinfo
);
608 mctx
.ss
.r7
= CAST_DOWN(unsigned long,p_uctx
);
610 mctx
.ss
.srr0
= CAST_DOWN(unsigned long,trampact
);
611 /* MSR_EXPORT_MASK_SET */
612 mctx
.ss
.srr1
= get_msr_exportmask();
613 mctx
.ss
.r1
= CAST_DOWN(unsigned long,sp
);
614 state_count
= PPC_THREAD_STATE_COUNT
;
615 if ((kretn
= thread_setstatus(th_act
, PPC_THREAD_STATE
, (void *)&mctx
.ss
, state_count
)) != KERN_SUCCESS
) {
616 panic("sendsig: thread_setstatus failed, ret = %08X\n", kretn
);
622 SIGACTION(p
, SIGILL
) = SIG_DFL
;
623 sig
= sigmask(SIGILL
);
624 p
->p_sigignore
&= ~sig
;
625 p
->p_sigcatch
&= ~sig
;
626 ut
->uu_sigmask
&= ~sig
;
627 /* sendsig is called with signal lock held */
628 psignal_lock(p
, SIGILL
, 0);
633 * System call to cleanup state after a signal
634 * has been taken. Reset signal mask and
635 * stack state from context left by sendsig (above).
636 * Return to previous pc and psl as specified by
637 * context left by sendsig. Check carefully to
638 * make sure that the user has not modified the
639 * psl to gain improper priviledges or to cause
645 sigreturn(struct proc
*p
, struct sigreturn_args
*uap
, __unused
int *retval
)
647 struct user_ucontext64 uctx
;
649 char mactx
[sizeof(struct mcontext64
)];
650 struct mcontext
*p_mctx
;
651 struct mcontext64
*p_64mctx
;
654 struct sigacts
*ps
= p
->p_sigacts
;
657 unsigned long state_count
;
658 unsigned int state_flavor
;
661 void *tsptr
, *fptr
, *vptr
;
662 int infostyle
= uap
->infostyle
;
663 int uthsigaltstack
= 0;
665 th_act
= current_thread();
667 ut
= (struct uthread
*)get_bsdthread_info(th_act
);
668 if (IS_64BIT_PROCESS(p
)) {
669 error
= copyin(uap
->uctx
, &uctx
, sizeof(struct user_ucontext64
));
673 struct ucontext64 uctx32
;
676 * struct ucontext and struct ucontext64 are identical in
677 * size and content; the only difference is the internal
678 * pointer type for the last element, which makes no
679 * difference for the copyin().
681 error
= copyin(uap
->uctx
, &uctx32
, sizeof(struct ucontext
));
684 ucontext_32to64(&uctx32
, &uctx
);
688 /* validate the machine context size */
689 switch (uctx
.uc_mcsize
) {
690 case UC_FLAVOR64_VEC_SIZE
:
691 case UC_FLAVOR64_SIZE
:
692 case UC_FLAVOR_VEC_SIZE
:
700 * The 64 bit process mcontext is identical to the mcontext64, so
701 * there is no conversion necessary.
703 error
= copyin(uctx
.uc_mcontext64
, mactx
, uctx
.uc_mcsize
);
707 uthsigaltstack
= p
->p_lflag
& P_LTHSIGSTACK
;
710 if (uctx
.uc_onstack
& 01) {
711 if (uthsigaltstack
!= 0)
712 ut
->uu_sigstk
.ss_flags
|= SA_ONSTACK
;
714 p
->p_sigacts
->ps_sigstk
.ss_flags
|= SA_ONSTACK
;
716 if (uthsigaltstack
!= 0)
717 ut
->uu_sigstk
.ss_flags
&= ~SA_ONSTACK
;
719 p
->p_sigacts
->ps_sigstk
.ss_flags
&= ~SA_ONSTACK
;
722 ut
->uu_sigmask
= uctx
.uc_sigmask
& ~sigcantmask
;
723 if (ut
->uu_siglist
& ~ut
->uu_sigmask
)
724 signal_setast(current_thread());
728 case UC_FLAVOR64_VEC
:
733 p_64mctx
= (struct mcontext64
*)mactx
;
734 tsptr
= (void *)&p_64mctx
->ss
;
735 fptr
= (void *)&p_64mctx
->fs
;
736 vptr
= (void *)&p_64mctx
->vs
;
737 state_flavor
= PPC_THREAD_STATE64
;
738 state_count
= PPC_THREAD_STATE64_COUNT
;
747 p_mctx
= (struct mcontext
*)mactx
;
748 tsptr
= (void *)&p_mctx
->ss
;
749 fptr
= (void *)&p_mctx
->fs
;
750 vptr
= (void *)&p_mctx
->vs
;
751 state_flavor
= PPC_THREAD_STATE
;
752 state_count
= PPC_THREAD_STATE_COUNT
;
757 /* validate the thread state, set/reset appropriate mode bits in srr1 */
758 (void)ppc_checkthreadstate(tsptr
, state_flavor
);
760 if (thread_setstatus(th_act
, state_flavor
, tsptr
, state_count
) != KERN_SUCCESS
) {
764 state_count
= PPC_FLOAT_STATE_COUNT
;
765 if (thread_setstatus(th_act
, PPC_FLOAT_STATE
, fptr
, state_count
) != KERN_SUCCESS
) {
769 mask
= sigmask(SIGFPE
);
770 if (((ut
->uu_sigmask
& mask
) == 0) && (p
->p_sigcatch
& mask
) && ((p
->p_sigignore
& mask
) == 0)) {
771 action
= ps
->ps_sigact
[SIGFPE
];
772 if((action
!= SIG_DFL
) && (action
!= SIG_IGN
)) {
773 thread_enable_fpe(th_act
, 1);
778 state_count
= PPC_VECTOR_STATE_COUNT
;
779 if (thread_setstatus(th_act
, PPC_VECTOR_STATE
, vptr
, state_count
) != KERN_SUCCESS
) {
783 return (EJUSTRETURN
);
787 * machine_exception() performs MD translation
788 * of a mach exception to a unix signal and code.
795 __unused
int subcode
,
802 case EXC_BAD_INSTRUCTION
:
803 *unix_signal
= SIGILL
;
808 *unix_signal
= SIGFPE
;
813 if (code
== EXC_PPC_TRAP
) {
814 *unix_signal
= SIGTRAP
;