|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.