arch/arm/kernel/entry-armv.S
447 .align 5
448 __irq_usr: 449 usr_entry @保存usr mode下的寄存器,有详细介绍。
450 kuser_cmpxchg_check
451
452 get_thread_info tsk @通过将sp的低13位设为0获得task指针。
453 #ifdef CONFIG_PREEMPT
454 ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
455 add r7, r8, #1 @ increment it
456 str r7, [tsk, #TI_PREEMPT]
457 #endif
458
459 irq_handler @irq处理函数,这个函数的核心,下面详细介绍。
460 #ifdef CONFIG_PREEMPT
461 ldr r0, [tsk, #TI_PREEMPT]
462 str r8, [tsk, #TI_PREEMPT]
463 teq r0, r7
464 ARM( strne r0, [r0, -r0] )
465 THUMB( movne r0, #0 )
466 THUMB( strne r0, [r0] )
467 #endif
468 #ifdef CONFIG_TRACE_IRQFLAGS
469 bl trace_hardirqs_on
470 #endif
471
472 mov why, #0
473 b ret_to_user
474 UNWIND(.fnend )
475 ENDPROC(__irq_usr)
|
L449 usr_entry
arch/arm/kernel/entry-armv.S
360 .macro usr_entry
361 UNWIND(.fnstart )
362 UNWIND(.cantunwind ) @ do not unwind the user space
363 sub sp, sp, #S_FRAME_SIZE
364 ARM( stmib sp, {r1 - r12} )
365 THUMB( stmia sp, {r0 - r12} )
366
367 ldmia r0, {r1 - r3}
368 add r0, sp, #S_PC @ here for interlock avoidance
369 mov r4, #-1 @ "" "" "" ""
370
371 str r1, [sp] @ save the "real" r0 copied
372 @ from the exception stack
373
374 @
375 @ We are now ready to fill in the remaining blanks on the stack:
376 @
377 @ r2 - lr_<exception>, already fixed up for correct return/restart
378 @ r3 - spsr_<exception>
379 @ r4 - orig_r0 (see pt_regs definition in ptrace.h)
380 @
381 @ Also, separately save sp_usr and lr_usr
382 @
383 stmia r0, {r2 - r4}
384 ARM( stmdb r0, {sp, lr}^ )
385 THUMB( store_user_sp_lr r0, r1, S_SP - S_PC )
386
387 @
388 @ Enable the alignment trap while in kernel mode
389 @
390 alignment_trap r0
391
392 @
393 @ Clear FP to mark the first stack frame
394 @
395 zero_fp
396
397 asm_trace_hardirqs_off
398 .endm
|
L452 get_thread_info tsk
通过把寄存器sp的低13位置0获得task的指针。
L459 irq_handler
arch/arm/kernel/entry-armv.S
28 /*
29 * Interrupt handling. Preserves r7, r8, r9
30 */
31 .macro irq_handler
32 get_irqnr_preamble r5, lr
33 1: get_irqnr_and_base r0, r6, r5, lr @获得irq number放在r0中
34 movne r1, sp @如果r0(irq number)非0,将r1设为sp(struct pt_regs).这是为调用asm_do_IRQ()做准备,r0和r1是asm_do_IRQ()的两个参数。
35 @
36 @ routine called with r0 = irq number, r1 = struct pt_regs *
37 @
38 adrne lr, BSYM(1b) @设置asm_do_IRQ()的返回地址是1:。循环获得下一个irq number并调用asm_do_IRQ(),直到所有的irq number被处理完毕。
39 bne asm_do_IRQ
40
41 #ifdef CONFIG_SMP
42 /*
43 * XXX
44 *
45 * this macro assumes that irqstat (r6) and base (r5) are
46 * preserved from get_irqnr_and_base above
47 */
48 test_for_ipi r0, r6, r5, lr
49 movne r0, sp
50 adrne lr, BSYM(1b)
51 bne do_IPI
52
53 #ifdef CONFIG_LOCAL_TIMERS
54 test_for_ltirq r0, r6, r5, lr
55 movne r0, sp
56 adrne lr, BSYM(1b)
57 bne do_local_timer
58 #endif
59 #endif
60
61 .endm
|
L32 get_irqnr_preamble r5, lr
L33 1: get_irqnr_and_base r0, r6, r5, lr
这两个宏都是在arch/arm/mach-xxxxxxx/include/mach/entry-macro.S中定义。用来获得最高优先级的irq number.
L39 bne asm_do_IRQ
100 /*
101 * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
102 * come via this function. Instead, they should provide their
103 * own 'handler'
104 */
105 asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
106 {
107 struct pt_regs *old_regs = set_irq_regs(regs);
108
109 irq_enter();
110
111 /*
112 * Some hardware gives randomly wrong interrupts. Rather
113 * than crashing, do something sensible.
114 */
115 if (unlikely(irq >= NR_IRQS)) {
116 if (printk_ratelimit())
117 printk(KERN_WARNING "Bad IRQ%u\n", irq);
118 ack_bad_irq(irq);
119 } else {
120 generic_handle_irq(irq);
121 }
122
123 /* AT91 specific workaround */
124 irq_finish(irq);
125
126 irq_exit();
127 set_irq_regs(old_regs);
128 }
|
L120 generic_handle_irq(irq);
302 /*
303 * Architectures call this to let the generic IRQ layer
304 * handle an interrupt. If the descriptor is attached to an
305 * irqchip-style controller then we call the ->handle_irq() handler,
306 * and it calls __do_IRQ() if it's attached to an irqtype-style controller.
307 */
308 static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
309 {
310 #ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
311 desc->handle_irq(irq, desc);
312 #else
313 if (likely(desc->handle_irq))
314 desc->handle_irq(irq, desc);
315 else
316 __do_IRQ(irq); //如果未定义desc->handle_irq(),调用通过的irq处理函数__do_IRQ(irq).
317 #endif
318 }
319
320 static inline void generic_handle_irq(unsigned int irq)
321 {
322 generic_handle_irq_desc(irq, irq_to_desc(irq));
323 }
|
每个平台的irq及其handle_irq都是在平台目录的下的irq.c文件里设置的。
arch/arm/mach-comcerto/irq.c
168 void __init comcerto_irq_init(struct comcerto_irq_desc *irq_table, int size)
169 {
170 unsigned int irq;
171 int i;
172
173 spin_lock_init(&comcerto_irq_lock);
174
175 /* mask all interrupts */
176 __raw_writel(0, COMCERTO_INTC_CSP_IRQMASK_0);
177 __raw_writel(0, COMCERTO_INTC_CSP_IRQMASK_1);
178
179 for (i = 0; i < size; i++) {
180 irq = irq_table[i].num;
181
182 /* setup interrupt handler and priority */
183 if (irq < 32) {
184 /* All STATUS0 interrupts must be setup from the single table declared in comcerto-xxx.c
185 * file. Use description index as a priority.
186 */
187 comcerto_irq_priority_set(irq, irq_table[i].prio);
188 set_irq_chip(irq, &comcerto_irq_chip_0);
189 } else
191 set_irq_chip(irq, &comcerto_irq_chip_1);
192
193 if (irq_table[i].handler != NULL) {
194 set_irq_handler(irq, irq_table[i].handler);
195 set_irq_flags(irq, IRQF_VALID);
196 }
197 }
198 }
|
阅读(2164) | 评论(0) | 转发(0) |