188 |
188 |
189 __NAKED__ void initialiseState(TInt /*aCpu*/, TSubScheduler* /*aSS*/) |
189 __NAKED__ void initialiseState(TInt /*aCpu*/, TSubScheduler* /*aSS*/) |
190 { |
190 { |
191 SET_RWNO_TID(,r1); |
191 SET_RWNO_TID(,r1); |
192 __ASM_CLI_MODE(MODE_ABT); |
192 __ASM_CLI_MODE(MODE_ABT); |
193 asm("str sp, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, i_AbtStackTop)); |
193 asm("str sp, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iAbtStackTop)); |
194 asm("mvn r3, #0 "); |
194 asm("mvn r3, #0 "); |
195 asm("str r3, [sp, #%a0]" : : "i" _FOFF(SFullArmRegSet, iExcCode)); |
195 asm("str r3, [sp, #%a0]" : : "i" _FOFF(SFullArmRegSet, iExcCode)); |
196 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, i_IrqNestCount)); |
196 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqNestCount)); |
197 __ASM_CLI_MODE(MODE_UND); |
197 __ASM_CLI_MODE(MODE_UND); |
198 asm("str sp, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, i_UndStackTop)); |
198 asm("str sp, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iUndStackTop)); |
199 __ASM_CLI_MODE(MODE_FIQ); |
199 __ASM_CLI_MODE(MODE_FIQ); |
200 asm("str sp, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, i_FiqStackTop)); |
200 asm("str sp, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iFiqStackTop)); |
201 __ASM_CLI_MODE(MODE_IRQ); |
201 __ASM_CLI_MODE(MODE_IRQ); |
202 asm("str sp, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, i_IrqStackTop)); |
202 asm("str sp, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqStackTop)); |
203 __ASM_CLI_MODE(MODE_SVC); |
203 __ASM_CLI_MODE(MODE_SVC); |
204 asm("ldr r2, __TheScheduler "); |
204 asm("ldr r2, __TheScheduler "); |
205 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, i_ScuAddr)); |
205 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, iSX.iScuAddr)); |
206 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, i_ScuAddr)); |
206 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iScuAddr)); |
207 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, i_GicDistAddr)); |
207 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, iSX.iGicDistAddr)); |
208 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, i_GicDistAddr)); |
208 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iGicDistAddr)); |
209 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, i_GicCpuIfcAddr)); |
209 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, iSX.iGicCpuIfcAddr)); |
210 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, i_GicCpuIfcAddr)); |
210 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iGicCpuIfcAddr)); |
211 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, i_LocalTimerAddr)); |
211 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, iSX.iLocalTimerAddr)); |
212 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, i_LocalTimerAddr)); |
212 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iLocalTimerAddr)); |
|
213 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, iSX.iGlobalTimerAddr)); |
|
214 asm("str r3, [r1, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iGlobalTimerAddr)); |
213 asm("mov r3, #0 "); |
215 asm("mov r3, #0 "); |
214 SET_RWRO_TID(,r3); |
216 SET_RWRO_TID(,r3); |
215 SET_RWRW_TID(,r3); |
217 SET_RWRW_TID(,r3); |
216 |
218 |
217 __JUMP(,lr); |
219 __JUMP(,lr); |
236 { |
238 { |
237 asm("stmfd sp!, {r0-r1} "); // save parameters |
239 asm("stmfd sp!, {r0-r1} "); // save parameters |
238 GET_RWNO_TID(,r0); |
240 GET_RWNO_TID(,r0); |
239 asm("cmp r0, #0 "); |
241 asm("cmp r0, #0 "); |
240 asm("ldreq r0, __SS0 "); |
242 asm("ldreq r0, __SS0 "); |
241 asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(TSubScheduler,i_Regs)); |
243 asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iRegs)); |
242 asm("cmp r0, #0 "); |
244 asm("cmp r0, #0 "); |
243 asm("ldreq r0, __DefaultRegs "); |
245 asm("ldreq r0, __DefaultRegs "); |
244 asm("ldr r1, [r0, #%a0]" : : "i" _FOFF(SFullArmRegSet, iExcCode)); |
246 asm("ldr r1, [r0, #%a0]" : : "i" _FOFF(SFullArmRegSet, iExcCode)); |
245 asm("cmp r1, #0 "); // context already saved? |
247 asm("cmp r1, #0 "); // context already saved? |
246 asm("bge state_already_saved "); // skip if so |
248 asm("bge state_already_saved "); // skip if so |
273 asm("cmp r0, #0 "); |
275 asm("cmp r0, #0 "); |
274 asm("moveq r2, #1 "); |
276 asm("moveq r2, #1 "); |
275 asm("streq r2, [r1] "); |
277 asm("streq r2, [r1] "); |
276 asm("beq skip_other_cores "); // If subscheduler not yet set, don't bother with other cores |
278 asm("beq skip_other_cores "); // If subscheduler not yet set, don't bother with other cores |
277 asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iCpuMask)); |
279 asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iCpuMask)); |
278 asm("ldr r5, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, i_GicCpuIfcAddr)); |
280 asm("ldr r5, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iGicCpuIfcAddr)); |
279 // asm("ldr r4, [r0, #%a0]" : : "i" _FOFF(TSubScheduler,i_Regs)); |
281 // asm("ldr r4, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iRegs)); |
280 asm("bic sp, sp, #4 "); // align stack to multiple of 8 |
282 asm("bic sp, sp, #4 "); // align stack to multiple of 8 |
281 |
283 |
282 __DATA_MEMORY_BARRIER_Z__(r6); |
284 __DATA_MEMORY_BARRIER_Z__(r6); |
283 asm("1: "); |
285 asm("1: "); |
284 LDREX(3,1); |
286 LDREX(3,1); |
291 asm("beq first_to_crash "); // branch if so |
293 asm("beq first_to_crash "); // branch if so |
292 |
294 |
293 // we weren't first to crash, so wait here for a crash IPI |
295 // we weren't first to crash, so wait here for a crash IPI |
294 // disable all interrupts except for CRASH_IPI |
296 // disable all interrupts except for CRASH_IPI |
295 GET_RWNO_TID(,r0); |
297 GET_RWNO_TID(,r0); |
296 asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, i_GicCpuIfcAddr)); |
298 asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iGicCpuIfcAddr)); |
297 asm("mov r1, #0 "); |
299 asm("mov r1, #0 "); |
298 asm("1: "); |
300 asm("1: "); |
299 asm("add r1, r1, #1 "); |
301 asm("add r1, r1, #1 "); |
300 asm("str r1, [r0, #%a0]" : : "i" _FOFF(GicCpuIfc, iPriMask)); |
302 asm("str r1, [r0, #%a0]" : : "i" _FOFF(GicCpuIfc, iPriMask)); |
301 __DATA_SYNC_BARRIER__(r6); |
303 __DATA_SYNC_BARRIER__(r6); |
310 |
312 |
311 // This CPU was first to crash |
313 // This CPU was first to crash |
312 asm("first_to_crash: "); |
314 asm("first_to_crash: "); |
313 asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iScheduler)); |
315 asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iScheduler)); |
314 asm("ldr r7, __CrashStateOut "); |
316 asm("ldr r7, __CrashStateOut "); |
315 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, iActiveCpus1)); |
317 asm("ldr r3, [r2, #%a0]" : : "i" _FOFF(TScheduler, iIpiAcceptCpus)); |
316 asm("str r3, [r7] "); // mask of CPUs pending |
318 asm("str r3, [r7] "); // mask of CPUs pending |
317 asm("ldr r5, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, i_GicDistAddr)); |
319 asm("ldr r5, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iGicDistAddr)); |
318 asm("ldr r1, __CrashIPIWord "); |
320 asm("ldr r1, __CrashIPIWord "); |
319 __DATA_SYNC_BARRIER_Z__(r6); |
321 __DATA_SYNC_BARRIER_Z__(r6); |
320 asm("str r1, [r5, #%a0]" : : "i" _FOFF(GicDistributor, iSoftIrq)); // send CRASH_IPI to all other CPUs |
322 asm("str r1, [r5, #%a0]" : : "i" _FOFF(GicDistributor, iSoftIrq)); // send CRASH_IPI to all other CPUs |
321 __DATA_SYNC_BARRIER__(r6); |
323 __DATA_SYNC_BARRIER__(r6); |
322 |
324 |
1034 __NAKED__ EXPORT_C TBool BTrace::OutFilteredPcFormatBig(TUint32 a0, TUint32 aModuleUid, TUint32 aPc, TUint16 aFormatId, const TAny* aData, TInt aDataSize) |
1036 __NAKED__ EXPORT_C TBool BTrace::OutFilteredPcFormatBig(TUint32 a0, TUint32 aModuleUid, TUint32 aPc, TUint16 aFormatId, const TAny* aData, TInt aDataSize) |
1035 { |
1037 { |
1036 asm("mov r0, #0"); //Kernel side not implemented yet |
1038 asm("mov r0, #0"); //Kernel side not implemented yet |
1037 } |
1039 } |
1038 |
1040 |
1039 |
1041 #ifdef __CPU_ARM_HAS_WFE_SEV |
1040 |
1042 |
1041 |
1043 extern "C" __NAKED__ void __arm_wfe() |
1042 |
1044 { |
|
1045 ARM_WFE; |
|
1046 __JUMP(, lr); |
|
1047 } |
|
1048 |
|
1049 extern "C" __NAKED__ void __arm_sev() |
|
1050 { |
|
1051 ARM_SEV; |
|
1052 __JUMP(, lr); |
|
1053 } |
|
1054 |
|
1055 #endif |
|
1056 |
|
1057 // Called by a CPU which has completed its detach sequence and should now be powered off |
|
1058 // Doesn't return - just waits for power to be removed |
|
1059 // CPU will come back up via the reset vector when it next wakes up. |
|
1060 // NOTE: On entry the CPU caches are disabled and the CPU does not participate in coherency |
|
1061 // SO BE VERY CAREFUL |
|
1062 extern "C" __NAKED__ void DetachComplete() |
|
1063 { |
|
1064 GET_RWNO_TID(,r0); |
|
1065 asm("ldr r1, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iUncached)); |
|
1066 asm("ldr r2, [r1, #%a0]" : : "i" _FOFF(SPerCpuUncached, iDetachCompleteCpus)); |
|
1067 asm("ldr r3, [r0, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iGicDistAddr)); |
|
1068 __DATA_SYNC_BARRIER_Z__(r12); // need DSB before sending any IPI |
|
1069 asm("mov r2, r2, lsl #16 "); |
|
1070 asm("orr r2, r2, #%a0" : : "i" ((TInt)INDIRECT_POWERDOWN_IPI_VECTOR)); |
|
1071 asm("str r2, [r3, #%a0]" : : "i" _FOFF(GicDistributor, iSoftIrq)); // trigger IPIs |
|
1072 |
|
1073 asm("wait_forever: "); |
|
1074 __DATA_SYNC_BARRIER__(r12); |
|
1075 ARM_WFE; |
|
1076 __DATA_SYNC_BARRIER__(r12); |
|
1077 asm("ldr r2, [r1, #%a0]" : : "i" _FOFF(SPerCpuUncached, iPowerOnReq)); |
|
1078 __DATA_SYNC_BARRIER__(r12); |
|
1079 asm("cmp r2, #0xF000000F "); // for 'fake' power down |
|
1080 asm("bne wait_forever "); |
|
1081 |
|
1082 asm("0: "); |
|
1083 __JUMP(,lr); |
|
1084 } |
|
1085 |
|
1086 |
|
1087 |
|
1088 |
|
1089 |