|
|
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.