中断处理程序,也叫Interupt Handler或中断服务例程(ISR),是中断发生后运行的一系列代码,一般用作对中断的响应。在我的内核中,构建了一个简单的框架,方便新处理函数的加入。
加入新ISR
- 编写一个处理程序,参数为一个整型IRQ号
- 调用add_isr(),参数依次为irq号和处理函数的地址
在内核中,add_isr可以在任何地方调用,但初始化内核时集中在interupt.c文件中的setup_idt()中以便于管理。
框架原理
isr_tbl
isr_tbl[ISR_NUM]是一个int_handler也就是函数指针类型的数组,存放着ISR,IRQ号顺序对应。内核最多支持ISR_NUM个中断类型。事实上add_isr函数就是在操作这个数组。
汇编头
isr_tbl中的函数只是中断处理的一部分,现场保护和堆栈切换都在interupt_entry.asm文件中用汇编实现。以时间中断(0号中断)为例:
        sub     esp, 4
        pushad
        push    ds
        push    es
        push    fs
        push    gs
        mov     dx, ss          ; ss's DPL is 0 which others want to be
        mov     ds, dx
        mov     es, dx
        in      al, 0x21        ; block same interupt source
        or      al, (1<<**0**)
        out     0x21, al
        mov     al, 0x20        ; EndOfInterupt
        out     0x20, al
        inc     dword [k_reenter]
        cmp     dword [k_reenter], 0
        jne     .re_enter**0**
        mov     esp, (kernel_stack + KERNEL_STACK_SIZE)
        sti
        push    **0**
        call    (isr_tbl + 4 * **0**)
        add     esp, 4
        cli
        mov     esp, [ready_task]
        lldt    [esp + (18*4)]
        lea     eax, [esp + (18*4)]
        mov     dword [itss + 4], eax
.re_enter**0**:
        in      al, 0x21        ; restore the same interupt
        and     al, ~(1<<**0**)
        out     0x21, al
        dec     dword [k_reenter]
        pop     gs
        pop     fs
        pop     es
        pop     ds
        popad
        add     esp, 4
        iretd