arm linux 下中断流程简要分析中断处理流程
是thread_info对象,即该栈拥有者线程的对象,而get_thread_info就是通过把sp低13位清0(8K边界)来获取当前thread_info对象的地址。
arch/arm/kernel/entry-armv.S:
.macroget_thread_info, rd
mov/rd, sp, lsr #13
mov/rd, /rd, lsl #13
.endm
调用该宏后寄存器tsk里存放的就是当前线程的地址了,tsk是哪个寄存器呢,我们在看:
arch/arm/kernel/entry-header.S:
tsk.reqr9@ current thread_info
,tsk只是r9的别名而已, 因此这时r9里保存的就是当前线程的地址。
我们接着看irq_handler:
arch/arm/kernel/entry-armv.S:
.macroirq_handler
1:get_irqnr_and_base r0, r6, r5, lr@平台相关,获取中断号
movner1, sp@如果r0(中断号)不等于0,则r1指向sp所在地址,即pt_regs对象地址(看上图)
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
adrnelr, 1b@如果r0(中断号)不等于0,lr(返回地址)等于标号1处,即
@ get_irqnr_and_base r0, r6, r5, lr的那行,即循环处理所有的中断。
bneasm_do_IRQ@处理该中断
#ifdef CONFIG_SMP
/*
* XXX
*
* this macro assumes that irqstat (r6) and base (r5) are
* preserved from get_irqnr_and_base above
*/
test_for_ipi r0, r6, r5, lr
movner0, sp
adrnelr, 1b
bnedo_IPI
#ifdef CONFIG_LOCAL_TIMERS
test_for_ltirq r0, r6, r5, lr
movner0, sp
adrnelr, 1b
bnedo_local_timer
#endif
#endif
.endm
get_irqnr_and_base是平台相关的,这里就不列出来了,对于s3c2410,代码在include/asm-arm/s3c2410/entry-macro.S里,该宏处理完后,r0 =中断号,接下来r1赋值为sp地址(pt_regs对象地址), 最后调用c函数asm_do_IRQ, r0, r1作为参数被传递进去。asm_do_IRQ()处理完后将返回到lr指向的地址处即上面汇编部分标号为1的地址处继续执行。
我们把__irq_usr的汇编部分分析完后再来分析asm_do_IRQ()等c函数。
Arch/arm/kernel/entry-armv.S:
__irq_usr:
……
……
mov why, #0@ why = 0, why是r8的别名,
b ret_to_user@返回到用户模式下
我们看ret_to_user
arch/arm/kernel/entry-common.S:
ENTRY(ret_to_user)
ret_slow_syscall:
disable_irq@ disable interrupts@关中断,
ldrr1, [tsk, #TI_FLAGS] @获取thread_info中flags域的值
tstr1, #_TIF_WORK_MASK@判断task是否被阻塞
bnework_pending@根据需要进行进程的切换。
no_work_pending:
@ slow_restore_user_regs
ldrr1, [sp, #S_PSR]@ get calling cpsr获取被中断代码处的状态(cpsp)
ldrlr, [sp, #S_PC]!@ get pc获取返回地址(被中断代码的下条代码处的地址)
msrspsr_cxsf, r1@ save in spsr_svc, spsr里保存好被中断代码处的状态(cpsp)
ldmdbsp, {r0 - lr}^@ get calling r1 – lr从栈上获取用户态下的r0到lr的值
movr0, r0
addsp, sp, #S_FRAME_SIZE - S_PC@栈地址恢复,避免多个中断后溢出
movspc, lr@ return & move spsr_svc into cpsr, 返回被中断代码处继续执行,并把spsr赋给cpsp,即恢复被中断处的现场状态。这样CPU又可以从被中断的地方继续执行了,而且这个时候所有的寄存器值(r0到r12),包括状态寄存器值(cpsr)都是源码被中断时的值。
我们顺便看下work_pending
arch/arm/kernel/entry-common.S:
work_pending:
tstr1, #_TIF_NEED_RESCHED@判断是否需要调度进程
bnework_resched@进程调度
tstr1, #_TIF_NOTIFY_RESUME | _TIF_SIGPENDING
beqno_work_pending@无需调度,返回
movr0, sp@ regs
movr2, why@ syscall
bldo_notify_resume
bret_slow_syscall@ Check work again
由该汇编可知,如果在用户模式下产生中断的话,在返回的时候,会根据需要进行进程调度,而从代码可知,如果中断发生在管理等内核模式下的话是不会进行进程调度的。
Ok,中断的流程大体就是这样的,下面我们就开始分析c函数里的中断流程。
先来看asm_do_IRQ
arch/arm/kernel/Irq.c:
/*
* do_IRQ handles all hardware IRQs.Decoded IRQs should not
* come via this function.Instead, they should provide their
* own handler
*/
asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct irqdesc *desc = irq_desc + irq; /*获取中断描述符*/
/*
* Some hardware gives randomly wrong interrupts.Rather
* than crashing, do something sensible.
*/
if (irq >= NR_IRQS)/*参数检查*/
desc = &bad_irq_desc;
irq_enter();
desc_handle_irq(irq, desc, regs);/*中断处理*/
/* AT91 specific workaround */
irq_finish(irq);
irq
armlinux中断处 相关文章:
- ARM linux的中断处理过程(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)