linux0.11中断处理源码初探

2019-04-23 18:26:01 浏览数 (1)

系统初始化的时候,定义和初始化了中断向量表。并初始化8259的工作方式。

代码语言:javascript复制
// 加载idt的基地址和限长到idt寄存器
lidt idt_descr
// 定义
idt_descr:
    .word 256*8-1       # idt contains 256 entries
    .long _id
// 初始化
_idt:    .fill 256,8,0

所以idt的内容是一个单位是8字节,长度是256的数组。linux0.11分为中断、系统、陷阱门。系统在启动的时候设置idt。

代码语言:javascript复制
void trap_init(void)
{
    int i;

    set_trap_gate(0,&divide_error);
    set_trap_gate(1,&debug);
    set_trap_gate(2,&nmi);
    set_system_gate(3,&int3);   /* int3-5 can be called from all */
    set_system_gate(4,&overflow);
    set_system_gate(5,&bounds);
    set_trap_gate(6,&invalid_op);
    set_trap_gate(7,&device_not_available);
    set_trap_gate(8,&double_fault);
    set_trap_gate(9,&coprocessor_segment_overrun);
    set_trap_gate(10,&invalid_TSS);
    set_trap_gate(11,&segment_not_present);
    set_trap_gate(12,&stack_segment);
    set_trap_gate(13,&general_protection);
    // 缺页和写保护异常处理函数
    set_trap_gate(14,&page_fault);
    set_trap_gate(15,&reserved);
    set_trap_gate(16,&coprocessor_error);
    for (i=17;i<48;i  )
        set_trap_gate(i,&reserved);
    set_trap_gate(45,&irq13);
    // 允许8259接收中断
    outb_p(inb_p(0x21)&0xfb,0x21);
    outb(inb_p(0xA1)&0xdf,0xA1);
    set_trap_gate(39,&parallel_interrupt);
}
代码语言:javascript复制
#define _set_gate(gate_addr,type,dpl,addr) 
// 把dx即处理函数地址的低16位赋值给ax,不影响eax的高16位
__asm__ ("movw %%dx,%%axnt" 
    /*
        设置idt描述符的第三个字节的内容,左移位数是字段对应的位置偏移,
        相加后赋值给dx,共16位,edx的高16位保存了处理函数的高16位地址
    */
    "movw %0,%%dxnt" 
    // 把eax即0x000080000   处理函数的地址赋值给idt描述符的前两个字节
    "movl %�x,%1nt" 
    // 把edx的内容写入idt描述符的第5-8个字节
    "movl %�x,%2" 
    : 
    : "i" ((short) (0x8000 (dpl<<13) (type<<8))), 
    // o表示使用内存地址并可以加偏移量
    "o" (*((char *) (gate_addr))), 
    // 指向保存选择子的首地址
    "o" (*(4 (char *) (gate_addr))), 
    // edx等于addr,eax等于0x00080000
    "d" ((char *) (addr)),"a" (0x00080000))

#define set_intr_gate(n,addr) 
    _set_gate(&idt[n],14,0,addr)

#define set_trap_gate(n,addr) 
    _set_gate(&idt[n],15,0,addr)

#define set_system_gate(n,addr) 
    _set_gate(&idt[n],15,3,addr)

其中idt描述符格式是,这个版本貌似还没有任务门。

在这里插入图片描述 还有一些是键盘,软盘等也设置中断。下面看一个异常处理程度。就是缺页或写保护异常的时候触发的

代码语言:javascript复制
.globl _page_fault

_page_fault:
    // 交换两个寄存器的值,esp指向的位置保存了错误码
    xchgl �x,(%esp)
    // 压栈寄存器
    pushl �x
    pushl �x
    push %ds
    push %es
    push %fs
    // 内核数据段描述符
    movl $0x10,�x
    mov %dx,%ds
    mov %dx,%es
    mov %dx,%fs
    // 如果是缺页异常,cr2保存了引起缺页的线性地址
    movl %cr2,�x
    // 线性地址(有的话)和错误码入参
    pushl �x
    pushl �x
    // 1和eax与,结果放到ZF中
    testl $1,�x
    // zf=0则跳转,即0是写异常,1是缺页异常
    jne 1f
    call _do_no_page
    jmp 2f
1:    call _do_wp_page
// 出栈,返回中断,会重新异常指令
2:    addl $8,%esp
    pop %fs
    pop %es
    pop %ds
    popl �x
    popl �x
    popl �x
    iret

缺页或写保护异常的时候,系统会把错误码和线性地址告诉处理程序。具体的处理可以见内存管理分析那篇文件。

0 人点赞