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