X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/cf03f5cdc65293b4cb5eba3ed23fed26dad903c9..de355530ae67247cbd0da700edb3a2a1dae884c2:/bsd/dev/ppc/unix_signal.c diff --git a/bsd/dev/ppc/unix_signal.c b/bsd/dev/ppc/unix_signal.c index 941ae0fe6..bc2a1f20f 100644 --- a/bsd/dev/ppc/unix_signal.c +++ b/bsd/dev/ppc/unix_signal.c @@ -3,22 +3,19 @@ * * @APPLE_LICENSE_HEADER_START@ * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -41,6 +38,7 @@ #include #include #include +#define __ELF__ 0 #include #define C_REDZONE_LEN 224 @@ -49,41 +47,6 @@ #define C_LINKAGE_LEN 48 #define TRUNC_DOWN(a,b,c) (((((unsigned)a)-(b))/(c)) * (c)) -/* - * The stack layout possibilities (info style); This needs to mach with signal trampoline code - * - * Traditional: 1 - * Traditional64: 20 - * Traditional64with vec: 25 - * 32bit context 30 - * 32bit context with vector 35 - * 64bit context 40 - * 64bit context with vector 45 - * Dual context 50 - * Dual context with vector 55 - * - */ - -#define UC_TRAD 1 -#define UC_TRAD64 20 -#define UC_TRAD64_VEC 25 -#define UC_FLAVOR 30 -#define UC_FLAVOR_VEC 35 -#define UC_FLAVOR64 40 -#define UC_FLAVOR64_VEC 45 -#define UC_DUAL 50 -#define UC_DUAL_VEC 55 - - /* The following are valid mcontext sizes */ -#define UC_FLAVOR_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int)) - -#define UC_FLAVOR_VEC_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int)) - -#define UC_FLAVOR64_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int)) - -#define UC_FLAVOR64_VEC_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int)) - - /* * Arrange for this process to run a signal handler */ @@ -96,7 +59,6 @@ sendsig(p, catcher, sig, mask, code) u_long code; { struct mcontext mctx, *p_mctx; - struct mcontext64 mctx64, *p_mctx64; struct ucontext uctx, *p_uctx; siginfo_t sinfo, *p_sinfo; struct sigacts *ps = p->p_sigacts; @@ -107,115 +69,42 @@ sendsig(p, catcher, sig, mask, code) thread_act_t th_act; struct uthread *ut; unsigned long paramp,linkp; - int infostyle = UC_TRAD; - int dualcontext =0; + int infostyle = 1; sig_t trampact; int vec_used = 0; int stack_size = 0; int stack_flags = 0; - void * tstate; - int flavor; - int ctx32 = 1; - int is_64signalregset(void); th_act = current_act(); ut = get_bsdthread_info(th_act); - - if (p->p_sigacts->ps_siginfo & sigmask(sig)) { - infostyle = UC_FLAVOR; - } - if(is_64signalregset() && (infostyle == UC_FLAVOR)) { - dualcontext = 1; - infostyle = UC_DUAL; - } - if (p->p_sigacts->ps_64regset & sigmask(sig)) { - dualcontext = 0; - ctx32 = 0; - infostyle = UC_FLAVOR64; - } - if (is_64signalregset() && (infostyle == UC_TRAD)) { - ctx32=0; - infostyle = UC_TRAD64; - } - - /* I need this for SIGINFO anyway */ - flavor = PPC_THREAD_STATE; - tstate = (void *)&mctx.ss; + state_count = PPC_EXCEPTION_STATE_COUNT; + if (act_machine_get_state(th_act, PPC_EXCEPTION_STATE, &mctx.es, &state_count) != KERN_SUCCESS) { + goto bad; + } state_count = PPC_THREAD_STATE_COUNT; - if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS) + if (act_machine_get_state(th_act, PPC_THREAD_STATE, &mctx.ss, &state_count) != KERN_SUCCESS) { goto bad; - - if ((ctx32 == 0) || dualcontext) { - flavor = PPC_THREAD_STATE64; - tstate = (void *)&mctx64.ss; - state_count = PPC_THREAD_STATE64_COUNT; - if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS) - goto bad; - } - - if ((ctx32 == 1) || dualcontext) { - flavor = PPC_EXCEPTION_STATE; - tstate = (void *)&mctx.es; - state_count = PPC_EXCEPTION_STATE_COUNT; - if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS) - goto bad; - } - - if ((ctx32 == 0) || dualcontext) { - flavor = PPC_EXCEPTION_STATE64; - tstate = (void *)&mctx64.es; - state_count = PPC_EXCEPTION_STATE64_COUNT; - - if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS) - goto bad; - - } - - - if ((ctx32 == 1) || dualcontext) { - flavor = PPC_FLOAT_STATE; - tstate = (void *)&mctx.fs; - state_count = PPC_FLOAT_STATE_COUNT; - if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS) - goto bad; - } - - if ((ctx32 == 0) || dualcontext) { - flavor = PPC_FLOAT_STATE; - tstate = (void *)&mctx64.fs; - state_count = PPC_FLOAT_STATE_COUNT; - if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS) - goto bad; - - } - + } + state_count = PPC_FLOAT_STATE_COUNT; + if (act_machine_get_state(th_act, PPC_FLOAT_STATE, &mctx.fs, &state_count) != KERN_SUCCESS) { + goto bad; + } vec_save(th_act); if (find_user_vec(th_act)) { vec_used = 1; - - if ((ctx32 == 1) || dualcontext) { - flavor = PPC_VECTOR_STATE; - tstate = (void *)&mctx.vs; - state_count = PPC_VECTOR_STATE_COUNT; - if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS) - goto bad; - infostyle += 5; - } - - if ((ctx32 == 0) || dualcontext) { - flavor = PPC_VECTOR_STATE; - tstate = (void *)&mctx64.vs; - state_count = PPC_VECTOR_STATE_COUNT; - if (thread_getstatus(th_act, flavor, (thread_state_t)tstate, &state_count) != KERN_SUCCESS) - goto bad; - infostyle += 5; - } - } + state_count = PPC_VECTOR_STATE_COUNT; + if (act_machine_get_state(th_act, PPC_VECTOR_STATE, &mctx.vs, &state_count) != KERN_SUCCESS) { + goto bad; + } + + } trampact = ps->ps_trampact[sig]; oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK; + if (p->p_sigacts->ps_siginfo & sigmask(sig)) + infostyle = 2; /* figure out where our new stack lives */ if ((ps->ps_flags & SAS_ALTSTACK) && !oonstack && @@ -225,30 +114,13 @@ sendsig(p, catcher, sig, mask, code) stack_size = ps->ps_sigstk.ss_size; ps->ps_sigstk.ss_flags |= SA_ONSTACK; } - else { - if (ctx32 == 0) - sp = (unsigned int)mctx64.ss.r1; - else - sp = mctx.ss.r1; - } + else + sp = mctx.ss.r1; - - /* put siginfo on top */ - /* preserve RED ZONE area */ sp = TRUNC_DOWN(sp, C_REDZONE_LEN, C_STK_ALIGN); - /* next are the saved registers */ - if ((ctx32 == 0) || dualcontext) { - sp -= sizeof(*p_mctx64); - p_mctx64 = (struct mcontext64 *)sp; - } - if ((ctx32 == 1) || dualcontext) { - sp -= sizeof(*p_mctx); - p_mctx = (struct mcontext *)sp; - } - - /* context goes first on stack */ + /* context goes first on stack */ sp -= sizeof(*p_uctx); p_uctx = (struct ucontext *) sp; @@ -256,9 +128,13 @@ sendsig(p, catcher, sig, mask, code) sp -= sizeof(*p_sinfo); p_sinfo = (siginfo_t *) sp; + /* next are the saved registers */ + sp -= sizeof(*p_mctx); + p_mctx = (struct mcontext *)sp; + /* C calling conventions, create param save and linkage - * areas - */ + * areas + */ sp = TRUNC_DOWN(sp, C_PARAMSAVE_LEN, C_STK_ALIGN); paramp = sp; @@ -273,25 +149,14 @@ sendsig(p, catcher, sig, mask, code) uctx.uc_stack.ss_flags |= SS_ONSTACK; uctx.uc_link = 0; - if (ctx32 == 0) - uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE64_COUNT + PPC_THREAD_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int)); - else - uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE_COUNT + PPC_THREAD_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int)); - + uctx.uc_mcsize = (size_t)((PPC_EXCEPTION_STATE_COUNT + PPC_THREAD_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int)); if (vec_used) uctx.uc_mcsize += (size_t)(PPC_VECTOR_STATE_COUNT * sizeof(int)); - - if (ctx32 == 0) - uctx.uc_mcontext = (void *)p_mctx64; - else - uctx.uc_mcontext = (void *)p_mctx; + uctx.uc_mcontext = p_mctx; /* setup siginfo */ bzero((caddr_t)&sinfo, sizeof(siginfo_t)); sinfo.si_signo = sig; - sinfo.si_addr = (void *)mctx.ss.srr0; - sinfo.pad[0] = (unsigned int)mctx.ss.r1; - switch (sig) { case SIGCHLD: sinfo.si_pid = p->si_pid; @@ -365,23 +230,13 @@ sendsig(p, catcher, sig, mask, code) break; } - /* copy info out to user space */ if (copyout((caddr_t)&uctx, (caddr_t)p_uctx, sizeof(struct ucontext))) goto bad; if (copyout((caddr_t)&sinfo, (caddr_t)p_sinfo, sizeof(siginfo_t))) goto bad; - if ((ctx32 == 0) || dualcontext) { - tstate = &mctx64; - if (copyout((caddr_t)tstate, (caddr_t)p_mctx64, uctx.uc_mcsize)) + if (copyout((caddr_t)&mctx, (caddr_t)p_mctx, uctx.uc_mcsize)) goto bad; - } - if ((ctx32 == 1) || dualcontext) { - tstate = &mctx; - if (copyout((caddr_t)tstate, (caddr_t)p_mctx, uctx.uc_mcsize)) - goto bad; - } - /* Place our arguments in arg registers: rtm dependent */ @@ -395,9 +250,10 @@ sendsig(p, catcher, sig, mask, code) mctx.ss.srr1 = get_msr_exportmask(); /* MSR_EXPORT_MASK_SET */ mctx.ss.r1 = sp; state_count = PPC_THREAD_STATE_COUNT; - if (thread_setstatus(th_act, PPC_THREAD_STATE, &mctx.ss, &state_count) != KERN_SUCCESS) { + if (act_machine_set_state(th_act, PPC_THREAD_STATE, &mctx.ss, &state_count) != KERN_SUCCESS) { goto bad; } + return; bad: @@ -421,121 +277,8 @@ bad: * psl to gain improper priviledges or to cause * a machine fault. */ - -#define FOR64_TRANSITION 1 - -#ifdef FOR64_TRANSITION - -struct osigreturn_args { - struct ucontext *uctx; -}; - -/* ARGSUSED */ -int -osigreturn(p, uap, retval) - struct proc *p; - struct osigreturn_args *uap; - int *retval; -{ - struct ucontext uctx; - struct ucontext *p_uctx; - struct mcontext64 mctx64; - struct mcontext64 *p_64mctx; - struct mcontext *p_mctx; - int error; - thread_act_t th_act; - struct sigacts *ps = p->p_sigacts; - sigset_t mask; - register sig_t action; - unsigned long state_count; - unsigned int state_flavor; - struct uthread * ut; - int vec_used = 0; - void *tsptr, *fptr, *vptr, *mactx; - void ppc_checkthreadstate(void *, int); - - th_act = current_act(); - /* lets use the larger one */ - mactx = (void *)&mctx64; - - ut = (struct uthread *)get_bsdthread_info(th_act); - if (error = copyin(uap->uctx, &uctx, sizeof(struct ucontext))) { - return(error); - } - if (error = copyin(uctx.uc_mcontext, mactx, uctx.uc_mcsize)) { - return(error); - } - - if (uctx.uc_onstack & 01) - p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; - else - p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; - - ut->uu_sigmask = uctx.uc_sigmask & ~sigcantmask; - if (ut->uu_siglist & ~ut->uu_sigmask) - signal_setast(current_act()); - - vec_used = 0; - switch (uctx.uc_mcsize) { - case UC_FLAVOR64_VEC_SIZE : - vec_used = 1; - case UC_FLAVOR64_SIZE : { - p_64mctx = (struct mcontext64 *)mactx; - tsptr = (void *)&p_64mctx->ss; - fptr = (void *)&p_64mctx->fs; - vptr = (void *)&p_64mctx->vs; - state_flavor = PPC_THREAD_STATE64; - state_count = PPC_THREAD_STATE64_COUNT; - } - break; - case UC_FLAVOR_VEC_SIZE : - vec_used = 1; - case UC_FLAVOR_SIZE: - default: { - p_mctx = (struct mcontext *)mactx; - tsptr = (void *)&p_mctx->ss; - fptr = (void *)&p_mctx->fs; - vptr = (void *)&p_mctx->vs; - state_flavor = PPC_THREAD_STATE; - state_count = PPC_THREAD_STATE_COUNT; - } - break; - } /* switch () */ - - /* validate the thread state, set/reset appropriate mode bits in srr1 */ - (void)ppc_checkthreadstate(tsptr, state_flavor); - - if (thread_setstatus(th_act, state_flavor, tsptr, &state_count) != KERN_SUCCESS) { - return(EINVAL); - } - - state_count = PPC_FLOAT_STATE_COUNT; - if (thread_setstatus(th_act, PPC_FLOAT_STATE, fptr, &state_count) != KERN_SUCCESS) { - return(EINVAL); - } - - mask = sigmask(SIGFPE); - if (((ut->uu_sigmask & mask) == 0) && (p->p_sigcatch & mask) && ((p->p_sigignore & mask) == 0)) { - action = ps->ps_sigact[SIGFPE]; - if((action != SIG_DFL) && (action != SIG_IGN)) { - thread_enable_fpe(th_act, 1); - } - } - - if (vec_used) { - state_count = PPC_VECTOR_STATE_COUNT; - if (thread_setstatus(th_act, PPC_VECTOR_STATE, vptr, &state_count) != KERN_SUCCESS) { - return(EINVAL); - } - } - return (EJUSTRETURN); -} - -#endif /* FOR64_TRANSITION */ - struct sigreturn_args { struct ucontext *uctx; - int infostyle; }; /* ARGSUSED */ @@ -545,23 +288,19 @@ sigreturn(p, uap, retval) struct sigreturn_args *uap; int *retval; { - struct ucontext uctx; - struct ucontext *p_uctx; - char mactx[sizeof(struct mcontext64)]; - struct mcontext *p_mctx; - struct mcontext64 *p_64mctx; + struct ucontext uctx, *p_uctx; + struct mcontext mctx, *p_mctx; int error; thread_act_t th_act; + struct ppc_float_state fs; + struct ppc_exception_state es; struct sigacts *ps = p->p_sigacts; sigset_t mask; register sig_t action; unsigned long state_count; - unsigned int state_flavor; + unsigned int nbits, rbits; struct uthread * ut; int vec_used = 0; - void *tsptr, *fptr, *vptr; - int infostyle = uap->infostyle; - void ppc_checkthreadstate(void *, int); th_act = current_act(); @@ -569,9 +308,7 @@ sigreturn(p, uap, retval) if (error = copyin(uap->uctx, &uctx, sizeof(struct ucontext))) { return(error); } - - - if (error = copyin(uctx.uc_mcontext, mactx, uctx.uc_mcsize)) { + if (error = copyin(uctx.uc_mcontext, &mctx, sizeof(struct mcontext))) { return(error); } @@ -579,49 +316,32 @@ sigreturn(p, uap, retval) p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; else p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; - ut->uu_sigmask = uctx.uc_sigmask & ~sigcantmask; + + if (ut->uu_siglist & ~ut->uu_sigmask) signal_setast(current_act()); - vec_used = 0; - switch (infostyle) { - case UC_FLAVOR64_VEC: - case UC_TRAD64_VEC: - vec_used = 1; - case UC_TRAD64: - case UC_FLAVOR64: { - p_64mctx = (struct mcontext64 *)mactx; - tsptr = (void *)&p_64mctx->ss; - fptr = (void *)&p_64mctx->fs; - vptr = (void *)&p_64mctx->vs; - state_flavor = PPC_THREAD_STATE64; - state_count = PPC_THREAD_STATE64_COUNT; - } - break; - case UC_FLAVOR_VEC : - vec_used = 1; - case UC_FLAVOR : - default: { - p_mctx = (struct mcontext *)mactx; - tsptr = (void *)&p_mctx->ss; - fptr = (void *)&p_mctx->fs; - vptr = (void *)&p_mctx->vs; - state_flavor = PPC_THREAD_STATE; - state_count = PPC_THREAD_STATE_COUNT; - } - break; - } /* switch () */ + nbits = get_msr_nbits(); + rbits = get_msr_rbits(); + /* adjust the critical fields */ + /* make sure naughty bits are off */ + mctx.ss.srr1 &= ~(nbits); + /* make sure necessary bits are on */ + mctx.ss.srr1 |= (rbits); - /* validate the thread state, set/reset appropriate mode bits in srr1 */ - (void)ppc_checkthreadstate(tsptr, state_flavor); + state_count = (size_t)((PPC_EXCEPTION_STATE_COUNT + PPC_THREAD_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int)); - if (thread_setstatus(th_act, state_flavor, tsptr, &state_count) != KERN_SUCCESS) { + if (uctx.uc_mcsize > state_count) + vec_used = 1; + + state_count = PPC_THREAD_STATE_COUNT; + if (act_machine_set_state(th_act, PPC_THREAD_STATE, &mctx.ss, &state_count) != KERN_SUCCESS) { return(EINVAL); } state_count = PPC_FLOAT_STATE_COUNT; - if (thread_setstatus(th_act, PPC_FLOAT_STATE, fptr, &state_count) != KERN_SUCCESS) { + if (act_machine_set_state(th_act, PPC_FLOAT_STATE, &mctx.fs, &state_count) != KERN_SUCCESS) { return(EINVAL); } @@ -635,10 +355,11 @@ sigreturn(p, uap, retval) if (vec_used) { state_count = PPC_VECTOR_STATE_COUNT; - if (thread_setstatus(th_act, PPC_VECTOR_STATE, vptr, &state_count) != KERN_SUCCESS) { + if (act_machine_set_state(th_act, PPC_VECTOR_STATE, &mctx.vs, &state_count) != KERN_SUCCESS) { return(EINVAL); } } + return (EJUSTRETURN); }