|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1997 Apple Computer, Inc.
27: *
28: * PowerPC Family: System Call handlers.
29: *
30: * HISTORY
31: * 18-Aug-97 Umesh Vaishampayan ([email protected])
32: * Added syscalltrace filtering.
33: * 27-July-97 Umesh Vaishampayan ([email protected])
34: * Debug printf() changed to kprintf(). Cleanup unused system timing.
35: */
36:
37: #include <mach/mach_types.h>
38: #include <mach/exception.h>
39: #include <mach/error.h>
40:
41: #include <kern/syscall_sw.h>
42: #include <kern/kdp.h>
43: #include <kern/kdebug.h>
44:
45: #include <machdep/ppc/frame.h>
46: #include <machdep/ppc/thread.h>
47: #include <machdep/ppc/asm.h>
48: #include <machdep/ppc/proc_reg.h>
49: #include <machdep/ppc/trap.h>
50: #include <machdep/ppc/exception.h>
51: #include <machdep/ppc/pcb_flags.h>
52:
53: #include <sys/param.h>
54: #include <sys/proc.h>
55: #include <sys/user.h>
56: #include <sys/systm.h>
57:
58: #if DIAGNOSTIC
59: /* syscalltrace defines */
60: #define _SCT_NUM_PIDS 8
61:
62: #define _SCT_OFF 0x00
63: #define _SCT_MACHCALLS 0x01
64: #define _SCT_UNIXCALLS 0x02
65: #define _SCT_ALL (_SCT_MACHCALLS | _SCT_UNIXCALLS)
66:
67: int syscalltrace = 0;
68: int usepids = 0; /* 1 enables pid filtering */
69: int pidstraced[_SCT_NUM_PIDS]; /* can specify upto _SCT_NUM_PIDS to filter */
70:
71: static int
72: matchpid( int pid )
73: {
74: int i;
75: for(i=0; i<_SCT_NUM_PIDS; i++)
76: if( pidstraced[i] == pid )
77: return 1; /* match! */
78: return 0; /* not found */
79: }
80:
81: #endif /* DIAGNOSTIC */
82:
83: /*
84: ** Function: mach_syscall
85: **
86: ** Inputs: pcb - pointer to Process Control Block
87: ** arg1 - arguments to mach system calls
88: ** arg2
89: ** arg3
90: ** arg4
91: ** arg5
92: ** arg6
93: ** arg7
94: **
95: ** Outputs: none
96: **
97: ** Notes: There may be additional arguments to the mach calls
98: ** that will be read in from user space if necessary
99: */
100: void
101: mach_syscall(
102: struct pcb * pcb,
103: int arg1,
104: int arg2,
105: int arg3,
106: int arg4,
107: int arg5,
108: int arg6,
109: int arg7
110: )
111: {
112: struct ppc_saved_state *regs;
113: int error; /* error code */
114: struct uthread *uthread;
115: struct proc *p;
116:
117: /* the mach trap number supplied by libmach */
118: int mach_trap;
119: mach_trap_t *trapp;
120: thread_t thread;
121: int arg0;
122: struct stack_frame *usfp;
123: int sbargs[4], uasfp, *argp;
124: extern char *mach_callnames[];
125:
126:
127: if (!USERMODE(pcb->ss.srr1))
128: panic("mach_syscall");
129:
130: regs = &pcb->ss;
131:
132: thread = current_thread();
133: uthread = thread->_uthread;
134: uthread->uu_ar0 = (int *)pcb;
135: p = current_proc();
136:
137: /* get the mach trap number */
138: mach_trap = -(regs->r0);
139:
140: /* get the first argument to the mach trap call */
141: arg0 = regs->r3;
142:
143: error = 0;
144:
145: /* find mach trap table entry */
146: if (mach_trap >= mach_trap_count || mach_trap < 0)
147: {
148: error = KERN_FAILURE;
149: }
150: else
151: {
152: trapp = &mach_trap_table[mach_trap];
153:
154: if (trapp->mach_trap_arg_count > MAXREGARGS)
155: {
156: int i, word;
157:
158: /*
159: ** This code gets executed when there are more than MAXREGARGS
160: ** worth of parameters expected for the call. The additional
161: ** parameters are passed on the users stack and must be copies
162: ** in from user space.
163: */
164: if (trapp->mach_trap_arg_count > NARGS)
165: panic("mach_syscall: max arg count exceeded");
166:
167: /* get the user stack frame pointer from saved state r1 */
168: usfp = (struct stack_frame *)regs->r1;
169:
170: /* set up a pointer to the user arguments stack frame pointer */
171: uasfp = (int)&usfp->pa.spa.saved_p8;
172:
173: /* setup the pointer for the stack based args */
174: argp = sbargs;
175:
176: for (i = 0; i < (trapp->mach_trap_arg_count - MAXREGARGS); i++ )
177: {
178: if (copyin ((void *)uasfp++, (void *)&word, sizeof(int)))
179: {
180: regs->r3 = -1;
181: thread_exception_return();
182: }
183: *argp++ = word;
184: }
185: }
186:
187: #if DIAGNOSTIC
188: if ((syscalltrace == _SCT_MACHCALLS) || (syscalltrace == _SCT_ALL)) {
189: int trpid = ((p) ? p->p_pid : -1);
190: if((!usepids) || (usepids && matchpid(trpid)))
191: kprintf("%s (%d) mach_syscall[%d = %s] --",
192: ((p) ? p->p_comm : "no-proc"),
193: trpid, mach_trap, mach_callnames[mach_trap]);
194: }
195: #endif /* DIAGNOSTIC */
196: /*
197: ** Notice that there are always NARGS passed into the mach_trap
198: ** regardless whether they are needed or not.
199: **
200: ** If NARGS changes this function call must be changed as well!!
201: */
202: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_EXCP_SC, 0) | DBG_FUNC_START,
203: mach_trap, arg0, arg1, arg2, arg3);
204:
205: error = (*(trapp->mach_trap_function))( arg0, arg1,
206: arg2, arg3,
207: arg4, arg5,
208: arg6, arg7,
209: sbargs[0], sbargs[1],
210: sbargs[2], sbargs[3] );
211:
212: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_EXCP_SC, 0) | DBG_FUNC_END,
213: mach_trap, error, 0, 0, 0);
214: #if DIAGNOSTIC
215: if ((syscalltrace == _SCT_MACHCALLS) || (syscalltrace == _SCT_ALL)) {
216: int trpid = ((p) ? p->p_pid : -1);
217: if((!usepids) || (usepids && matchpid(trpid))) {
218: if (error)
219: kprintf("> sys=0x%X, sub=0x%X, code=0x%X\n",
220: err_get_system(error), err_get_sub(error),
221: err_get_code(error));
222: else
223: kprintf("> error == 0x%X\n", error);
224: }
225: }
226: #endif /* DIAGNOSTIC */
227: }
228:
229: regs->r3 = error;
230:
231: thread_exception_return();
232: /* NOTREACHED */
233: }
234:
235:
236: /*
237: ** Function: unix_syscall
238: **
239: ** Inputs: pcb - pointer to Process Control Block
240: ** arg1 - arguments to mach system calls
241: ** arg2
242: ** arg3
243: ** arg4
244: ** arg5
245: ** arg6
246: ** arg7
247: **
248: ** Outputs: none
249: */
250: void
251: unix_syscall(
252: struct pcb * pcb,
253: int arg1,
254: int arg2,
255: int arg3,
256: int arg4,
257: int arg5,
258: int arg6,
259: int arg7
260: )
261: {
262: struct ppc_saved_state *regs;
263: thread_t thread;
264: struct uthread *uthread;
265: struct sysent *callp;
266: struct proc *p;
267: int nargs, error;
268: unsigned short code;
269: int rval[2];
270: extern char *syscallnames[];
271:
272: if (!USERMODE(pcb->ss.srr1))
273: panic("unix_syscall");
274:
275: regs = &pcb->ss;
276: thread = current_thread();
277:
278: uthread = thread->_uthread;
279: uthread->uu_ar0 = (int *)pcb;
280: p = current_proc();
281:
282: /*
283: ** Get index into sysent table
284: */
285: code = regs->r0;
286:
287: if (code > nsysent)
288: {
289: error = 0;
290: switch (code) {
291: case 0x7FFA:
292: if ((thread->pcb->flags & PCB_BB_MASK) == 0) {
293: error = EPERM;
294: break;
295: }
296: NotifyInterruption(regs->r3,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
297: break;
298: case 0x7FFF:
299: mapBlueBoxShmem(regs->r3,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
300: break;
301: case 0x7FFD:
302: unmapBlueBoxShmem(regs->r3,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
303: break;
304: }
305: }
306: else {
307: /*
308: ** Set up call pointer
309: */
310: callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
311:
312: /*
313: ** SPECIAL CASE function 0 to be indirect system call
314: */
315: if (callp == sysent)
316: {
317: code = regs->r3;
318: callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
319: uthread->uu_arg[0] = arg1;
320: uthread->uu_arg[1] = arg2;
321: uthread->uu_arg[2] = arg3;
322: uthread->uu_arg[3] = arg4;
323: uthread->uu_arg[4] = arg5;
324: uthread->uu_arg[5] = arg6;
325: uthread->uu_arg[6] = arg7;
326: }
327: else
328: {
329: /*
330: ** Set up the args for the system call
331: */
332: uthread->uu_arg[0] = regs->r3;
333: uthread->uu_arg[1] = arg1;
334: uthread->uu_arg[2] = arg2;
335: uthread->uu_arg[3] = arg3;
336: uthread->uu_arg[4] = arg4;
337: uthread->uu_arg[5] = arg5;
338: uthread->uu_arg[6] = arg6;
339: uthread->uu_arg[7] = arg7;
340: }
341:
342: if (callp->sy_narg > 8)
343: panic("unix_syscall: max arg count exceeded");
344:
345: rval[0] = 0;
346:
347: /* r4 is volatile, if we set it to regs->r4 here the child
348: * will have parents r4 after execve */
349: rval[1] = 0;
350:
351: error = 0; /* Start with a good value */
352:
353: /*
354: ** the PPC runtime calls cerror after every unix system call, so
355: ** assume no error and adjust the "pc" to skip this call.
356: ** It will be set back to the cerror call if an error is detected.
357: */
358: regs->srr0 += 4;
359: #if DIAGNOSTIC
360: if ((syscalltrace == _SCT_UNIXCALLS) || (syscalltrace == _SCT_ALL)) {
361: int trpid = ((p) ? p->p_pid : -1);
362: if((!usepids) || (usepids && matchpid(trpid))) {
363: kprintf("%s(%d) unix_syscall[%d = %s] --",
364: ((p) ? p->p_comm : "no-proc"),
365: trpid, code, syscallnames[code]);
366: if ( (code == 5) || (code == 59) )
367: kprintf(" arg0 = %x, arg1 = %d, arg2 = %d, "
368: "arg3 = %d --",
369: uthread->uu_arg[0], uthread->uu_arg[1],
370: uthread->uu_arg[2], uthread->uu_arg[3]);
371: }
372: }
373: #endif /* DIAGNOSTIC */
374: #if KDEBUG
375: if (code != 180) {
376: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_EXCP_SC, 1) | DBG_FUNC_START,
377: code, uthread->uu_arg[0], uthread->uu_arg[1],
378: uthread->uu_arg[2], uthread->uu_arg[3]);
379: }
380: #endif /* KDEBUG */
381:
382: error = (*(callp->sy_call))(p, (caddr_t)uthread->uu_arg, rval);
383:
384: #if KDEBUG
385: if (code != 180) {
386: KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_EXCP_SC, 1) | DBG_FUNC_END,
387: code, error, rval[0], rval[1], 0);
388: }
389: #endif /* KDEBUG */
390: #if DIAGNOSTIC
391: if ((syscalltrace == _SCT_UNIXCALLS) || (syscalltrace == _SCT_ALL)) {
392: int trpid = ((p) ? p->p_pid : -1);
393: if((!usepids) || (usepids && matchpid(trpid)))
394: if (error)
395: kprintf("> error == 0x%X\n", error);
396: else
397: kprintf("> rval=0x%X %X\n", rval[0],rval[1]);
398: }
399: #endif /* DIAGNOSTIC */
400: }
401: if (error == ERESTART) {
402: regs->srr0 -= 8;
403: }
404: else if (error != EJUSTRETURN) {
405: if (error)
406: {
407: regs->r3 = error;
408: /* set the "pc" to execute cerror routine */
409: regs->srr0 -= 4;
410: } else { /* (not error) */
411: regs->r3 = rval[0];
412: regs->r4 = rval[1];
413: }
414: }
415: /* else (error == EJUSTRETURN) { nothing } */
416:
417: thread_exception_return();
418: /* NOTREACHED */
419:
420: }
421:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.