|
|
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.