2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 #include <mach/kern_return.h>
26 #include <kern/thread.h>
27 #include <ppc/exception.h>
28 #include <kern/ipc_tt.h>
29 #include <ipc/ipc_port.h>
30 #include <ppc/atomic_switch.h>
31 #include <kern/thread_act.h>
36 ** Function: NotifyInterruption
38 ** Inputs: port - mach_port for main thread
39 ** ppcInterrupHandler - interrupt handler to execute
40 ** interruptStatePtr - current interrupt state
41 ** emulatorDescriptor - where in emulator to notify
42 ** originalPC - where the emulator was executing
43 ** originalR2 - new R2
52 syscall_notify_interrupt(mach_port_t
, UInt32
, UInt32
*, EmulatorDescriptor
*,
53 void ** , void **, void *);
56 syscall_notify_interrupt( mach_port_t port_thread
,
57 UInt32 ppcInterruptHandler
,
58 UInt32
* interruptStatePtr
,
59 EmulatorDescriptor
* emulatorDescriptor
,
65 struct ppc_saved_state
*mainPCB
;
66 thread_t thread
, nthread
;
68 UInt32 interruptState
, currentState
, postIntMask
;
69 extern thread_act_t
port_name_to_act(mach_port_t
);
70 boolean_t isSelf
, runningInKernel
;
71 static unsigned long sequence
=0;
73 #define COPYIN_INTSTATE() { \
74 (void) copyin((char *) interruptStatePtr, (char *)&interruptState, sizeof(interruptState)); \
75 if (emulatorDescriptor) \
76 (void) copyin((char *) &emulatorDescriptor->postIntMask, (char *)&postIntMask, sizeof(postIntMask)); }
77 #define COPYOUT_INTSTATE() (void) copyout((char *) &interruptState, (char *)interruptStatePtr, sizeof(interruptState))
80 act
= port_name_to_act(port_thread
);
83 if (act
== THR_ACT_NULL
)
86 runningInKernel
= (act
->mact
.ksp
== 0);
87 isSelf
= (current_act() == act
);
90 /* First.. suspend the thread */
91 result
= thread_suspend(act
);
98 /* Now try to find and wait for any pending activitations
99 * to complete.. (the following is an expansion of
100 * thread_set_state())
103 thread
= act_lock_thread(act
);
105 act_unlock_thread(act
);
113 if (!thread
|| act
!= thread
->top_act
)
116 act_unlock_thread(act
);
117 (void) thread_stop_wait(thread
);
118 nthread
= act_lock_thread(act
);
119 if (nthread
== thread
)
121 thread_unstop(thread
);
129 currentState
= kOutsideMain
;
131 currentState
= (interruptState
& kInterruptStateMask
) >> kInterruptStateShift
;
133 if (debugNotify
> 5) {
134 printf("\nNotifyInterruption: %X, %X, %X, %X, %X, %X\n",
135 port_thread
, ppcInterruptHandler
, interruptStatePtr
,
136 emulatorDescriptor
, originalPC
, originalR2
);
138 mainPCB
= USER_REGS(act
);
140 switch (currentState
)
143 case kInUninitialized
:
145 printf("NotifyInterrupt: kInUninitialized\n");
148 case kInPseudoKernel
:
151 printf("NotifyInterrupt: kInPseudoKernel/kOutsideMain\n");
152 interruptState
= interruptState
153 | ((postIntMask
>> kCR2ToBackupShift
) & kBackupCR2Mask
);
157 case kInSystemContext
:
159 printf("kInSystemContext: old CR %x, postIntMask %x, new CR %x\n",
160 mainPCB
->cr
, postIntMask
, mainPCB
->cr
| postIntMask
);
161 mainPCB
->cr
|= postIntMask
;
164 case kInAlternateContext
:
166 printf("kInAlternateContext: IN InterruptState %x, postIntMask %x\n",
167 interruptState
, postIntMask
);
168 interruptState
= interruptState
| ((postIntMask
>> kCR2ToBackupShift
) & kBackupCR2Mask
);
169 interruptState
= (interruptState
& ~kInterruptStateMask
);
172 interruptState
|= (kNotifyPending
<< kInterruptStateShift
);
174 interruptState
|= (kInPseudoKernel
<< kInterruptStateShift
);
176 (void) copyout((char *)&mainPCB
->srr0
, (char *)originalPC
, sizeof(originalPC
));
177 (void) copyout((char *)&mainPCB
->r2
, (char *)originalR2
, sizeof(originalR2
));
180 printf("kInAlternateContext: Out interruptState %x, Old PC %x, New %x, R2 %x\n",
181 interruptState
, mainPCB
->srr0
, ppcInterruptHandler
, mainPCB
->r2
);
183 mainPCB
->srr0
= ppcInterruptHandler
;
186 case kInExceptionHandler
:
188 printf("NotifyInterrupt: kInExceptionHandler\n");
189 interruptState
= interruptState
| ((postIntMask
>> kCR2ToBackupShift
) & kBackupCR2Mask
);
195 printf("NotifyInterrupt: default ");
196 printf("Interruption while running in unknown state\n");
197 printf("interruptState = 0x%X\n",currentState
);
202 if (thread
&& act
== thread
->top_act
)
203 thread_unstop(thread
);
205 act_unlock_thread(act
);