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