关于init_IRQ的函数分析

init_IRQ() xen启动函数 __start_xen中调用初始化中断的函数,其中有一段代码我认为是挺绕的。经过了一些时间的分析,终于弄明白了分享给大家,也给自己做个记录。

 

for ( vector = FIRST_DYNAMIC_VECTOR; vector < NR_VECTORS; vector++ )

    {

        if (vector == HYPERCALL_VECTOR || vector == LEGACY_SYSCALL_VECTOR)

            continue;

        set_intr_gate(vector, interrupt[vector]);

    }

这段代码看起来没什么稀奇的,但是想要弄明白interrupt[vector],我却用了些心思。

 

xen/arch/x86/i8295.c文件中有这么个定义:

 

    static void (*interrupt[])(void) = {

        IRQLIST_16(0x0), IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),

        IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),

        IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),

        IRQLIST_16(0xc), IRQLIST_16(0xd), IRQLIST_16(0xe), IRQLIST_16(0xf)

    };

 

#define IRQLIST_16(x) /

    IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), /

    IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), /

    IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), /

    IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)

 

#define IRQ(x,y) /

    IRQ##x##y##_interrupt

 

那么这个函数 IRQ##x##y##_interrupt 是什么时候定义的呢?

 

在这个C文件的最顶部有这么一些宏代码

 

BUILD_COMMON_IRQ()

 

#define BI(x,y) /

    BUILD_IRQ(x##y)

 

#define BUILD_16_IRQS(x) /

    BI(x,0) BI(x,1) BI(x,2) BI(x,3) /

    BI(x,4) BI(x,5) BI(x,6) BI(x,7) /

    BI(x,8) BI(x,9) BI(x,a) BI(x,b) /

    BI(x,c) BI(x,d) BI(x,e) BI(x,f)

 

BUILD_16_IRQS(0x0) BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)

BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)

BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)

BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) BUILD_16_IRQS(0xe) BUILD_16_IRQS(0xf)

 

从名字上看好像是创建与 IRQ有关的什么东西。

         跟进看看究竟

 

#define IRQ_NAME2(nr) nr##_interrupt(void)

#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)

 

#define BUILD_IRQ(nr)                          /

asmlinkage void IRQ_NAME(nr);                  /

__asm__(                                      /

"/n"__ALIGN_STR"/n"                           /

STR(IRQ) #nr "_interrupt:/n/t"                     /

    "pushq $0/n/t"                              /

    "movl $"#nr",4(%rsp)/n/t"                    /

"jmp common_interrupt");

 

到这里可能会发现些什么,原来通过以上三个宏的表述可以得到以下结论

 

#define BUILD_IRQ(nr) == asmlinkage void IRQ##nr##_interrupt(void)

 

且在宏#define BUILD_16_IRQS(x) 相当于定义了 256个函数。那么这些函数在那里定义的呢?

看了下面的这段代码我想你就明白了:

 

#define BUILD_COMMON_IRQ()                   /

__asm__(                                        /

    "/n" __ALIGN_STR"/n"                        /

    "common_interrupt:/n/t"                        /

    STR(SAVE_ALL)                             /

    "movq %rsp,%rdi/n/t"                          /

    "callq " STR(do_IRQ) "/n/t"                     /

    "jmp ret_from_intr/n");

 

#define IRQ_NAME2(nr) nr##_interrupt(void)

#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)

 

#define BUILD_IRQ(nr)                           /

asmlinkage void IRQ_NAME(nr);                    /

__asm__(                                        /

"/n"__ALIGN_STR"/n"                             /

STR(IRQ) #nr "_interrupt:/n/t"                    /

    "pushq $0/n/t"                              /

    "movl $"#nr",4(%rsp)/n/t"                    /

    "jmp common_interrupt");

 

 

在文件xen/arch/x86/i8295.c的最开始调用了一个宏,BUILD_COMMON_IRQ(),其它的那些BUILD_IRQ的宏,再预编译的时候,就把自己跳转到标号common_interrupt: 然后走后面的汇编语句,其实到最后是调用do_irq()这个函数。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值