欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

3、linux中断中(异常向量详解)

程序员文章站 2024-02-25 15:04:09
...

中断程序完成了从asm代码到C代码的传递,并且获得了引起中断的IRQ编号

中断向量表在arch/arm/kernel/entry_armv.S中定义

3、linux中断中(异常向量详解)

代码被分为两部分:
第一部分是真正的向量跳转表,位于__vectors_start__vectors_end之间;
第二部分是处理跳转的部分,位于__stubs_start__stubs_end之间;

  .globl  __stubs_start  
__stubs_start:  

    vector_stub irq, IRQ_MODE, 4  

    .long   __irq_usr           @  0  (USR_26 / USR_32)  
    .long   __irq_invalid           @  1  (FIQ_26 / FIQ_32)  
    .long   __irq_invalid           @  2  (IRQ_26 / IRQ_32)  
    .long   __irq_svc           @  3  (SVC_26 / SVC_32)  

    vector_stub dabt, ABT_MODE, 8  

    .long   __dabt_usr          @  0  (USR_26 / USR_32)  
    .long   __dabt_invalid          @  1  (FIQ_26 / FIQ_32)  
    .long   __dabt_invalid          @  2  (IRQ_26 / IRQ_32)  
    .long   __dabt_svc          @  3  (SVC_26 / SVC_32)  

vector_fiq:  
    disable_fiq  
    subs    pc, lr, #4  
    ......  
    .globl  __stubs_end  
__stubs_end:  



    .equ    stubs_offset, __vectors_start + 0x200 - __stubs_start  
    .globl  __vectors_start  
__vectors_start:  
 ARM(   swi SYS_ERROR0  )  
 THUMB( svc #0      )  
 THUMB( nop         )  
    W(b)    vector_und + stubs_offset  
    W(ldr)  pc, .LCvswi + stubs_offset  
    W(b)    vector_pabt + stubs_offset  
    W(b)    vector_dabt + stubs_offset  
    W(b)    vector_addrexcptn + stubs_offset  
    W(b)    vector_irq + stubs_offset  
    W(b)    vector_fiq + stubs_offset  

    .globl  __vectors_end  
__vectors_end:  

中断向量表的使用:

3、linux中断中(异常向量详解)
1. 首先,在setup_arch函数中,early_trap_init被调用,其中完成了中断向量的拷贝和重定位工作。

void __init early_trap_init(void)  
{  
    ......  
    /* 
     * Copy the vectors, stubs and kuser helpers (in entry-armv.S) 
     * into the vector page, mapped at 0xffff0000, and ensure these 
     * are visible to the instruction stream. 
     */  
    memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);  
    memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);  
    ......  
}  

两个memcpy会把__vectors_start开始的代码拷贝到0xffff0000处,把__stubs_start开始的代码拷贝到0xFFFF0000+0x200处,这样,异常中断到来时,CPU就可以正确地跳转到相应中断向量入口并执行他们。
3、linux中断中(异常向量详解)


  1. 然后,start_kernel发出early_irq_init调用,early_irq_init属于与硬件和平台无关的通用逻辑层,它完成irq_desc结构的内存申请,为它们其中某些字段填充默认值,完成后调用体系相关的arch_early_irq_init函数完成进一步的初始化工作,不过ARM体系没有实现arch_early_irq_init

  2. 接着,start_kernel发出init_IRQ调用,它会直接调用所属板子machine_desc结构体中的init_irq回调。machine_desc通常在板子的特定代码中,使用MACHINE_START和MACHINE_END宏进行定义。
    machine_desc->init_irq()完成对中断控制器的初始化,为每个irq_desc结构安装合适的流控handler,为每个irq_desc结构安装irq_chip指针,使他指向正确的中断控制器所对应的irq_chip结构的实例,同时,如果该平台中的中断线有多路复用(多个中断公用一个irq中断线)的情况,还应该初始化irq_desc中相应的字段和标志,以便实现中断控制器的级联。