Linux中断处理体系结构

来源:互联网 发布:经传软件免费版 编辑:程序博客网 时间:2024/05/17 00:05

参考:http://blog.chinaunix.net/uid-26606708-id-3342309.html

memcpy((void*)vectors, __vectors_start, __vectors_end- __vectors_start);
    memcpy((void*)vectors + 0x200, __stubs_start, __stubs_end- __stubs_start);

vectors等于0xffff0000。地址__vectors_start ~ __vectors_end之间的代码就是异常向量,在arch/arm/kernel/entry-armv.S中定义,它们复制到地址0xffff0000处。异常向量的代码很简单,它们只是一些跳转指令。发生异常时,CPU自动执行这些指令,跳转去执行更复杂的代码,比如保存被中断程序的执行环境,调用异常处理函数,恢复被中断程序的执行环境并重新运行。这些“更复杂的代码”在地址__stubs_start ~__stubs_end之间,它们在arch/arm/kernel/entry-armv.S中定义。将它们复制到地址0xffff0000+0x200处。 异常向量、异常向量跳去执行的代码都是使用汇编写的,它们在arch/arm/kernel/entry-armv.S中。异常向量的代码如下,其中的“stubs_offset”用来重新定位跳转的位置(向量被复制到地址0xffff0000处,跳转的目的代码被复制到地址0xffff0000+0x200处)。

  1. .equ stubs_offset, __vectors_start + 0x200 - __stubs_start

  2. .globl __vectors_start
  3. __vectors_start:
  4. ARM( swi SYS_ERROR0 )
  5. THUMB( svc #0 )
  6. THUMB( nop )
  7. W(b) vector_und + stubs_offset
  8. W(ldr) pc, .LCvswi + stubs_offset
  9. W(b) vector_pabt + stubs_offset
  10. W(b) vector_dabt + stubs_offset
  11. W(b) vector_addrexcptn + stubs_offset
  12. W(b) vector_irq + stubs_offset
  13. W(b) vector_fiq + stubs_offset

  14. .globl __vectors_end
  15. __vectors_end:

1)找不到标号vector_xxxx

原来vector_xxxx就在arch/arm/kernel/entry-armv.S中。

2)stubs_offset的理解

vector为异常向量基址,unsigned long vectors = CONFIG_VECTORS_BASE。
在arch/arm/kernel/entry-armv.S中,stubs_offset定义为:
.equ    stubs_offset, __vectors_start + 0x200 - __stubs_start????????

我们把搬移前的中断向量表中的irq入口地址记
irq_PC,它在中断向量表的偏移量就是irq_PC-vectors_start,
vector_irq在stubs中的偏移量是vector_irq-stubs_start,这两个偏移量在搬移前后是不变的。

memcpy的函数原型为:void *memcpy(void *dest, const void *src, size_t n);从下面代码的3个memcpy()函数可以看出,vectors~vectors+ 0x200存储的异常向量,B vector_<exception>,中断向量;vectors+ 0x200~vectors + 0x1000存储的具体异常的处理分支,而这个分支视乎只是地址,vector_<exception>
,跳转表。
arch/arm/kernel/entry-armv.S中的标号,那程序是怎么实现跳转的呢?????

 

中断的处理流程如下:
1)发生中断时,CPU执行异常向量vector_irq的代码。
2)在vector_irq里面,最终会调用中断处理的总入口函数asm_do_IRQ。
3)asm_do_IRQ根据中断号调用irq_desc数组项中的handle_irq。
4)handle_irq会使用chip成员中的函数来设置硬件,比如清楚中断,禁止中断,重新使能中断等。
5)handle_irq逐个调用用户在action链表中注册的处理函数。