首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >linux0.11中断处理源码初探

linux0.11中断处理源码初探

作者头像
theanarkh
发布2019-04-23 18:26:01
1.7K0
发布2019-04-23 18:26:01
举报
文章被收录于专栏:原创分享原创分享

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

// 加载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。

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);
}
#define _set_gate(gate_addr,type,dpl,addr) \
// 把dx即处理函数地址的低16位赋值给ax,不影响eax的高16位
__asm__ ("movw %%dx,%%ax\n\t" \
    /*
        设置idt描述符的第三个字节的内容,左移位数是字段对应的位置偏移,
        相加后赋值给dx,共16位,edx的高16位保存了处理函数的高16位地址
    */
    "movw %0,%%dx\n\t" \
    // 把eax即0x000080000 + 处理函数的地址赋值给idt描述符的前两个字节
    "movl %%eax,%1\n\t" \
    // 把edx的内容写入idt描述符的第5-8个字节
    "movl %%edx,%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描述符格式是,这个版本貌似还没有任务门。

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

.globl _page_fault

_page_fault:
    // 交换两个寄存器的值,esp指向的位置保存了错误码
    xchgl %eax,(%esp)
    // 压栈寄存器
    pushl %ecx
    pushl %edx
    push %ds
    push %es
    push %fs
    // 内核数据段描述符
    movl $0x10,%edx
    mov %dx,%ds
    mov %dx,%es
    mov %dx,%fs
    // 如果是缺页异常,cr2保存了引起缺页的线性地址
    movl %cr2,%edx
    // 线性地址(有的话)和错误码入参
    pushl %edx
    pushl %eax
    // 1和eax与,结果放到ZF中
    testl $1,%eax
    // 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 %edx
    popl %ecx
    popl %eax
    iret

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档