x86 kernel 中断分析三——中断处理流程

本文详细分析了x86架构下CPU如何检测中断、查找IDT、处理中断,包括interrupt数组的使用、中断栈的定义、初始化和切换,以及在handle_IRQ过程中的关键步骤。内容涵盖从中断检测到中断服务程序执行的完整流程。
摘要由CSDN通过智能技术生成

CPU检测中断

CPU在执行每条程序之前会检测是否有中断到达,即中断控制器是否有发送中断信号过来

查找IDT

CPU根据中断向量到IDT中读取对应的中断描述符表项,根据段选择符合偏移确定中断服务程序的地址见附录2

interrupt数组

在分析一中,我们看到,填充IDT中断服务程序的是interrupt数组的内容,所以第2步跳转到interrupt数组对应的表项,表项的内容之前也已分析过

push vector num and jmp to common_interrupt

 778 /*
 779  * the CPU automatically disables interrupts when executing an IRQ vector,
 780  * so IRQ-flags tracing has to follow that:
 781  */
 782     .p2align CONFIG_X86_L1_CACHE_SHIFT
 783 common_interrupt:
 784     ASM_CLAC
 785     addl $-0x80,(%esp)  /* Adjust vector into the [-256,-1] range */ 
 786     SAVE_ALL
 787     TRACE_IRQS_OFF
 788     movl %esp,%eax
 789     call do_IRQ
 790     jmp ret_from_intr
 791 ENDPROC(common_interrupt)
 792     CFI_ENDPROC
addl $-0x80,(%esp)

根据第一篇分析,此时栈顶是(~vector + 0x80),这里减去0x80,所以值为vector num取反,范围在[-256, -1]。这么做是为了和系统调用区分,正值为系统调用号,负值为中断向量。

SAVE_ALL

保存现场,将所有寄存器的值压栈(cs eip ss esp由系统自动保存)

186 .macro SAVE_ALL
 187     cld
 188     PUSH_GS
 189     pushl_cfi %fs
 190     /*CFI_REL_OFFSET fs, 0;*/
 191     pushl_cfi %es
 192     /*CFI_REL_OFFSET es, 0;*/
 193     pushl_cfi %ds
 194     /*CFI_REL_OFFSET ds, 0;*/
 195     pushl_cfi %eax
 196     CFI_REL_OFFSET eax, 0
 197     pushl_cfi %ebp
 198     CFI_REL_OFFSET ebp, 0
 199     pushl_cfi %edi
 200     CFI_REL_OFFSET edi, 0
 201     pushl_cfi %esi
 202     CFI_REL_OFFSET esi, 0
 203     pushl_cfi %edx
 204     CFI_REL_OFFSET edx, 0
 205     pushl_cfi %ecx
 206     CFI_REL_OFFSET ecx, 0
 207     pushl_cfi %ebx
 208     CFI_REL_OFFSET ebx, 0
 209     movl $(__USER_DS), %edx
 210     movl %edx, %ds
 211     movl %edx, %es
 212     movl $(__KERNEL_PERCPU), %edx
 213     movl %edx, %fs
 214     SET_KERNEL_GS %edx
 215 .endm
movl %esp,%eax

将esp的值赋值给eax,eax作为do_IRQ的第一个参数,esp的值是以上压栈的寄存器的内容,以pt_reg形式传过去。

call do_IRQ

175 /*
176  * do_IRQ handles all normal device IRQ's (the special
177  * SMP cross-CPU interrupts have their own specific
178  * handlers).
179  */
180 __visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
181 {
182     struct pt_regs *old_regs = set_irq_regs(regs);
183
184     /* high bit used in ret_from_ code  */
185     unsigned vector = ~regs->orig_ax;       //获取向量号,这里有一个取反的操作,与之前的取反相对应得到正的向量号
186     unsigned irq;
187
188     irq_enter();
189     exit_idle();
190
191     irq = __this_cpu_read(vector_irq[vector]);       //通过向量号得到中断号
192
193     if (!handle_irq(irq, regs)) {
194         ack_APIC_irq();
195
196         if (irq != VECTOR_RETRIGGERED) {
197             pr_emerg_ratelimited("%s: %d.%d No irq handler for vector (irq %d)\n",
198                          __func__, smp_processor_id(),
199                          vector, irq);
200         } else {
201             __this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
202         }
203     }
204
205
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值