1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#include	<ppc/asm.h>
29#include	<ppc/proc_reg.h>
30#include	<ppc/exception.h>
31#include	<mach/ppc/vm_param.h>
32#include	<assym.s>
33
34/*
35 *	Classic atomic switch and fast trap code
36 *	Written by: Mark Gorlinsky
37 */
38
39/*
40**
41** Blue Box Fast Trap entry
42**
43**
44** The registers at entry are as hw_exceptions left them. Which means
45** that the Blue Box data area is pointed to be R26.
46**
47** We exit here through the fast path exit point in hw_exceptions.  That means that
48** upon exit, R4 must not change.  It is the savearea with the current user context
49** to restore.
50**
51** Input registers are:
52** r0  = Syscall number
53** r4  = Current context savearea (do not modify)
54** r13 = THREAD_TOP_ACT pointer
55** r26 = base of ACT_MACH_BDA in kernel address space
56** -- for Traps --
57** r24 = Index into TWI table (x4)
58**
59**
60*/
61
62
63ENTRY(atomic_switch_syscall, TAG_NO_FRAME_USED)
64
65/*
66 *			Note: the BlueBox fast path system calls (-1 and -2) we handled as
67 *			an ultra-fast trap in lowmem_vectors.
68 */
69			lwz		r5,bbSysCall(r13)					; Pick up the syscall vector
70			b		.L_CallPseudoKernel
71
72ENTRY(atomic_switch_trap, TAG_NO_FRAME_USED)
73
74/*
75** functions 0-15 -> Call PseudoKernel
76**             16 -> Exit PseudoKernel
77*/
78
79			cmplwi	cr7,r24,BB_RFI_TRAP					; Is this an RFI?
80			beq		cr7,.L_ExitPseudoKernel				; Yes...
81
82			lwz		r5,bbTrap(r13)						; Pick up the trap vector
83
84/******************************************************************************
85 * void CallPseudoKernel ( int vector, thread_act_t * act, BEDA_t * beda, savearea *sv )
86 *
87 * This op provides a means of invoking the BlueBox PseudoKernel from a
88 * system (68k) or native (PPC) context while changing BlueBox interruption
89 * state atomically.  As an added bonus, this op leaves all but R1/PC of the user
90 * state registers intact.  R1/PC are saved in a per thread save area, the base of
91 * which is located in the bbDescAddr member of the thread_act structure.
92 *
93 * This op is invoked from the Emulator Trap dispatch table or from a System
94 * Call when Mach SCs have been disabled. A vectorindex is passed in to indicate
95 * which vector should be taken.
96 *
97 * If this op is invoked from the Emulator Trap dispatch table, the kernel is
98 * aware of starting address of this table.  It used the users PC (SRR0)
99 * and the start of the Trap dispatch table address to verify the trap exception
100 * as a atomic_switch trap.  If a trap exception is verified as a atomic_switch
101 * trap we enter here with the following registers loaded.
102 *
103 * Input registers are:
104 * r5	= Vector to take
105 * r13 	= Current thread context data
106 * r26	= Base address of BlueBox exception data area in kernel address space
107 * r4	= Current context savearea (do not modify)
108 *
109 ******************************************************************************/
110
111.L_CallPseudoKernel:
112
113			mfsprg	r2,1								; Get the current activation
114			lwz		r2,ACT_PER_PROC(r2)					; Get the per_proc block
115			rlwinm	r6,r26,0,0,19						; Start of page is bttd
116			lwz		r7,ACT_MACT_SPF(r13)				; Get special flags
117			lwz		r1,BTTD_INTERRUPT_VECTOR(r6)		; Get interrupt vector
118			rlwinm	r7,r7,0,bbNoMachSCbit+1,bbNoMachSCbit-1
119														; Reactivate Mach SCs
120			lwz		r8,BTTD_INTCONTROLWORD(r6)			; Get Interrupt Control Word
121			cmpwi	r1,0								; Is this a preemptive thread ?
122			stw		r7,ACT_MACT_SPF(r13)				; Update special flags
123			stw		r7,spcFlags(r2)						; Update per_proc version
124			beq		.L_CallFromPreemptiveThread			; No int vector means preemptive thread
125
126			rlwinm	r1,r8,0,INTSTATEMASK_B,INTSTATEMASK_E
127														; Extract current Interrupt state
128			rlwinm	r8,r8,0,INTSTATEMASK_E+1,INTSTATEMASK_B-1
129														; Clear current interrupt state
130			xoris	r2,r1,SYSCONTEXTSTATE				; Setup for System Context check
131			lwz		r1,savecr(r4)						; Load current CR bits
132			cmpwi	r2,0								; Check if state is System Context?
133			oris	r8,r8,PSEUDOKERNELSTATE				; Update state for entering the PK
134			bne		.L_CallFromAlternateContext			; No, then do not save CR2 bits
135
136			rlwimi	r8,r1,32-INTCR2TOBACKUPSHIFT,INTBACKUPCR2MASK_B,INTBACKUPCR2MASK_E
137														; Insert live CR2 in ICW BackupCR2
138.L_CallFromAlternateContext:
139
140			stw		r8,BTTD_INTCONTROLWORD(r6)			; Update ICW
141
142.L_CallFromPreemptiveThread:
143
144			lwz		r1,savesrr0+4(r4)					; Get current PC
145			lwz		r2,saver1+4(r4)						; Get current R1
146			lwz		r3,savesrr1+4(r4)					; Get current MSR
147			stw		r1,BEDA_SRR0(r26)					; Save current PC
148			rlwinm	r3,r3,0,MSR_BE_BIT+1,MSR_SE_BIT-1
149														; Clear SE|BE bits in MSR
150			stw		r2,BEDA_SPRG1(r26)					; Save current R1
151			stw		r3,savesrr1+4(r4)					; Load new MSR
152
153			lwz		r1,BEDA_SPRG0(r26)					; Get replacement R1
154			stw		r5,savesrr0+4(r4)					; Save vector as PC
155			stw		r3,BEDA_SRR1(r26)					; Update saved MSR
156			stw		r1,saver1+4(r4)						; Load up new R1
157
158			b		EXT(fastexit)						; Go back and take the fast path exit...
159
160/******************************************************************************
161 * void ExitPseudoKernel ( thread_act_t * act, BEDA_t * beda, savearea * sv  )
162 *
163 * This op provides a means of exiting from the BlueBox PseudoKernel to a
164 * user context.  This op attempts to simulate an RFI for the returning
165 * Traps (atomic_switch_trap) and SysCalls (atomic_switch_syscall).  Only the
166 * Blue Thread handling interrupts is allowed to atomically change
167 * interruption state and handle pending interrupts.
168 *
169 * If an interrupt is pending and we are returning to the alternate context,
170 * the exit is aborted and we return to an pending interrupt handler in the
171 * Blue Box pseudokernel.
172 *
173 * It also allows the MSR's FE0, FE1, BE and SE bits to updated for the user
174 * and completes the PPC register loading.
175 *
176 * Input registers are:
177 * r4  = Current context savearea (do not modify)
178 * r13 = Pointer to the current active thread's data
179 * r26 = Base address of BlueBox Data in kernel address space
180 *
181 ******************************************************************************/
182
183.L_ExitPseudoKernel:
184
185			rlwinm	r6,r26,0,0,19						; Start of page is bttd
186			lwz		r7,ACT_MACT_SPF(r13)				; Get special flags
187			lwz		r2,BTTD_INTERRUPT_VECTOR(r6)		; Get the interrupt vector
188			lwz		r1,BEDA_SPRG1(r26)					; Get saved CTR
189			ori		r7,r7,(0x8000 >> (bbNoMachSCbit - 16))	; Disable Mach SCs for Blue Box
190
191			cmpwi	r2,0								; Is this a preemptive thread
192			stw		r1,savectr+4(r4)					; Update CTR
193			beq		.L_ExitFromPreemptiveThread
194
195			lwz		r8,BTTD_INTCONTROLWORD(r6)			; Get ICW
196			lwz		r1,BTTD_NEWEXITSTATE(r6)			; New interrupt state
197			lwz		r2,BTTD_TESTINTMASK(r6)				; Get pending interrupt mask
198			lis		r3,SYSCONTEXTSTATE					; Setup for check in system context
199			rlwimi	r8,r1,0,INTSTATEMASK_B,INTSTATEMASK_E
200														; Insert new state
201			cmplw	cr1,r1,r3							; System context ?
202			and.	r2,r8,r2							; Any pending interrupt?
203			lwz		r1,savecr(r4)						; Get current CR
204
205			beq		cr1,.L_ExitToSystemContext			; We are in system context
206			beq		.L_ExitUpdateRuptControlWord		; We do not have a pending interrupt
207
208			lwz		r2,saver1+4(r4)						; Get current R1
209			lwz		r1,BEDA_SPRG0(r26)					; Get replacement R1
210			stw		r2,BEDA_SPRG1(r26)					; Save current R1
211			stw		r1,saver1+4(r4)						; Load up new R1
212			lwz		r3,bbPending(r13)					; Get pending interrupt PC
213			b		.L_ExitAbortExit					; Abort and Exit
214
215.L_ExitToSystemContext:
216			rlwimi	r1,r8,INTCR2TOBACKUPSHIFT,INTCR2MASK_B,INTCR2MASK_E
217														; Insert live CR2 into backup CR2
218.L_ExitUpdateRuptControlWord:
219			stw		r8,BTTD_INTCONTROLWORD(r6)			; Update ICW
220			stw		r1,savecr(r4)						; Update CR
221
222.L_ExitFromPreemptiveThread:
223			mfsprg	r3,1								; Get the current activation
224			lwz		r3,ACT_PER_PROC(r3)					; Get the per_proc block
225			lwz		r2,savesrr1+4(r4)					; Get current MSR
226			lwz		r1,BEDA_SRR1(r26)					; Get new MSR
227			stw		r7,ACT_MACT_SPF(r13)				; Update special flags
228			stw		r7,spcFlags(r3)						; Update per_proc version
229			rlwimi	r2,r1,0,MSR_FE0_BIT,MSR_FE1_BIT
230														; Insert FE0,FE1,SE,BE bits
231			lwz		r3,BEDA_SRR0(r26)					; Get new PC
232			stw		r2,savesrr1+4(r4)					; Update MSR
233
234.L_ExitAbortExit:
235			stw		r3,savesrr0+4(r4)					; Update PC
236
237			b		EXT(fastexit)						; Go back and take the fast path exit...
238
239