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