中断的一些硬件机制不做过多的描述,只介绍一些和linux实现比较贴近的机制,便于理解代码。

1.1 关于intel和linux几种门的简介

intel提供了4种门:系统门,中断门,陷阱门,调用门。

调用门:不同特权级之间实现受控的程序控制转移,它是放在GDT或LDT之中。使用调用门需要为CALL或JMP指令的操作数提供一个远指针,该指针中的段选择符用于指定调用门,指向的是GDT或LDT中的一个段,在低特权级代码切换到高特权级代码是会发生代码段的转移。(linux没有使用这种门,感觉这是intel用来给操作系统实现系统调用的机制,但是linux没有使用,linux使用陷阱门来实现系统调用,原因是软件实现更加灵活,有优化空间,而且可以用来检查一些硬件无法检查的段寄存器数据的正确性)

任务门:用来处理中断和异常。可以放在GDT、LDT、IDT中,任务门描述符中TSS选择符字段指向GDT的一个TSS段描述符,在跳转时必须跳转到TSS选择符指向的段,(linux在GDT中只定义了一个TSS,即每个CPU一个TSS),这也是linux中唯一使用调用门来处理的异常,其他异常都使用陷阱门来处理。

中断门:处理中断。放在IDT中,清空IF标志,屏蔽将到来的中断。linux在intel的基础上将其中断门分为如下两类:

  • 中断门:用户态进程不能访问,所有的中断处理程序都通过中断门激活,限制在内核态
  • 系统中断门:能被用户态程序访问,与向量3相关的异常处理程序由系统中断门来激活,在用户态可以使用int3指令,该指令表示断点,用来调试。

陷阱门:与中断门类似,只是不修改IF标志位。

  • 陷阱门:用户态进程不能访问,大部分的linux异常都由陷阱门激活。
  • 系统门:能被用户态程序访问,用户态程序可以发布into、bound、int 0x80指令,其中int 0x80是系统中断

门能否被用户态访问是有一套优先级判断机制,这里不做描述了。

 1.2 几种异常的初始化

arch\i386\kernel\trap.s中的trap_init函数

void __init trap_init(void)
{
#ifdef CONFIG_EISA
    void __iomem *p = ioremap(0x0FFFD9, 4);
    if (readl(p) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) {
        EISA_bus = 1;
    }
    iounmap(p);
#endif

#ifdef CONFIG_X86_LOCAL_APIC
    init_apic_mappings();
#endif

    set_trap_gate(0,&divide_error);
    set_intr_gate(1,&debug);
    set_intr_gate(2,&nmi);
    set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
    set_system_gate(4,&overflow);
    set_trap_gate(5,&bounds);
    set_trap_gate(6,&invalid_op);
    set_trap_gate(7,&device_not_available);
    set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
    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_intr_gate(14,&page_fault);
    set_trap_gate(15,&spurious_interrupt_bug);
    set_trap_gate(16,&coprocessor_error);
    set_trap_gate(17,&alignment_check);
#ifdef CONFIG_X86_MCE
    set_trap_gate(18,&machine_check);
#endif
    set_trap_gate(19,&simd_coprocessor_error);

    if (cpu_has_fxsr) {
        /*
         * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
         * Generates a compile-time "error: zero width for bit-field" if
         * the alignment is wrong.
         */
        struct fxsrAlignAssert {
            int _:!(offsetof(struct task_struct,
                    thread.i387.fxsave) & 15);
        };

        printk(KERN_INFO "Enabling fast FPU save and restore... ");
        set_in_cr4(X86_CR4_OSFXSR);
        printk("done.\n");
    }
    if (cpu_has_xmm) {
        printk(KERN_INFO "Enabling unmasked SIMD FPU exception "
                "support... ");
        set_in_cr4(X86_CR4_OSXMMEXCPT);
        printk("done.\n");
    }

    set_system_gate(SYSCALL_VECTOR,&system_call);

    /*
     * Should be a barrier for any external CPU state.
     */
    cpu_init();

    trap_init_hook();
}
trap_init

相关文章:

  • 2022-01-03
  • 2021-03-05
  • 2018-04-22
  • 2021-07-06
  • 2021-08-29
  • 2022-12-23
  • 2022-12-23
  • 2021-05-16
猜你喜欢
  • 2018-03-26
  • 2021-05-19
  • 2022-02-01
  • 2021-08-14
  • 2021-11-23
  • 2022-03-05
  • 2021-08-01
相关资源
相似解决方案