Annotation of XNU/bsd/dev/ppc/unix_signal.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.