2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
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>
33 ** Function: NotifyInterruption
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
49 syscall_notify_interrupt(mach_port_t
, UInt32
, UInt32
*, EmulatorDescriptor
*,
50 void ** , void **, void *);
53 syscall_notify_interrupt( mach_port_t port_thread
,
54 UInt32 ppcInterruptHandler
,
55 UInt32
* interruptStatePtr
,
56 EmulatorDescriptor
* emulatorDescriptor
,
62 struct ppc_saved_state
*mainPCB
;
63 thread_t thread
, nthread
;
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;
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))
77 act
= port_name_to_act(port_thread
);
80 if (act
== THR_ACT_NULL
)
83 runningInKernel
= (act
->mact
.ksp
== 0);
84 isSelf
= (current_act() == act
);
87 /* First.. suspend the thread */
88 result
= thread_suspend(act
);
95 /* Now try to find and wait for any pending activitations
96 * to complete.. (the following is an expansion of
100 thread
= act_lock_thread(act
);
102 act_unlock_thread(act
);
110 if (!thread
|| act
!= thread
->top_act
)
113 act_unlock_thread(act
);
114 (void) thread_stop_wait(thread
);
115 nthread
= act_lock_thread(act
);
116 if (nthread
== thread
)
118 thread_unstop(thread
);
126 currentState
= kOutsideMain
;
128 currentState
= (interruptState
& kInterruptStateMask
) >> kInterruptStateShift
;
130 if (debugNotify
> 5) {
131 printf("\nNotifyInterruption: %X, %X, %X, %X, %X, %X\n",
132 port_thread
, ppcInterruptHandler
, interruptStatePtr
,
133 emulatorDescriptor
, originalPC
, originalR2
);
135 mainPCB
= USER_REGS(act
);
137 switch (currentState
)
140 case kInUninitialized
:
142 printf("NotifyInterrupt: kInUninitialized\n");
145 case kInPseudoKernel
:
148 printf("NotifyInterrupt: kInPseudoKernel/kOutsideMain\n");
149 interruptState
= interruptState
150 | ((postIntMask
>> kCR2ToBackupShift
) & kBackupCR2Mask
);
154 case kInSystemContext
:
156 printf("kInSystemContext: old CR %x, postIntMask %x, new CR %x\n",
157 mainPCB
->cr
, postIntMask
, mainPCB
->cr
| postIntMask
);
158 mainPCB
->cr
|= postIntMask
;
161 case kInAlternateContext
:
163 printf("kInAlternateContext: IN InterruptState %x, postIntMask %x\n",
164 interruptState
, postIntMask
);
165 interruptState
= interruptState
| ((postIntMask
>> kCR2ToBackupShift
) & kBackupCR2Mask
);
166 interruptState
= (interruptState
& ~kInterruptStateMask
);
169 interruptState
|= (kNotifyPending
<< kInterruptStateShift
);
171 interruptState
|= (kInPseudoKernel
<< kInterruptStateShift
);
173 (void) copyout((char *)&mainPCB
->srr0
, (char *)originalPC
, sizeof(originalPC
));
174 (void) copyout((char *)&mainPCB
->r2
, (char *)originalR2
, sizeof(originalR2
));
177 printf("kInAlternateContext: Out interruptState %x, Old PC %x, New %x, R2 %x\n",
178 interruptState
, mainPCB
->srr0
, ppcInterruptHandler
, mainPCB
->r2
);
180 mainPCB
->srr0
= ppcInterruptHandler
;
183 case kInExceptionHandler
:
185 printf("NotifyInterrupt: kInExceptionHandler\n");
186 interruptState
= interruptState
| ((postIntMask
>> kCR2ToBackupShift
) & kBackupCR2Mask
);
192 printf("NotifyInterrupt: default ");
193 printf("Interruption while running in unknown state\n");
194 printf("interruptState = 0x%X\n",currentState
);
199 if (thread
&& act
== thread
->top_act
)
200 thread_unstop(thread
);
202 act_unlock_thread(act
);