Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15530751
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2007-12-25 11:21:43

浅析armlinux 2.4.19中断irq分发例程的派发流程之根基

文章来源:http://gliethttp.cublog.cn

应用程序运行在user模式,对应arm的cpsr&15的值为0,而内核代码运行在svc模式,对应arm的cpsr&15的值为3,
所以,如果应用程序在运行期间,即usr模式下,arm发生了irq中断,那么中断处理代码得知后会调用__irq_usr分发处理例程处理irq中断,如果在系统调用syscall之类使程序运行在内核空间执行内核程序的时候,即svc模式下,arm发生了irq中断,那么中断处理代码得知后会调用__irq_svc分发处理例程处理irq中断,中断程序是怎么识别svc和usr模式,进而派发相应的__irq_usr和__irq_svc分发例程的呢,来看看代码部分:
//1.arch\arm\kernel\entry-armv.S
...
.LCvswi:    .word    vector_swi

.LCsirq:    .word    __temp_irq
.LCsund:    .word    __temp_und
.LCsabt:    .word    __temp_abt

__stubs_end:

        .equ    __real_stubs_start, .LCvectors + 0x200

.LCvectors:    swi    SYS_ERROR0
        b    __real_stubs_start + (vector_undefinstr - __stubs_start)
        ldr    pc, __real_stubs_start + (.LCvswi - __stubs_start)
        b    __real_stubs_start + (vector_prefetch - __stubs_start)
        b    __real_stubs_start + (vector_data - __stubs_start)
        b    __real_stubs_start + (vector_addrexcptn - __stubs_start)
//irq中断发生后,cpu捕获中断,跳转到这里执行vector_IRQ处理程序[gliethttp_20071225]
//中断处理代码位于0xFFFF0000地址之后的空间中,
//为了更透彻的理解,最好先看看另3篇文章
//《浅析arm-linux中断vector向量表的建立流程》
//《浅析armlinux-setup_arch()->create_mapping()函数5-2-2》
//《浅析arm-linux系统调用的流程》
//文章1:http://blog.chinaunix.net/u1/38994/showart_333925.html
//文章2:http://blog.chinaunix.net/u1/38994/showart_353785.html
//文章3:http://blog.chinaunix.net/u1/38994/showart_331915.html
//为了更好理解上面的这几篇文章,最好先看看《浅析armlinux2.4.19启动程序[head-armv.s文件]》
//文章4:http://blog.chinaunix.net/u1/38994/showart_346701.html
        b    __real_stubs_start + (vector_IRQ - __stubs_start)
        b    __real_stubs_start + (vector_FIQ - __stubs_start)
...
//2.arch\arm\kernel\entry-armv.S
...
vector_IRQ:    @
        @ save mode specific registers
        @
        ldr    r13, .LCsirq    //取出LCsirq变量的地址,用来存放lr
        sub    lr, lr, #4        //lr-4,这是arm必须的
        str    lr, [r13]        //将计算之后的返回地址lr存入LCsirq变量
//读取此次irq中断发生时,cpu所处模式spsr,即,中断发生时cpu正在用户空间运行用户应用程序,
//还是在内核空间svc模式下运行内核代码,lr&15的数值为arm进入irq之前cpu运行的模式值
//如果lr&15=0表示,此次irq中断发生时,cpu正运行用户空间的用户程序,
//如果lr&15=3表示,此次irq中断发生时,cpu正运行内核空间的内核代码[gliethttp_20071225]
        mrs    lr, spsr
        str    lr, [r13, #4]

        mrs    r13, cpsr
        bic    r13, r13, #MODE_MASK
        orr    r13, r13, #I_BIT | MODE_SVC
//切换到svc模式,因为当前cpsr为irq模式,所以可以修改cpsr,
//注意在usr模式下cpsr的数值,即使使用了msr spsr_c, r13赋值语句,
//因为usr模式不允许修改cpsr,所以r13的数值并不能被真正赋值给spsr,
//执行完赋值语句之后,spsr的数值不会发生任何改变,仍然是原来的值[gliethttp_20071225]
        msr    spsr_c, r13    

        and    lr, lr, #15
//lr&15的值为发生irq之前cpu所在的空间,
//0:在用户空间发生了irq中断
//3:在内核空间发生了irq中断
//lr<<2=lr*4也就是pc+0和pc+12
//分别对应LCtab_irq的.word __irq_usr域和.word __irq_svc域
        ldr    lr, [pc, lr, lsl #2]
//跳转到__irq_usr或者__irq_svc处理此次irq中断[gliethttp_20071225]
        movs    pc, lr

.LCtab_irq: .word    __irq_usr            @ 0 (USR_26 / USR_32)//用户空间发生irq中断
        .word    __irq_invalid            @ 1 (FIQ_26 / FIQ_32)
        .word    __irq_invalid            @ 2 (IRQ_26 / IRQ_32)
        .word    __irq_svc                @ 3 (SVC_26 / SVC_32)//内核空间发生irq中断
        .word    __irq_invalid            @ 4
        .word    __irq_invalid            @ 5
        .word    __irq_invalid            @ 6
        .word    __irq_invalid            @ 7
        .word    __irq_invalid            @ 8
        .word    __irq_invalid            @ 9
        .word    __irq_invalid            @ a
        .word    __irq_invalid            @ b
        .word    __irq_invalid            @ c
        .word    __irq_invalid            @ d
        .word    __irq_invalid            @ e
        .word    __irq_invalid            @ f
...
.LCvswi:    .word    vector_swi
.LCsirq:    .word    __temp_irq
.LCsund:    .word    __temp_und
.LCsabt:    .word    __temp_abt
...

阅读(1753) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-06-10 11:57:39

看了你的文章受益匪浅