122 #endif |
123 #endif |
123 GET_RWNO_TID(,r4); |
124 GET_RWNO_TID(,r4); |
124 asm("mov r5, sp "); |
125 asm("mov r5, sp "); |
125 asm("str r1, [sp, #%a0]" : : "i" _FOFF(SThreadExcStack,iExcCode)); // word describing exception type |
126 asm("str r1, [sp, #%a0]" : : "i" _FOFF(SThreadExcStack,iExcCode)); // word describing exception type |
126 __ASM_STI2_MODE(MODE_SYS); // mode_sys, IRQs off, FIQs on |
127 __ASM_STI2_MODE(MODE_SYS); // mode_sys, IRQs off, FIQs on |
127 asm("ldr sp, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, i_IrqStackTop)); |
128 asm("ldr sp, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqStackTop)); |
128 USER_MEMORY_GUARD_ON(,r8,r0); // r8 = original DACR if user memory guards in use |
129 USER_MEMORY_GUARD_ON(,r8,r0); // r8 = original DACR if user memory guards in use |
129 |
130 |
130 asm("nested_irq_rejoin: "); |
131 asm("nested_irq_rejoin: "); |
131 asm("ldr r0, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, i_IrqCount)); |
132 asm("ldr r0, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqCount)); |
132 asm("ldr r7, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, i_IrqNestCount)); |
133 asm("ldr r7, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqNestCount)); |
133 asm("ldr r12, __ArmInterrupt "); |
134 asm("ldr r12, __ArmInterrupt "); |
134 asm("ldr r10, _ArmVectorIrq "); |
135 asm("ldr r10, _ArmVectorIrq "); |
135 asm("add r0, r0, #1 "); |
136 asm("add r0, r0, #1 "); |
136 asm("add r7, r7, #1 "); |
137 asm("add r7, r7, #1 "); |
137 __DATA_MEMORY_BARRIER_Z__(r2); // ensure memory accesses in interrupted code are observed before |
138 __DATA_MEMORY_BARRIER_Z__(r2); // ensure memory accesses in interrupted code are observed before |
138 // the writes to i_IrqCount, i_IrqNestCount |
139 // the writes to i_IrqCount, i_IrqNestCount |
139 asm("str r0, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, i_IrqCount)); // increment i_IrqCount |
140 asm("str r0, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqCount)); // increment i_IrqCount |
140 asm("ldr r11, [r12,#%a0]" : : "i" _FOFF(SArmInterruptInfo,iIrqHandler)); // address of IRQ handler |
141 asm("ldr r11, [r12,#%a0]" : : "i" _FOFF(SArmInterruptInfo,iIrqHandler)); // address if IRQ handler |
141 asm("ldr r6, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, i_GicCpuIfcAddr)); |
142 asm("ldr r6, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iGicCpuIfcAddr)); |
142 asm("str r7, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, i_IrqNestCount)); // increment i_IrqNestCount |
143 asm("str r7, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqNestCount)); // increment i_IrqNestCount |
143 |
144 |
144 asm("1: "); |
145 asm("1: "); |
145 #ifdef BTRACE_CPU_USAGE |
146 #ifdef BTRACE_CPU_USAGE |
146 asm("ldr r2, __BTraceCpuUsageFilter "); |
147 asm("ldr r2, __BTraceCpuUsageFilter "); |
147 #endif |
148 #endif |
185 asm("beq do_resched_ipi "); |
186 asm("beq do_resched_ipi "); |
186 asm("cmp r2, #%a0" : : "i" ((TInt)GENERIC_IPI_VECTOR)); |
187 asm("cmp r2, #%a0" : : "i" ((TInt)GENERIC_IPI_VECTOR)); |
187 asm("beq do_generic_ipi "); |
188 asm("beq do_generic_ipi "); |
188 asm("cmp r2, #%a0" : : "i" ((TInt)TRANSFERRED_IRQ_VECTOR)); |
189 asm("cmp r2, #%a0" : : "i" ((TInt)TRANSFERRED_IRQ_VECTOR)); |
189 asm("beq do_transferred_ipi "); |
190 asm("beq do_transferred_ipi "); |
|
191 asm("cmp r2, #%a0" : : "i" ((TInt)INDIRECT_POWERDOWN_IPI_VECTOR)); |
|
192 asm("beq do_indirect_powerdown_ipi "); |
190 asm("cmp r2, #15 "); |
193 asm("cmp r2, #15 "); |
191 __JUMP(hi, r11); // if >15 but not TIMESLICE_VECTOR, call dispatcher |
194 __JUMP(hi, r11); // if >15 but not TIMESLICE_VECTOR, call dispatcher |
192 |
195 |
193 // else assume CRASH_IPI |
196 // else assume CRASH_IPI |
194 asm("str r0, [r6, #%a0]" : : "i" _FOFF(GicCpuIfc, iEoi)); // acknowledge interrupt |
197 asm("str r0, [r6, #%a0]" : : "i" _FOFF(GicCpuIfc, iEoi)); // acknowledge interrupt |
196 asm("ldr r1, __HandleCrashIPI "); |
199 asm("ldr r1, __HandleCrashIPI "); |
197 __JUMP(, r1); // CRASH IPI, so crash |
200 __JUMP(, r1); // CRASH IPI, so crash |
198 |
201 |
199 // TIMESLICE, RESCHED or TRANSFERRED |
202 // TIMESLICE, RESCHED or TRANSFERRED |
200 asm("do_timeslice_irq: "); |
203 asm("do_timeslice_irq: "); |
201 asm("ldr r2, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, i_LocalTimerAddr)); |
204 asm("ldr r2, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, iSSX.iLocalTimerAddr)); |
202 asm("mov r1, #1 "); |
205 asm("mov r1, #1 "); |
203 asm("str r1, [r2, #%a0]" : : "i" _FOFF(ArmLocalTimer, iTimerIntStatus)); // clear timer event flag |
206 asm("str r1, [r2, #%a0]" : : "i" _FOFF(ArmLocalTimer, iTimerIntStatus)); // clear timer event flag |
204 asm("do_resched_ipi: "); |
207 asm("do_resched_ipi: "); |
205 asm("mov r1, #1 "); |
208 asm("mov r1, #1 "); |
206 asm("strb r1, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, iRescheduleNeededFlag)); |
209 asm("strb r1, [r4, #%a0]" : : "i" _FOFF(TSubScheduler, iRescheduleNeededFlag)); |
209 __DATA_SYNC_BARRIER_Z__(r1); // ensure writes to i_IrqCount, i_IrqNestCount, iRescheduleNeededFlag complete before SEV |
212 __DATA_SYNC_BARRIER_Z__(r1); // ensure writes to i_IrqCount, i_IrqNestCount, iRescheduleNeededFlag complete before SEV |
210 // also ensure EOI is written before we return from the interrupt |
213 // also ensure EOI is written before we return from the interrupt |
211 ARM_SEV; // kick any CPUs waiting for us to enter the ISR |
214 ARM_SEV; // kick any CPUs waiting for us to enter the ISR |
212 asm("b 1b "); |
215 asm("b 1b "); |
213 |
216 |
|
217 asm("do_indirect_powerdown_ipi: "); |
|
218 asm("str r0, [r6, #%a0]" : : "i" _FOFF(GicCpuIfc, iEoi)); // acknowledge interrupt |
|
219 __DATA_SYNC_BARRIER_Z__(r1); // ensure writes to i_IrqCount, i_IrqNestCount, iRescheduleNeededFlag complete before SEV |
|
220 // also ensure EOI is written before we return from the interrupt |
|
221 ARM_SEV; // kick any CPUs waiting for us to enter the ISR |
|
222 asm("stmfd sp!, {r0-r3,r12,lr} "); |
|
223 asm("bl call_ipd_handler "); |
|
224 asm("ldmfd sp!, {r0-r3,r12,lr} "); |
|
225 asm("b 1b "); |
|
226 |
214 // GENERIC_IPI |
227 // GENERIC_IPI |
215 asm("do_generic_ipi: "); |
228 asm("do_generic_ipi: "); |
216 asm("ldr r2, _GenericIPIIsr "); |
229 asm("ldr r2, _GenericIPIIsr "); |
217 asm("str r0, [r6, #%a0]" : : "i" _FOFF(GicCpuIfc, iEoi)); // acknowledge interrupt |
230 asm("str r0, [r6, #%a0]" : : "i" _FOFF(GicCpuIfc, iEoi)); // acknowledge interrupt |
218 asm("mov r0, r4 "); // r0->SubScheduler |
231 asm("mov r0, r4 "); // r0->SubScheduler |
219 __DATA_SYNC_BARRIER_Z__(r1); |
232 __DATA_SYNC_BARRIER_Z__(r1); |
220 __JUMP(, r2); |
233 __JUMP(, r2); |
221 |
234 |
222 asm("__DebugMsg_longjump_Irq: "); |
235 asm("__DebugMsg_longjump_Irq: "); |
223 asm("ldr pc, _dmIrq "); |
236 asm("ldr pc, _dmIrq "); |
|
237 |
|
238 asm("call_ipd_handler: "); |
|
239 asm("ldr pc, __handle_ipd_ipi "); |
224 |
240 |
225 asm("__reset_vector:"); |
241 asm("__reset_vector:"); |
226 asm(".word __ArmVectorReset "); |
242 asm(".word __ArmVectorReset "); |
227 asm("__undef_vector:"); |
243 asm("__undef_vector:"); |
228 __DECLARE_UNDEFINED_INSTRUCTION_HANDLER; |
244 __DECLARE_UNDEFINED_INSTRUCTION_HANDLER; |