zoukankan      html  css  js  c++  java
  • init_ir_技术实现篇

    1. 中断的初始化

    中断向量号是8位的,那么它一共有256项(0-255),所以中断描述符表最多只有256项,中断向量表也是256项。

    对于不同的中断,在中断初始化和中断处理过程中,其处理方式是不一样的,尤其是不同类型的中断,其处理响应机制差别较大,后面会详述。这里先描述中断的初始化过程。

    从中断触发的源角度,可以将中断分为内部中断(0~31号中断向量号)和外部中断(32~255号中断向量号),linux初始化过程中,会先初始化内部中断,再初始化外部中断。这两种中断的初始化区别如下:

    1. 内部中断(0~31号、0x80作为中断号)
    只要初始化:
        1) 相关的中断向量表
    2. 外部中断(0~255中的除了0~31号、0x80的其他中断号)
    需要初始化:
        1) 相关的中断向量表
        2) 以及中断控制器(控制器负责优先级排队、屏蔽等工作)

    0x1: 内部中断初始化

    内部中断的初始化需要对0~31号和0x80号系统保留中断向量的初始化,这部分草走在trap_init()中完成

    linux-3.15.5archx86kernel raps

    复制代码
    void __init trap_init(void)
    {
        int i;
    
    #ifdef CONFIG_EISA
        void __iomem *p = early_ioremap(0x0FFFD9, 4);
    
        if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
            EISA_bus = 1;
        early_iounmap(p, 4);
    #endif
    /*
    trap_init()主要是调用set_xxx_gate(中断向量, 中断处理函数)
    set_xxx_gate()就是按照中断门的格式填写中断向量表的
    
    Intel x86支持4种"门描述符":
    1) 调用门(call gate) 
    2) 陷阱门(trap gate)   
    3) 中断门(iinterrupt gate)   
    4) 任务门(task gate)
    */
        set_intr_gate(X86_TRAP_DE, divide_error);
        set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
        /* int4 can be called from all */
        set_system_intr_gate(X86_TRAP_OF, &overflow);
        set_intr_gate(X86_TRAP_BR, bounds);
        set_intr_gate(X86_TRAP_UD, invalid_op);
        set_intr_gate(X86_TRAP_NM, device_not_available);
    #ifdef CONFIG_X86_32
        set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);
    #else
        set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);
    #endif
        set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun);
        set_intr_gate(X86_TRAP_TS, invalid_TSS);
        set_intr_gate(X86_TRAP_NP, segment_not_present);
        set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK);
        set_intr_gate(X86_TRAP_GP, general_protection);
        set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug);
        set_intr_gate(X86_TRAP_MF, coprocessor_error);
        set_intr_gate(X86_TRAP_AC, alignment_check);
    #ifdef CONFIG_X86_MCE
        set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
    #endif
        set_intr_gate(X86_TRAP_XF, simd_coprocessor_error);
    
        /* Reserve all the builtin and the syscall vector: */
        for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
            set_bit(i, used_vectors);
    
    #ifdef CONFIG_IA32_EMULATION
        set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
        set_bit(IA32_SYSCALL_VECTOR, used_vectors);
    #endif
    //设置系统调用中断
    #ifdef CONFIG_X86_32
        set_system_trap_gate(SYSCALL_VECTOR, &system_call);
        set_bit(SYSCALL_VECTOR, used_vectors);
    #endif
    
        /*
         * Set the IDT descriptor to a fixed read-only location, so that the
         * "sidt" instruction will not leak the location of the kernel, and
         * to defend the IDT against arbitrary memory write vulnerabilities.
         * It will be reloaded in cpu_init() */
        __set_fixmap(FIX_RO_IDT, __pa_symbol(idt_table), PAGE_KERNEL_RO);
        idt_descr.address = fix_to_virt(FIX_RO_IDT);
    
        /*
         * Should be a barrier for any external CPU state:
         */
        cpu_init();
    
        x86_init.irqs.trap_init();
    
    #ifdef CONFIG_X86_64
        memcpy(&debug_idt_table, &idt_table, IDT_ENTRIES * 16);
        set_nmi_gate(X86_TRAP_DB, &debug);
        set_nmi_gate(X86_TRAP_BP, &int3);
    #endif
    }
    复制代码

    0x2: 外部中断初始化

    外部中断的初始化需要:

    1. 对除了0~31、0x80中断号之外的其它中断向量
    2. 中断控制器的初始化(相比内部中断初始化多了这一步)
    这两步操作都在在init_IRQ()中完成

    linux-3.15.5archx86kerneli8259.c

    复制代码
    void __init init_IRQ(void)
    {
        int i;
    
        /*
         * We probably need a better place for this, but it works for
         * now ...
         */
        x86_add_irq_domains();
    
        /*
         * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
         * If these IRQ's are handled by legacy interrupt-controllers like PIC,
         * then this configuration will likely be static after the boot. If
         * these IRQ's are handled by more mordern controllers like IO-APIC,
         * then this vector space can be freed and re-used dynamically as the
         * irq's migrate etc.
         */
        for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) //对于单CPU结构,
            per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;
    
        //x86_init.irqs.intr_init()等价于调用:native_init_IRQ()
        x86_init.irqs.intr_init();
    }
    
    
    void __init native_init_IRQ(void)
    {
        int i;
    
        /* Execute any quirks before the call gates are initialised: */
        x86_init.irqs.pre_vector_init(); //调用 init_ISA_irqs 
    
        apic_intr_init();  
    
        /*
         * Cover the whole vector space, no vector can escape
         * us. (some of these will be overridden and become
         * 'special' SMP interrupts)
         */
         /*
         interrupt数组,它保存的是每个中断服务程序的入口地址,它的定义是在linux-3.15.5archx86kernelentry_32.S中
         */
        for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) 
        { 
        //设置32~255号中断
            /* IA32_SYSCALL_VECTOR could be used in trap_init already. */
            if (!test_bit(i, used_vectors)) 
        {
            //要除去0x80中断
            set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
        } 
        }
    
    
        if (!acpi_ioapic && !of_ioapic)
            setup_irq(2, &irq2);
    
    #ifdef CONFIG_X86_32
        /*
         * External FPU? Set up irq13 if so, for
         * original braindamaged IBM FERR coupling.
         */
        if (boot_cpu_data.hard_math && !cpu_has_fpu)
            setup_irq(FPU_IRQ, &fpu_irq);
    
        irq_ctx_init(smp_processor_id());
    #endif
    }
  • 相关阅读:
    强化学习
    详解a标签中href=""的几种用法 锚点
    使用Django自带的登录访问限制login_required
    ValueError: invalid literal for int() with base 10: ''
    Django 中创建Model时报以下错误: TypeError: init() missing 1 required positional argument: ‘on_delete’
    bootstrp实现同一界面多个模态框
    第十二章 Django框架开发
    Python format 格式化函数
    Python3.x在django中如何设置Content-Disposition,才能让浏览器正确保存中文命名的文件?
    python中的*和**参数传递机制
  • 原文地址:https://www.cnblogs.com/pricks/p/7715238.html
Copyright © 2011-2022 走看看