浅析armlinux 2.4.19中断irq分发例程的派发流程之根基 |
| 时间:2008-06-06 11:46:44 来源: 作者: |
应用程序运行在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 ...
|
|
|
|