Annotation of XNU/osfmk/ppc/notify_interrupt.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: #include <mach/kern_return.h>
                     23: #include <kern/thread.h>
                     24: #include <ppc/exception.h>
                     25: #include <kern/ipc_tt.h>
                     26: #include <ipc/ipc_port.h>
                     27: #include <ppc/atomic_switch.h>
                     28: #include <kern/thread_act.h>
                     29: 
                     30: int    debugNotify = 0;
                     31: 
                     32: /*
                     33: ** Function:   NotifyInterruption
                     34: **
                     35: ** Inputs:     port                    - mach_port for main thread
                     36: **             ppcInterrupHandler      - interrupt handler to execute
                     37: **             interruptStatePtr       - current interrupt state
                     38: **             emulatorDescriptor      - where in emulator to notify
                     39: **             originalPC              - where the emulator was executing
                     40: **             originalR2              - new R2
                     41: **
                     42: ** Outputs:
                     43: **
                     44: ** Notes:
                     45: **
                     46: */
                     47: 
                     48: unsigned long
                     49: syscall_notify_interrupt(mach_port_t, UInt32, UInt32 *, EmulatorDescriptor *,
                     50:                                void ** , void **, void *);
                     51: 
                     52: unsigned long
                     53: syscall_notify_interrupt(      mach_port_t             port_thread,
                     54:                                UInt32                  ppcInterruptHandler,
                     55:                                UInt32 *                interruptStatePtr,
                     56:                                EmulatorDescriptor *    emulatorDescriptor,
                     57:                                void **                 originalPC,
                     58:                                void **                 originalR2,
                     59:                                void                    *othread )
                     60: {
                     61:     kern_return_t      result; 
                     62:     struct ppc_saved_state     *mainPCB;
                     63:     thread_t           thread, nthread;
                     64:     thread_act_t       act;
                     65:     UInt32             interruptState, currentState, postIntMask;
                     66:     extern thread_act_t port_name_to_act(mach_port_t);
                     67:     boolean_t          isSelf, runningInKernel;
                     68:        static unsigned long    sequence =0;
                     69: 
                     70: #define        COPYIN_INTSTATE() { \
                     71:        (void) copyin((char *) interruptStatePtr, (char *)&interruptState, sizeof(interruptState)); \
                     72:        if (emulatorDescriptor) \
                     73:                (void) copyin((char *) &emulatorDescriptor->postIntMask, (char *)&postIntMask, sizeof(postIntMask));  }
                     74: #define        COPYOUT_INTSTATE() (void) copyout((char *) &interruptState, (char *)interruptStatePtr, sizeof(interruptState))
                     75: 
                     76: 
                     77:     act = port_name_to_act(port_thread);
                     78: 
                     79:    
                     80:     if (act == THR_ACT_NULL) 
                     81:        return port_thread;
                     82: 
                     83:     runningInKernel = (act->mact.ksp == 0);
                     84:     isSelf = (current_act() == act);
                     85: 
                     86:     if (!isSelf) {
                     87:        /* First.. suspend the thread */
                     88:            result = thread_suspend(act);
                     89:        
                     90:            if (result) {
                     91:                act_deallocate(act);
                     92:                return port_thread;
                     93:           }
                     94:        
                     95:            /* Now try to find and wait for any pending activitations
                     96:             * to complete.. (the following is an expansion of 
                     97:             * thread_set_state())
                     98:             */
                     99:        
                    100:            thread = act_lock_thread(act);
                    101:            if (!act->active) {
                    102:                act_unlock_thread(act);
                    103:                act_deallocate(act);
                    104:                return port_thread;
                    105:           }
                    106:        
                    107:           thread_hold(act);
                    108:        
                    109:           while (1) {
                    110:                if (!thread || act != thread->top_act)
                    111:                        break;
                    112:        
                    113:                act_unlock_thread(act);
                    114:                (void) thread_stop_wait(thread);
                    115:                nthread = act_lock_thread(act);
                    116:                if (nthread == thread)
                    117:                        break;
                    118:                thread_unstop(thread);
                    119:                thread = nthread;
                    120:           }
                    121:        
                    122:        }
                    123: 
                    124:        COPYIN_INTSTATE()
                    125:        if (isSelf)
                    126:                currentState = kOutsideMain;
                    127:        else
                    128:                currentState = (interruptState & kInterruptStateMask) >> kInterruptStateShift; 
                    129: 
                    130:     if (debugNotify > 5) {
                    131:        printf("\nNotifyInterruption: %X, %X, %X, %X, %X, %X\n",
                    132:                port_thread, ppcInterruptHandler, interruptStatePtr,
                    133:                emulatorDescriptor, originalPC, originalR2 );
                    134:     }
                    135:     mainPCB = USER_REGS(act);
                    136: 
                    137:     switch (currentState)
                    138:     {
                    139:     case kNotifyPending:
                    140:     case kInUninitialized:
                    141:        if (debugNotify > 2)
                    142:                printf("NotifyInterrupt: kInUninitialized\n");
                    143:        break;
                    144:                
                    145:     case kInPseudoKernel:
                    146:     case kOutsideMain:
                    147:        if (debugNotify > 2)
                    148:                printf("NotifyInterrupt: kInPseudoKernel/kOutsideMain\n");
                    149:        interruptState = interruptState
                    150:                | ((postIntMask >> kCR2ToBackupShift) & kBackupCR2Mask);
                    151:        COPYOUT_INTSTATE();
                    152:        break;
                    153:                
                    154:     case kInSystemContext:
                    155:        if (debugNotify > 2) 
                    156:                printf("kInSystemContext: old CR %x, postIntMask %x, new CR %x\n",
                    157:                mainPCB->cr, postIntMask, mainPCB->cr | postIntMask);
                    158:        mainPCB->cr |= postIntMask;
                    159:        break;
                    160:                
                    161:     case kInAlternateContext:
                    162:        if (debugNotify > 2)
                    163:        printf("kInAlternateContext: IN InterruptState %x, postIntMask %x\n",
                    164:                        interruptState, postIntMask);
                    165:        interruptState = interruptState | ((postIntMask >> kCR2ToBackupShift) & kBackupCR2Mask);
                    166:        interruptState = (interruptState & ~kInterruptStateMask);
                    167: 
                    168:        if (runningInKernel)
                    169:                interruptState |= (kNotifyPending << kInterruptStateShift);
                    170:        else
                    171:                interruptState |= (kInPseudoKernel << kInterruptStateShift);
                    172:                
                    173:        (void) copyout((char *)&mainPCB->srr0, (char *)originalPC, sizeof(originalPC));
                    174:        (void) copyout((char *)&mainPCB->r2, (char *)originalR2, sizeof(originalR2));
                    175:        COPYOUT_INTSTATE();
                    176:        if (debugNotify > 2)
                    177:        printf("kInAlternateContext: Out interruptState %x, Old PC %x, New %x, R2 %x\n",
                    178:                interruptState, mainPCB->srr0, ppcInterruptHandler, mainPCB->r2);
                    179: 
                    180:        mainPCB->srr0 = ppcInterruptHandler;
                    181:        break;
                    182:                
                    183:     case kInExceptionHandler:
                    184:        if (debugNotify > 2)
                    185:                printf("NotifyInterrupt: kInExceptionHandler\n");
                    186:        interruptState = interruptState | ((postIntMask >> kCR2ToBackupShift) & kBackupCR2Mask);
                    187:        COPYOUT_INTSTATE();
                    188:        break;
                    189:                
                    190:     default:
                    191:        if (debugNotify)
                    192:                printf("NotifyInterrupt: default ");
                    193:                printf("Interruption while running in unknown state\n");
                    194:                printf("interruptState = 0x%X\n",currentState);
                    195:        break;
                    196:     }
                    197: 
                    198:        if (!isSelf) {
                    199:                if (thread && act == thread->top_act)
                    200:                        thread_unstop(thread);
                    201:                thread_release(act);
                    202:                act_unlock_thread(act);
                    203:                thread_resume(act);
                    204:        }
                    205: 
                    206:     act_deallocate(act);
                    207: 
                    208:    return port_thread;
                    209: }

unix.superglobalmegacorp.com

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