Annotation of XNU/osfmk/ppc/notify_interrupt.c, revision 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.