|
|
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) 1999 Apple Computer, Inc. All rights reserved.
24: */
25:
26: #include <mach/mach_types.h>
27: #include <mach/exception_types.h>
28:
29: #include <sys/param.h>
30: #include <sys/proc.h>
31: #include <sys/user.h>
32:
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>
38:
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))
44:
45: /*
46: * Arrange for this process to run a signal handler
47: */
48:
49:
50: struct sigregs {
51: struct ppc_saved_state ss;
52: struct ppc_float_state fs;
53: };
54:
55: void
56: sendsig(p, catcher, sig, mask, code)
57: struct proc *p;
58: sig_t catcher;
59: int sig, mask;
60: u_long code;
61: {
62: struct sigregs *p_regs;
63: struct sigcontext context, *p_context;
64: struct sigacts *ps = p->p_sigacts;
65: int framesize;
66: int oonstack;
67: unsigned long sp;
68: struct ppc_saved_state statep;
69: struct ppc_float_state fs;
70: unsigned long state_count;
71: struct thread *thread;
72: thread_act_t th_act;
73: unsigned long paramp,linkp;
74:
75: thread = current_thread();
76: th_act = current_act();
77:
78: state_count = PPC_THREAD_STATE_COUNT;
79: if (act_machine_get_state(th_act, PPC_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) {
80: goto bad;
81: }
82: state_count = PPC_FLOAT_STATE_COUNT;
83: if (act_machine_get_state(th_act, PPC_FLOAT_STATE, &fs, &state_count) != KERN_SUCCESS) {
84: goto bad;
85: }
86:
87: oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK;
88:
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;
95: }
96: else
97: sp = statep.r1;
98:
99: // preserve RED ZONE area
100: sp = TRUNC_DOWN(sp, C_REDZONE_LEN, C_STK_ALIGN);
101:
102: // context goes first on stack
103: sp -= sizeof(*p_context);
104: p_context = (struct sigcontext *) sp;
105:
106: // next are the saved registers
107: sp -= sizeof(*p_regs);
108: p_regs = (struct sigregs *)sp;
109:
110: // C calling conventions, create param save and linkage
111: // areas
112:
113: sp = TRUNC_DOWN(sp, C_PARAMSAVE_LEN, C_STK_ALIGN);
114: paramp = sp;
115: sp -= C_LINKAGE_LEN;
116: linkp = sp;
117:
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;
124:
125: /* copy info out to user space */
126: if (copyout((caddr_t)&context, (caddr_t)p_context, sizeof(context)))
127: goto bad;
128: if (copyout((caddr_t)&statep, (caddr_t)&p_regs->ss,
129: sizeof(struct ppc_saved_state)))
130: goto bad;
131: if (copyout((caddr_t)&fs, (caddr_t)&p_regs->fs,
132: sizeof(struct ppc_float_state)))
133: goto bad;
134:
135: /* Place our arguments in arg registers: rtm dependent */
136:
137: statep.r3 = (unsigned long)sig;
138: statep.r4 = (unsigned long)code;
139: statep.r5 = (unsigned long)p_context;
140:
141: statep.srr0 = (unsigned long)catcher;
142: statep.srr1 = get_msr_exportmask(); /* MSR_EXPORT_MASK_SET */
143: statep.r1 = sp;
144: state_count = PPC_THREAD_STATE_COUNT;
145: if (act_machine_set_state(th_act, PPC_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) {
146: goto bad;
147: }
148:
149: return;
150:
151: bad:
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: psignal(p, SIGILL);
158: return;
159: }
160:
161: /*
162: * System call to cleanup state after a signal
163: * has been taken. Reset signal mask and
164: * stack state from context left by sendsig (above).
165: * Return to previous pc and psl as specified by
166: * context left by sendsig. Check carefully to
167: * make sure that the user has not modified the
168: * psl to gain improper priviledges or to cause
169: * a machine fault.
170: */
171: struct sigreturn_args {
172: struct sigcontext *sigcntxp;
173: };
174:
175: /* ARGSUSED */
176: int
177: sigreturn(p, uap, retval)
178: struct proc *p;
179: struct sigreturn_args *uap;
180: int *retval;
181: {
182: struct sigcontext context;
183: struct sigregs *p_regs;
184: int error;
185: struct thread *thread;
186: thread_act_t th_act;
187: struct ppc_saved_state statep;
188: struct ppc_float_state fs;
189: unsigned long state_count;
190: unsigned int nbits, rbits;
191:
192: thread = current_thread();
193: th_act = current_act();
194:
195: if (error = copyin(uap->sigcntxp, &context, sizeof(context))) {
196: return(error);
197: }
198: state_count = PPC_THREAD_STATE_COUNT;
199: if (act_machine_get_state(th_act, PPC_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) {
200: return(EINVAL);
201: }
202: state_count = PPC_FLOAT_STATE_COUNT;
203: if (act_machine_get_state(th_act, PPC_FLOAT_STATE, &fs, &state_count) != KERN_SUCCESS) {
204: return(EINVAL);
205: }
206: nbits = get_msr_nbits();
207: rbits = get_msr_rbits();
208: /* adjust the critical fields */
209: /* make sure naughty bits are off */
210: context.sc_psw &= ~(nbits);
211: /* make sure necessary bits are on */
212: context.sc_psw |= (rbits);
213:
214: // /* we return from sigreturns as if we faulted in */
215: // entry->es_flags = (entry->es_flags & ~ES_GATEWAY) | ES_TRAP;
216:
217: if (context.sc_regs) {
218: p_regs = (struct sigregs *)context.sc_regs;
219: if (error = copyin(&p_regs->ss, &statep,
220: sizeof(struct ppc_saved_state)))
221: return(error);
222:
223: if (error = copyin(&p_regs->fs, &fs,
224: sizeof(struct ppc_float_state)))
225: return(error);
226:
227: }
228: else {
229: statep.r1 = context.sc_sp;
230: }
231: // entry->es_general.saved.stack_pointer = context.sc_sp;
232:
233: if (context.sc_onstack & 01)
234: p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
235: else
236: p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
237: p->p_sigmask = context.sc_mask &~ sigcantmask;
238: statep.srr0 = context.sc_ir;
239: statep.srr1 = context.sc_psw;
240:
241: state_count = PPC_THREAD_STATE_COUNT;
242: if (act_machine_set_state(th_act, PPC_THREAD_STATE, &statep, &state_count) != KERN_SUCCESS) {
243: return(EINVAL);
244: }
245:
246: state_count = PPC_FLOAT_STATE_COUNT;
247: if (act_machine_set_state(th_act, PPC_FLOAT_STATE, &fs, &state_count) != KERN_SUCCESS) {
248: return(EINVAL);
249: }
250: return (EJUSTRETURN);
251: }
252:
253: /*
254: * machine_exception() performs MD translation
255: * of a mach exception to a unix signal and code.
256: */
257:
258: boolean_t
259: machine_exception(
260: int exception,
261: int code,
262: int subcode,
263: int *unix_signal,
264: int *unix_code
265: )
266: {
267: switch(exception) {
268:
269: case EXC_BAD_INSTRUCTION:
270: *unix_signal = SIGILL;
271: *unix_code = code;
272: break;
273:
274: case EXC_ARITHMETIC:
275: *unix_signal = SIGFPE;
276: *unix_code = code;
277: break;
278:
279: case EXC_SOFTWARE:
280: if (code == EXC_PPC_TRAP) {
281: *unix_signal = SIGTRAP;
282: *unix_code = code;
283: break;
284: } else
285: return(FALSE);
286:
287: default:
288: return(FALSE);
289: }
290:
291: return(TRUE);
292: }
293:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.