浅析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 ...
|