|
浅析armlinux 2.4.19中断irq分发例程的派发流程之根基X4cLinux联盟 X4cLinux联盟 文章来源:http://gliethttp.cublog.cnX4cLinux联盟 X4cLinux联盟 应用程序运行在user模式,对应arm的cpsr&15的值为0,而内核代码运行在svc模式,对应arm的cpsr&15的值为3,X4cLinux联盟 所以,如果应用程序在运行期间,即usr模式下,arm发生了irq中断,那么中断处理代码得知后会调用__irq_usr分发处理例程处理irq中断,如果在系统调用syscall之类使程序运行在内核空间执行内核程序的时候,即svc模式下,arm发生了irq中断,那么中断处理代码得知后会调用__irq_svc分发处理例程处理irq中断,中断程序是怎么识别svc和usr模式,进而派发相应的__irq_usr和__irq_svc分发例程的呢,来看看代码部分:X4cLinux联盟 //1.arch\arm\kernel\entry-armv.SX4cLinux联盟 ...X4cLinux联盟 .LCvswi: .word vector_swiX4cLinux联盟 X4cLinux联盟 .LCsirq: .word __temp_irqX4cLinux联盟 .LCsund: .word __temp_undX4cLinux联盟 .LCsabt: .word __temp_abtX4cLinux联盟 X4cLinux联盟 __stubs_end:X4cLinux联盟 X4cLinux联盟 .equ __real_stubs_start, .LCvectors + 0x200X4cLinux联盟 X4cLinux联盟 .LCvectors: swi SYS_ERROR0X4cLinux联盟 b __real_stubs_start + (vector_undefinstr - __stubs_start)X4cLinux联盟 ldr pc, __real_stubs_start + (.LCvswi - __stubs_start)X4cLinux联盟 b __real_stubs_start + (vector_prefetch - __stubs_start)X4cLinux联盟 b __real_stubs_start + (vector_data - __stubs_start)X4cLinux联盟 b __real_stubs_start + (vector_addrexcptn - __stubs_start)X4cLinux联盟 //irq中断发生后,cpu捕获中断,跳转到这里执行vector_IRQ处理程序[gliethttp_20071225]X4cLinux联盟 //中断处理代码位于0xFFFF0000地址之后的空间中,X4cLinux联盟 //为了更透彻的理解,最好先看看另3篇文章X4cLinux联盟 //《浅析arm-linux中断vector向量表的建立流程》X4cLinux联盟 //《浅析armlinux-setup_arch()->create_mapping()函数5-2-2》X4cLinux联盟 //《浅析arm-linux系统调用的流程》X4cLinux联盟 //文章1:http://blog.chinaunix.net/u1/38994/showart_333925.htmlX4cLinux联盟 //文章2:http://blog.chinaunix.net/u1/38994/showart_353785.htmlX4cLinux联盟 //文章3:http://blog.chinaunix.net/u1/38994/showart_331915.htmlX4cLinux联盟 //为了更好理解上面的这几篇文章,最好先看看《浅析armlinux2.4.19启动程序[head-armv.s文件]》X4cLinux联盟 //文章4:http://blog.chinaunix.net/u1/38994/showart_346701.htmlX4cLinux联盟 b __real_stubs_start + (vector_IRQ - __stubs_start)X4cLinux联盟 b __real_stubs_start + (vector_FIQ - __stubs_start)X4cLinux联盟 ...X4cLinux联盟 //2.arch\arm\kernel\entry-armv.SX4cLinux联盟 ...X4cLinux联盟 vector_IRQ: @X4cLinux联盟 @ save mode specific registersX4cLinux联盟 @X4cLinux联盟 ldr r13, .LCsirq //取出LCsirq变量的地址,用来存放lrX4cLinux联盟 sub lr, lr, #4 //lr-4,这是arm必须的X4cLinux联盟 str lr, [r13] //将计算之后的返回地址lr存入LCsirq变量X4cLinux联盟 //读取此次irq中断发生时,cpu所处模式spsr,即,中断发生时cpu正在用户空间运行用户应用程序,X4cLinux联盟 //还是在内核空间svc模式下运行内核代码,lr&15的数值为arm进入irq之前cpu运行的模式值X4cLinux联盟 //如果lr&15=0表示,此次irq中断发生时,cpu正运行用户空间的用户程序,X4cLinux联盟 //如果lr&15=3表示,此次irq中断发生时,cpu正运行内核空间的内核代码[gliethttp_20071225]X4cLinux联盟 mrs lr, spsrX4cLinux联盟 str lr, [r13, #4]X4cLinux联盟 X4cLinux联盟 mrs r13, cpsrX4cLinux联盟 bic r13, r13, #MODE_MASKX4cLinux联盟 orr r13, r13, #I_BIT | MODE_SVCX4cLinux联盟 //切换到svc模式,因为当前cpsr为irq模式,所以可以修改cpsr,X4cLinux联盟 //注意在usr模式下cpsr的数值,即使使用了msr spsr_c, r13赋值语句,X4cLinux联盟 //因为usr模式不允许修改cpsr,所以r13的数值并不能被真正赋值给spsr,X4cLinux联盟 //执行完赋值语句之后,spsr的数值不会发生任何改变,仍然是原来的值[gliethttp_20071225]X4cLinux联盟 msr spsr_c, r13 X4cLinux联盟 X4cLinux联盟 and lr, lr, #15X4cLinux联盟 //lr&15的值为发生irq之前cpu所在的空间,X4cLinux联盟 //0:在用户空间发生了irq中断X4cLinux联盟 //3:在内核空间发生了irq中断X4cLinux联盟 //lr<<2=lr*4也就是pc+0和pc+12X4cLinux联盟 //分别对应LCtab_irq的.word __irq_usr域和.word __irq_svc域X4cLinux联盟 ldr lr, [pc, lr, lsl #2]X4cLinux联盟 //跳转到__irq_usr或者__irq_svc处理此次irq中断[gliethttp_20071225]X4cLinux联盟 movs pc, lrX4cLinux联盟 X4cLinux联盟 .LCtab_irq: .word __irq_usr @ 0 (USR_26 / USR_32)//用户空间发生irq中断X4cLinux联盟 .word __irq_invalid @ 1 (FIQ_26 / FIQ_32)X4cLinux联盟 .word __irq_invalid @ 2 (IRQ_26 / IRQ_32)X4cLinux联盟 .word __irq_svc @ 3 (SVC_26 / SVC_32)//内核空间发生irq中断X4cLinux联盟 .word __irq_invalid @ 4 X4cLinux联盟 .word __irq_invalid @ 5X4cLinux联盟 .word __irq_invalid @ 6X4cLinux联盟 .word __irq_invalid @ 7X4cLinux联盟 .word __irq_invalid @ 8X4cLinux联盟 .word __irq_invalid @ 9X4cLinux联盟 .word __irq_invalid @ aX4cLinux联盟 .word __irq_invalid @ bX4cLinux联盟 .word __irq_invalid @ cX4cLinux联盟 .word __irq_invalid @ dX4cLinux联盟 .word __irq_invalid @ eX4cLinux联盟 .word __irq_invalid @ fX4cLinux联盟 ...X4cLinux联盟 .LCvswi: .word vector_swiX4cLinux联盟 .LCsirq: .word __temp_irqX4cLinux联盟 .LCsund: .word __temp_undX4cLinux联盟 .LCsabt: .word __temp_abtX4cLinux联盟 ...
Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论 |
|