changeset 90 | 947f0dc9f7a8 |
parent 0 | a41df078684a |
child 177 | a232af6b0b1f |
52:2d65c2f76d7b | 90:947f0dc9f7a8 |
---|---|
18 #include <e32cia.h> |
18 #include <e32cia.h> |
19 #include <arm.h> |
19 #include <arm.h> |
20 #include <arm_gic.h> |
20 #include <arm_gic.h> |
21 #include <arm_tmr.h> |
21 #include <arm_tmr.h> |
22 |
22 |
23 |
23 extern "C" { |
24 extern SVariantInterfaceBlock* VIB; |
|
25 } |
|
24 |
26 |
25 __NAKED__ void Arm::GetUserSpAndLr(TAny*) |
27 __NAKED__ void Arm::GetUserSpAndLr(TAny*) |
26 { |
28 { |
27 asm("stmia r0, {r13, r14}^ "); |
29 asm("stmia r0, {r13, r14}^ "); |
28 asm("mov r0, r0"); // NOP needed between stm^ and banked register access |
30 asm("mov r0, r0"); // NOP needed between stm^ and banked register access |
285 __JUMP(, lr); |
287 __JUMP(, lr); |
286 } |
288 } |
287 #endif |
289 #endif |
288 |
290 |
289 |
291 |
290 |
292 #if defined(__NKERN_TIMESTAMP_USE_LOCAL_TIMER__) |
291 /** Get the current value of the system timestamp |
293 #error Use of local timer for NKern::Timestamp() no longer supported |
292 |
294 |
293 @publishedPartner |
295 #elif defined(__NKERN_TIMESTAMP_USE_SCU_GLOBAL_TIMER__) |
294 @prototype |
296 // Code to access global timer in Cortex A9 r1p0 |
295 */ |
297 |
298 #ifndef __CPU_ARM_HAS_GLOBAL_TIMER_BLOCK |
|
299 #error NKern::Timestamp() wants global timer, but global timer not present. |
|
300 #endif |
|
301 |
|
296 EXPORT_C __NAKED__ TUint64 NKern::Timestamp() |
302 EXPORT_C __NAKED__ TUint64 NKern::Timestamp() |
297 { |
303 { |
298 asm("ldr r3, __TheScheduler "); |
304 asm("ldr r3, __TheScheduler "); |
299 asm("mrs r12, cpsr "); // r12 = saved interrupt mask |
305 asm("mrs r12, cpsr "); // r12 = saved interrupt mask |
300 asm("ldr r2, [r3, #%a0]" : : "i" _FOFF(TScheduler,i_LocalTimerAddr)); // r2 points to local timer |
306 asm("stmfd sp!, {r4-r7} "); |
307 asm("ldr r5, [r3, #%a0]" : : "i" _FOFF(TScheduler,iSub[0])); // r5->subscheduler for CPU0 |
|
308 asm("ldr r4, [r3, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGlobalTimerAddr)); // r4 points to global timer |
|
301 __ASM_CLI(); // disable all interrupts |
309 __ASM_CLI(); // disable all interrupts |
302 GET_RWNO_TID(,r3); // r3 -> TSubScheduler |
310 asm("ldr r6, [r5, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iTicksSinceLastSync)); // r6 = count value of last frequency change (low) |
303 asm("ldr r1, [r2, #%a0]" : : "i" _FOFF(ArmLocalTimer,iTimerCount)); // r1 = current timer counter |
311 asm("ldr r7, [r5, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iLastTimerSet)); // r7 = count value of last frequency change (high) |
304 asm("ldr r0, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,i_LastTimerSet)); // r0 = last value written to timer counter |
312 asm("ldr r2, [r4, #%a0]" : : "i" _FOFF(ArmGlobalTimer,iTimerCountHigh)); // r2 = current timer counter high word |
305 asm("ldr r2, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,i_TimerMultI)); // r2 = scaling factor |
313 |
306 asm("sub r0, r0, r1 "); // elapsed timer ticks since last timestamp sync |
314 // To read 64 bit timer value, read high, low, high |
307 asm("umull r1, r2, r0, r2 "); // r2:r1 = elapsed ticks * scaling factor |
315 // If two high values match -> OK, else repeat |
308 asm("ldr r0, [r3, #%a0]!" : : "i" _FOFF(TSubScheduler,iLastTimestamp64)); // r0 = last timestamp sync point, low word |
316 asm("1: "); |
309 asm("ldr r3, [r3, #4] "); // r3 = last timestamp sync point, high word |
317 asm("mov r1, r2 "); // r1 = previous value of timer counter high word |
310 asm("adds r1, r1, #0x00800000 "); // add 2^23 (rounding) |
318 asm("ldr r0, [r4, #%a0]" : : "i" _FOFF(ArmGlobalTimer,iTimerCountLow)); // r0 = current timer counter low word |
311 asm("adcs r2, r2, #0 "); |
319 asm("ldr r2, [r4, #%a0]" : : "i" _FOFF(ArmGlobalTimer,iTimerCountHigh)); // r2 = current timer counter high word |
312 asm("mov r1, r1, lsr #24 "); // divide by 2^24 |
320 asm("cmp r1, r2 "); // high word changed? |
313 asm("orr r1, r1, r2, lsl #8 "); // r1 = elapsed time since last timestamp sync |
321 asm("bne 1b "); // if so, retry |
322 |
|
323 // Now have R1:R0 = 64 bit global timer count |
|
324 asm("ldr r3, [r5, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iNTimerPeriodM)); // r3 = period multiplier |
|
325 asm("ldr r4, [r5, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iNTimerPeriodS)); // r4 = period multiplier shift |
|
326 asm("subs r6, r0, r6 "); // r7:r6 = ticks from last frequency change |
|
327 asm("sbcs r7, r1, r7 "); |
|
328 asm("umull r0, r1, r6, r3 "); |
|
329 asm("mov r2, #0 "); |
|
330 asm("umlal r1, r2, r7, r3 "); // r2:r1:r0 = delta * period multiplier |
|
331 asm("rsb r3, r4, #32 "); |
|
332 asm("ldr r6, [r5, #%a0]!" : : "i" _FOFF(TSubScheduler,iSSX.iLastSyncTime)); // r6 = timestamp at last freq change (low) |
|
333 asm("ldr r7, [r5, #4] "); // r7 = timestamp at last freq change (high) |
|
314 asm("msr cpsr, r12 "); // restore interrupts |
334 asm("msr cpsr, r12 "); // restore interrupts |
315 asm("adds r0, r0, r1 "); // r1:r0 = last timestamp sync point + elapsed time since last timestamp sync |
335 asm("movs r0, r0, lsr r4 "); // rounding bit into C |
316 asm("adcs r1, r3, #0 "); |
336 asm("orr r0, r0, r1, lsl r3 "); |
317 __JUMP(,lr); |
337 asm("mov r1, r1, lsr r4 "); |
338 asm("orr r1, r1, r2, lsl r3 "); // r1:r0 = (delta * period multiplier) >> period multiplier shift |
|
339 asm("adcs r0, r0, r6 "); // scaled delta + timestamp at last freq change |
|
340 asm("adcs r1, r1, r7 "); |
|
341 asm("ldmfd sp!, {r4-r7} "); |
|
342 __JUMP(,lr); |
|
343 |
|
318 asm("__TheScheduler: "); |
344 asm("__TheScheduler: "); |
319 asm(".word %a0" : : "i" ((TInt)&TheScheduler)); |
345 asm(".word %a0" : : "i" ((TInt)&TheScheduler)); |
320 } |
346 } |
347 |
|
348 #elif defined(__NKERN_TIMESTAMP_USE_INLINE_BSP_CODE__) |
|
349 #define __DEFINE_NKERN_TIMESTAMP_ASM__ |
|
350 #include <variant_timestamp.h> |
|
351 #undef __DEFINE_NKERN_TIMESTAMP_ASM__ |
|
352 #elif defined(__NKERN_TIMESTAMP_USE_BSP_CALLOUT__) |
|
353 // Code to call function defined in variant |
|
354 #else |
|
355 #error No definition for NKern::Timestamp() |
|
356 #endif |
|
321 |
357 |
322 |
358 |
323 extern "C" __NAKED__ TLinAddr get_sp_svc() |
359 extern "C" __NAKED__ TLinAddr get_sp_svc() |
324 { |
360 { |
325 asm("mrs r1, cpsr "); |
361 asm("mrs r1, cpsr "); |
357 asm("msr cpsr, r1 "); |
393 asm("msr cpsr, r1 "); |
358 __JUMP(, lr); |
394 __JUMP(, lr); |
359 |
395 |
360 asm("1: "); |
396 asm("1: "); |
361 GET_RWNO_TID(,r3); |
397 GET_RWNO_TID(,r3); |
362 asm("ldr r2, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,i_FiqStackTop)); // if so, r2->top of FIQ stack |
398 asm("ldr r2, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iFiqStackTop)); // if so, r2->top of FIQ stack |
363 asm("ldr r0, [r2, #-4] "); // get return address |
399 asm("ldr r0, [r2, #-4] "); // get return address |
364 asm("msr cpsr, r1 "); |
400 asm("msr cpsr, r1 "); |
365 __JUMP(, lr); |
401 __JUMP(, lr); |
366 } |
402 } |
367 |
403 |
592 SPIN_LOCK_MARK_ACQ() |
628 SPIN_LOCK_MARK_ACQ() |
593 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
629 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
594 __JUMP(,lr); |
630 __JUMP(,lr); |
595 |
631 |
596 asm("2: "); |
632 asm("2: "); |
633 asm("ldr r1, __CrashState "); |
|
597 ARM_WFE; |
634 ARM_WFE; |
598 asm("ldrb r1, [r0, #0] "); /* read out count again */ |
635 asm("ldr r1, [r1] "); /* check for system crash while we were waiting */ |
599 asm("b 3b "); |
636 asm("cmp r1, #0 "); |
637 asm("bne 9f "); |
|
638 asm("ldrb r1, [r0, #0] "); /* read out count again */ |
|
639 asm("b 3b "); |
|
640 asm("9: "); |
|
641 __ASM_CRASH(); /* system crashed while we were waiting */ |
|
600 } |
642 } |
601 |
643 |
602 __NAKED__ EXPORT_C void TSpinLock::UnlockIrq() |
644 __NAKED__ EXPORT_C void TSpinLock::UnlockIrq() |
603 { |
645 { |
604 SPIN_UNLOCK_ENTRY_CHECK() |
646 SPIN_UNLOCK_ENTRY_CHECK() |
613 } |
655 } |
614 |
656 |
615 __NAKED__ EXPORT_C TBool TSpinLock::FlashIrq() |
657 __NAKED__ EXPORT_C TBool TSpinLock::FlashIrq() |
616 { |
658 { |
617 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
659 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
618 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr)); |
660 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr)); |
619 asm("ldrh r1, [r0, #0] "); |
661 asm("ldrh r1, [r0, #0] "); |
620 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
662 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
621 asm("sub r1, r1, r1, lsr #8 "); /* r1 low byte = (out - in) mod 256 */ |
663 asm("sub r1, r1, r1, lsr #8 "); /* r1 low byte = (out - in) mod 256 */ |
622 asm("and r1, r1, #0xFF "); |
664 asm("and r1, r1, #0xFF "); |
623 asm("cmp r1, #0xFF "); /* if out - in = -1, no-one else waiting */ |
665 asm("cmp r1, #0xFF "); /* if out - in = -1, no-one else waiting */ |
653 SPIN_LOCK_MARK_ACQ() |
695 SPIN_LOCK_MARK_ACQ() |
654 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
696 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
655 __JUMP(,lr); |
697 __JUMP(,lr); |
656 |
698 |
657 asm("2: "); |
699 asm("2: "); |
700 asm("ldr r1, __CrashState "); |
|
658 ARM_WFE; |
701 ARM_WFE; |
659 asm("ldrb r1, [r0, #0] "); /* read out count again */ |
702 asm("ldr r1, [r1] "); /* check for system crash while we were waiting */ |
660 asm("b 3b "); |
703 asm("cmp r1, #0 "); |
704 asm("bne 9f "); |
|
705 asm("ldrb r1, [r0, #0] "); /* read out count again */ |
|
706 asm("b 3b "); |
|
707 asm("9: "); |
|
708 __ASM_CRASH(); /* system crashed while we were waiting */ |
|
661 } |
709 } |
662 |
710 |
663 __NAKED__ EXPORT_C void TSpinLock::UnlockOnly() |
711 __NAKED__ EXPORT_C void TSpinLock::UnlockOnly() |
664 { |
712 { |
665 SPIN_UNLOCK_ENTRY_CHECK() |
713 SPIN_UNLOCK_ENTRY_CHECK() |
711 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
759 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
712 asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask)); /* return original CPSR I and F bits */ |
760 asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask)); /* return original CPSR I and F bits */ |
713 __JUMP(,lr); |
761 __JUMP(,lr); |
714 |
762 |
715 asm("2: "); |
763 asm("2: "); |
764 asm("ldr r1, __CrashState "); |
|
716 ARM_WFE; |
765 ARM_WFE; |
717 asm("ldrb r1, [r0, #0] "); /* read out count again */ |
766 asm("ldr r1, [r1] "); /* check for system crash while we were waiting */ |
718 asm("b 3b "); |
767 asm("cmp r1, #0 "); |
768 asm("bne 9f "); |
|
769 asm("ldrb r1, [r0, #0] "); /* read out count again */ |
|
770 asm("b 3b "); |
|
771 asm("9: "); |
|
772 __ASM_CRASH(); /* system crashed while we were waiting */ |
|
719 } |
773 } |
720 |
774 |
721 __NAKED__ EXPORT_C void TSpinLock::UnlockIrqRestore(TInt) |
775 __NAKED__ EXPORT_C void TSpinLock::UnlockIrqRestore(TInt) |
722 { |
776 { |
723 SPIN_UNLOCK_ENTRY_CHECK() |
777 SPIN_UNLOCK_ENTRY_CHECK() |
735 } |
789 } |
736 |
790 |
737 __NAKED__ EXPORT_C TBool TSpinLock::FlashIrqRestore(TInt) |
791 __NAKED__ EXPORT_C TBool TSpinLock::FlashIrqRestore(TInt) |
738 { |
792 { |
739 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
793 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
740 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr)); |
794 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr)); |
741 asm("ldrh r2, [r0, #0] "); |
795 asm("ldrh r2, [r0, #0] "); |
742 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
796 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
743 asm("sub r2, r2, r2, lsr #8 "); /* r2 low byte = (out - in) mod 256 */ |
797 asm("sub r2, r2, r2, lsr #8 "); /* r2 low byte = (out - in) mod 256 */ |
744 asm("and r2, r2, #0xFF "); |
798 asm("and r2, r2, #0xFF "); |
745 asm("cmp r2, #0xFF "); /* if out - in = -1, no-one else waiting */ |
799 asm("cmp r2, #0xFF "); /* if out - in = -1, no-one else waiting */ |
777 asm("bl " CSM_ZN5NKern15PreemptionPointEv); |
831 asm("bl " CSM_ZN5NKern15PreemptionPointEv); |
778 asm("ldr r0, [sp], #4 "); |
832 asm("ldr r0, [sp], #4 "); |
779 asm("bl " CSM_ZN9TSpinLock8LockOnlyEv); |
833 asm("bl " CSM_ZN9TSpinLock8LockOnlyEv); |
780 asm("mov r0, #1 "); |
834 asm("mov r0, #1 "); |
781 asm("ldr pc, [sp], #4 "); |
835 asm("ldr pc, [sp], #4 "); |
836 |
|
837 asm("__CrashState: "); |
|
838 asm(".word %a0" : : "i" ((TInt)&CrashState)); |
|
782 } |
839 } |
783 |
840 |
784 |
841 |
785 /****************************************************************************** |
842 /****************************************************************************** |
786 * Read/Write Spin lock |
843 * Read/Write Spin lock |
1159 RWSPIN_RLOCK_MARK_ACQ() |
1216 RWSPIN_RLOCK_MARK_ACQ() |
1160 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1217 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1161 __JUMP(,lr); |
1218 __JUMP(,lr); |
1162 |
1219 |
1163 asm("2: "); |
1220 asm("2: "); |
1221 asm("ldr r1, __CrashState "); |
|
1164 ARM_WFE; |
1222 ARM_WFE; |
1165 asm("ldr r1, [r0, #0] "); /* read out.w count again */ |
1223 asm("ldr r1, [r1] "); /* check for system crash while we were waiting */ |
1166 asm("b 3b "); |
1224 asm("cmp r1, #0 "); |
1225 asm("bne 9f "); |
|
1226 asm("ldr r1, [r0, #0] "); /* read out.w count again */ |
|
1227 asm("b 3b "); |
|
1228 asm("9: "); |
|
1229 __ASM_CRASH(); /* system crashed while we were waiting */ |
|
1167 } |
1230 } |
1168 |
1231 |
1169 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqR() |
1232 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqR() |
1170 { |
1233 { |
1171 RWSPIN_RUNLOCK_ENTRY_CHECK() |
1234 RWSPIN_RUNLOCK_ENTRY_CHECK() |
1183 } |
1246 } |
1184 |
1247 |
1185 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqR() |
1248 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqR() |
1186 { |
1249 { |
1187 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
1250 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
1188 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr)); |
1251 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr)); |
1189 asm("ldr r2, [r0, #0] "); |
1252 asm("ldr r2, [r0, #0] "); |
1190 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
1253 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
1191 asm("eor r2, r2, r2, lsr #16 "); /* r2 low byte = out.w ^ in.w = 0 if no writers waiting */ |
1254 asm("eor r2, r2, r2, lsr #16 "); /* r2 low byte = out.w ^ in.w = 0 if no writers waiting */ |
1192 asm("tst r2, #0xFF "); |
1255 asm("tst r2, #0xFF "); |
1193 asm("addeq r3, r3, #1 "); |
1256 asm("addeq r3, r3, #1 "); |
1228 RWSPIN_WLOCK_MARK_ACQ() |
1291 RWSPIN_WLOCK_MARK_ACQ() |
1229 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1292 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1230 __JUMP(,lr); |
1293 __JUMP(,lr); |
1231 |
1294 |
1232 asm("2: "); |
1295 asm("2: "); |
1296 asm("ldr r1, __CrashState "); |
|
1233 ARM_WFE; |
1297 ARM_WFE; |
1234 asm("ldr r1, [r0, #0] "); /* read out count again */ |
1298 asm("ldr r1, [r1] "); /* check for system crash while we were waiting */ |
1235 asm("b 3b "); |
1299 asm("cmp r1, #0 "); |
1300 asm("bne 9f "); |
|
1301 asm("ldr r1, [r0, #0] "); /* read out count again */ |
|
1302 asm("b 3b "); |
|
1303 asm("9: "); |
|
1304 __ASM_CRASH(); /* system crashed while we were waiting */ |
|
1236 } |
1305 } |
1237 |
1306 |
1238 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqW() |
1307 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqW() |
1239 { |
1308 { |
1240 RWSPIN_WUNLOCK_ENTRY_CHECK() |
1309 RWSPIN_WUNLOCK_ENTRY_CHECK() |
1249 } |
1318 } |
1250 |
1319 |
1251 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqW() |
1320 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqW() |
1252 { |
1321 { |
1253 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
1322 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
1254 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr)); |
1323 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr)); |
1255 asm("ldr r2, [r0, #0] "); |
1324 asm("ldr r2, [r0, #0] "); |
1256 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
1325 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
1257 asm("add r2, r2, #0x00010000 "); /* increment out.w */ |
1326 asm("add r2, r2, #0x00010000 "); /* increment out.w */ |
1258 asm("tst r2, #0x00FF0000 "); /* if wraparound, revert carry */ |
1327 asm("tst r2, #0x00FF0000 "); /* if wraparound, revert carry */ |
1259 asm("subeq r2, r2, #0x01000000 "); |
1328 asm("subeq r2, r2, #0x01000000 "); |
1298 RWSPIN_RLOCK_MARK_ACQ() |
1367 RWSPIN_RLOCK_MARK_ACQ() |
1299 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1368 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1300 __JUMP(,lr); |
1369 __JUMP(,lr); |
1301 |
1370 |
1302 asm("2: "); |
1371 asm("2: "); |
1372 asm("ldr r1, __CrashState "); |
|
1303 ARM_WFE; |
1373 ARM_WFE; |
1304 asm("ldr r1, [r0, #0] "); /* read out.w count again */ |
1374 asm("ldr r1, [r1] "); /* check for system crash while we were waiting */ |
1305 asm("b 3b "); |
1375 asm("cmp r1, #0 "); |
1376 asm("bne 9f "); |
|
1377 asm("ldr r1, [r0, #0] "); /* read out.w count again */ |
|
1378 asm("b 3b "); |
|
1379 asm("9: "); |
|
1380 __ASM_CRASH(); /* system crashed while we were waiting */ |
|
1306 } |
1381 } |
1307 |
1382 |
1308 __NAKED__ EXPORT_C void TRWSpinLock::UnlockOnlyR() |
1383 __NAKED__ EXPORT_C void TRWSpinLock::UnlockOnlyR() |
1309 { |
1384 { |
1310 RWSPIN_RUNLOCK_ENTRY_CHECK() |
1385 RWSPIN_RUNLOCK_ENTRY_CHECK() |
1360 RWSPIN_WLOCK_MARK_ACQ() |
1435 RWSPIN_WLOCK_MARK_ACQ() |
1361 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1436 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1362 __JUMP(,lr); |
1437 __JUMP(,lr); |
1363 |
1438 |
1364 asm("2: "); |
1439 asm("2: "); |
1440 asm("ldr r1, __CrashState "); |
|
1365 ARM_WFE; |
1441 ARM_WFE; |
1366 asm("ldr r1, [r0, #0] "); /* read out count again */ |
1442 asm("ldr r1, [r1] "); /* check for system crash while we were waiting */ |
1367 asm("b 3b "); |
1443 asm("cmp r1, #0 "); |
1444 asm("bne 9f "); |
|
1445 asm("ldr r1, [r0, #0] "); /* read out count again */ |
|
1446 asm("b 3b "); |
|
1447 asm("9: "); |
|
1448 __ASM_CRASH(); /* system crashed while we were waiting */ |
|
1368 } |
1449 } |
1369 |
1450 |
1370 __NAKED__ EXPORT_C void TRWSpinLock::UnlockOnlyW() |
1451 __NAKED__ EXPORT_C void TRWSpinLock::UnlockOnlyW() |
1371 { |
1452 { |
1372 RWSPIN_WUNLOCK_ENTRY_CHECK() |
1453 RWSPIN_WUNLOCK_ENTRY_CHECK() |
1426 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1507 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1427 asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask)); /* return original CPSR I and F bits */ |
1508 asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask)); /* return original CPSR I and F bits */ |
1428 __JUMP(,lr); |
1509 __JUMP(,lr); |
1429 |
1510 |
1430 asm("2: "); |
1511 asm("2: "); |
1512 asm("ldr r1, __CrashState "); |
|
1431 ARM_WFE; |
1513 ARM_WFE; |
1432 asm("ldr r1, [r0, #0] "); /* read out.w count again */ |
1514 asm("ldr r1, [r1] "); /* check for system crash while we were waiting */ |
1433 asm("b 3b "); |
1515 asm("cmp r1, #0 "); |
1516 asm("bne 9f "); |
|
1517 asm("ldr r1, [r0, #0] "); /* read out.w count again */ |
|
1518 asm("b 3b "); |
|
1519 asm("9: "); |
|
1520 __ASM_CRASH(); /* system crashed while we were waiting */ |
|
1434 } |
1521 } |
1435 |
1522 |
1436 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqRestoreR(TInt) |
1523 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqRestoreR(TInt) |
1437 { |
1524 { |
1438 RWSPIN_RUNLOCK_ENTRY_CHECK() |
1525 RWSPIN_RUNLOCK_ENTRY_CHECK() |
1453 } |
1540 } |
1454 |
1541 |
1455 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqRestoreR(TInt) |
1542 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqRestoreR(TInt) |
1456 { |
1543 { |
1457 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
1544 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
1458 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr)); |
1545 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr)); |
1459 asm("ldr r2, [r0, #0] "); |
1546 asm("ldr r2, [r0, #0] "); |
1460 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
1547 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
1461 asm("eor r2, r2, r2, lsr #16 "); /* r2 low byte = out.w ^ in.w = 0 if no writers waiting */ |
1548 asm("eor r2, r2, r2, lsr #16 "); /* r2 low byte = out.w ^ in.w = 0 if no writers waiting */ |
1462 asm("tst r2, #0xFF "); |
1549 asm("tst r2, #0xFF "); |
1463 asm("addeq r3, r3, #1 "); |
1550 asm("addeq r3, r3, #1 "); |
1500 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1587 __DATA_MEMORY_BARRIER__(r3); /* we have got the lock */ |
1501 asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask)); /* return original CPSR I and F bits */ |
1588 asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask)); /* return original CPSR I and F bits */ |
1502 __JUMP(,lr); |
1589 __JUMP(,lr); |
1503 |
1590 |
1504 asm("2: "); |
1591 asm("2: "); |
1592 asm("ldr r1, __CrashState "); |
|
1505 ARM_WFE; |
1593 ARM_WFE; |
1506 asm("ldr r1, [r0, #0] "); /* read out count again */ |
1594 asm("ldr r1, [r1] "); /* check for system crash while we were waiting */ |
1507 asm("b 3b "); |
1595 asm("cmp r1, #0 "); |
1596 asm("bne 9f "); |
|
1597 asm("ldr r1, [r0, #0] "); /* read out count again */ |
|
1598 asm("b 3b "); |
|
1599 asm("9: "); |
|
1600 __ASM_CRASH(); /* system crashed while we were waiting */ |
|
1508 } |
1601 } |
1509 |
1602 |
1510 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqRestoreW(TInt) |
1603 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqRestoreW(TInt) |
1511 { |
1604 { |
1512 RWSPIN_WUNLOCK_ENTRY_CHECK() |
1605 RWSPIN_WUNLOCK_ENTRY_CHECK() |
1524 } |
1617 } |
1525 |
1618 |
1526 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqRestoreW(TInt) |
1619 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqRestoreW(TInt) |
1527 { |
1620 { |
1528 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
1621 GET_RWNO_TID(,r12); /* r12 -> TSubScheduler */ |
1529 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr)); |
1622 asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr)); |
1530 asm("ldr r2, [r0, #0] "); |
1623 asm("ldr r2, [r0, #0] "); |
1531 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
1624 asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending)); |
1532 asm("add r2, r2, #0x00010000 "); /* increment out.w */ |
1625 asm("add r2, r2, #0x00010000 "); /* increment out.w */ |
1533 asm("tst r2, #0x00FF0000 "); /* if wraparound, revert carry */ |
1626 asm("tst r2, #0x00FF0000 "); /* if wraparound, revert carry */ |
1534 asm("subeq r2, r2, #0x01000000 "); |
1627 asm("subeq r2, r2, #0x01000000 "); |