关于init_IRQ的函数分析
2010-08-19 18:54
274 查看
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()这个函数。
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()这个函数。
相关文章推荐
- libsvm代码阅读:关于svm_train函数分析
- Linux中的内存页表创建之memtable_init()函数分析
- 最新版ffmpeg源码分析三:transcode_init()函数
- 关于container_of和list_for_each_entry 及其相关函数的分析
- 关于container_of和list_for_each_entry 及其相关函数的分析
- [Funkunux] Linux_2.6.22.6 内核 start_kernel 函数分析之 rest_init
- 关于分析函数参数传递是值传递还是地址传递
- 关于vs2005中添加对话框初始化函数initdialog;
- 函数分析AndroidInitProcess分析心得(2)
- 关于动态存储分配函数的调用,在已经过排序的数组中查找及删除内容的操作,余数的分析,删除字符数组中的空格,对链表的逆置,在源字符串中查找子字符串的个数,函数指针以及函数的调用,循环赋值带来的问题以及插入
- 004:STM32启动文件详解及SystemInit函数分析(转)
- uboot的jumptable_init函数分析
- 关于DB2与ORACLE相关常用函数比较分析
- 最新版ffmpeg源码分析三:transcode_init()函数
- 关于hive分析函数
- ffmpeg源码分析:transcode_init()函数
- 低功耗蓝牙cc2541学习笔记之无线通信- 分析SimpleBLEPeripheral_Init()函数
- STM32启动文件详解及SystemInit函数分析(转)
- Linux中的内存分配和释放之free_area_init_node()函数分析
- Kernel/ init/calibrate.c 文件中 alibrate_delay() 函数分析