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