]>
git.saurik.com Git - apple/xnu.git/blob - bsd/dev/ppc/unix_signal.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
26 #include <mach/mach_types.h>
27 #include <mach/exception_types.h>
29 #include <sys/param.h>
33 #include <ppc/signal.h>
34 #include <sys/signalvar.h>
35 #include <kern/thread.h>
36 #include <kern/thread_act.h>
37 #include <mach/ppc/thread_status.h>
39 #define C_REDZONE_LEN 224
40 #define C_STK_ALIGN 16
41 #define C_PARAMSAVE_LEN 64
42 #define C_LINKAGE_LEN 48
43 #define TRUNC_DOWN(a,b,c) (((((unsigned)a)-(b))/(c)) * (c))
46 * Arrange for this process to run a signal handler
51 struct ppc_saved_state ss
;
52 struct ppc_float_state fs
;
56 sendsig(p
, catcher
, sig
, mask
, code
)
62 struct sigregs
*p_regs
;
63 struct sigcontext context
, *p_context
;
64 struct sigacts
*ps
= p
->p_sigacts
;
68 struct ppc_saved_state statep
;
69 struct ppc_float_state fs
;
70 unsigned long state_count
;
71 struct thread
*thread
;
73 unsigned long paramp
,linkp
;
75 thread
= current_thread();
76 th_act
= current_act();
78 state_count
= PPC_THREAD_STATE_COUNT
;
79 if (act_machine_get_state(th_act
, PPC_THREAD_STATE
, &statep
, &state_count
) != KERN_SUCCESS
) {
82 state_count
= PPC_FLOAT_STATE_COUNT
;
83 if (act_machine_get_state(th_act
, PPC_FLOAT_STATE
, &fs
, &state_count
) != KERN_SUCCESS
) {
87 oonstack
= ps
->ps_sigstk
.ss_flags
& SA_ONSTACK
;
89 /* figure out where our new stack lives */
90 if ((ps
->ps_flags
& SAS_ALTSTACK
) && !oonstack
&&
91 (ps
->ps_sigonstack
& sigmask(sig
))) {
92 sp
= (unsigned long)(ps
->ps_sigstk
.ss_sp
);
93 sp
+= ps
->ps_sigstk
.ss_size
;
94 ps
->ps_sigstk
.ss_flags
|= SA_ONSTACK
;
99 // preserve RED ZONE area
100 sp
= TRUNC_DOWN(sp
, C_REDZONE_LEN
, C_STK_ALIGN
);
102 // context goes first on stack
103 sp
-= sizeof(*p_context
);
104 p_context
= (struct sigcontext
*) sp
;
106 // next are the saved registers
107 sp
-= sizeof(*p_regs
);
108 p_regs
= (struct sigregs
*)sp
;
110 // C calling conventions, create param save and linkage
113 sp
= TRUNC_DOWN(sp
, C_PARAMSAVE_LEN
, C_STK_ALIGN
);
118 /* fill out sigcontext */
119 context
.sc_onstack
= oonstack
;
120 context
.sc_mask
= mask
;
121 context
.sc_ir
= statep
.srr0
;
122 context
.sc_psw
= statep
.srr1
;
123 context
.sc_regs
= p_regs
;
125 /* copy info out to user space */
126 if (copyout((caddr_t
)&context
, (caddr_t
)p_context
, sizeof(context
)))
128 if (copyout((caddr_t
)&statep
, (caddr_t
)&p_regs
->ss
,
129 sizeof(struct ppc_saved_state
)))
131 if (copyout((caddr_t
)&fs
, (caddr_t
)&p_regs
->fs
,
132 sizeof(struct ppc_float_state
)))
135 /* Place our arguments in arg registers: rtm dependent */
137 statep
.r3
= (unsigned long)sig
;
138 statep
.r4
= (unsigned long)code
;
139 statep
.r5
= (unsigned long)p_context
;
141 statep
.srr0
= (unsigned long)catcher
;
142 statep
.srr1
= get_msr_exportmask(); /* MSR_EXPORT_MASK_SET */
144 state_count
= PPC_THREAD_STATE_COUNT
;
145 if (act_machine_set_state(th_act
, PPC_THREAD_STATE
, &statep
, &state_count
) != KERN_SUCCESS
) {
152 SIGACTION(p
, SIGILL
) = SIG_DFL
;
153 sig
= sigmask(SIGILL
);
154 p
->p_sigignore
&= ~sig
;
155 p
->p_sigcatch
&= ~sig
;
156 p
->p_sigmask
&= ~sig
;
157 /* sendsig is called with signal lock held */
158 psignal_lock(p
, SIGILL
, 0, 1);
163 * System call to cleanup state after a signal
164 * has been taken. Reset signal mask and
165 * stack state from context left by sendsig (above).
166 * Return to previous pc and psl as specified by
167 * context left by sendsig. Check carefully to
168 * make sure that the user has not modified the
169 * psl to gain improper priviledges or to cause
172 struct sigreturn_args
{
173 struct sigcontext
*sigcntxp
;
178 sigreturn(p
, uap
, retval
)
180 struct sigreturn_args
*uap
;
183 struct sigcontext context
;
184 struct sigregs
*p_regs
;
186 struct thread
*thread
;
188 struct ppc_saved_state statep
;
189 struct ppc_float_state fs
;
190 unsigned long state_count
;
191 unsigned int nbits
, rbits
;
193 thread
= current_thread();
194 th_act
= current_act();
196 if (error
= copyin(uap
->sigcntxp
, &context
, sizeof(context
))) {
199 state_count
= PPC_THREAD_STATE_COUNT
;
200 if (act_machine_get_state(th_act
, PPC_THREAD_STATE
, &statep
, &state_count
) != KERN_SUCCESS
) {
203 state_count
= PPC_FLOAT_STATE_COUNT
;
204 if (act_machine_get_state(th_act
, PPC_FLOAT_STATE
, &fs
, &state_count
) != KERN_SUCCESS
) {
207 nbits
= get_msr_nbits();
208 rbits
= get_msr_rbits();
209 /* adjust the critical fields */
210 /* make sure naughty bits are off */
211 context
.sc_psw
&= ~(nbits
);
212 /* make sure necessary bits are on */
213 context
.sc_psw
|= (rbits
);
215 // /* we return from sigreturns as if we faulted in */
216 // entry->es_flags = (entry->es_flags & ~ES_GATEWAY) | ES_TRAP;
218 if (context
.sc_regs
) {
219 p_regs
= (struct sigregs
*)context
.sc_regs
;
220 if (error
= copyin(&p_regs
->ss
, &statep
,
221 sizeof(struct ppc_saved_state
)))
224 if (error
= copyin(&p_regs
->fs
, &fs
,
225 sizeof(struct ppc_float_state
)))
230 statep
.r1
= context
.sc_sp
;
232 // entry->es_general.saved.stack_pointer = context.sc_sp;
234 if (context
.sc_onstack
& 01)
235 p
->p_sigacts
->ps_sigstk
.ss_flags
|= SA_ONSTACK
;
237 p
->p_sigacts
->ps_sigstk
.ss_flags
&= ~SA_ONSTACK
;
238 p
->p_sigmask
= context
.sc_mask
&~ sigcantmask
;
239 statep
.srr0
= context
.sc_ir
;
240 statep
.srr1
= context
.sc_psw
;
242 state_count
= PPC_THREAD_STATE_COUNT
;
243 if (act_machine_set_state(th_act
, PPC_THREAD_STATE
, &statep
, &state_count
) != KERN_SUCCESS
) {
247 state_count
= PPC_FLOAT_STATE_COUNT
;
248 if (act_machine_set_state(th_act
, PPC_FLOAT_STATE
, &fs
, &state_count
) != KERN_SUCCESS
) {
251 return (EJUSTRETURN
);
255 * machine_exception() performs MD translation
256 * of a mach exception to a unix signal and code.
270 case EXC_BAD_INSTRUCTION
:
271 *unix_signal
= SIGILL
;
276 *unix_signal
= SIGFPE
;
281 if (code
== EXC_PPC_TRAP
) {
282 *unix_signal
= SIGTRAP
;