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
    }
  • 相关阅读:
    1093 Count PAT's(25 分)
    1089 Insert or Merge(25 分)
    1088 Rational Arithmetic(20 分)
    1081 Rational Sum(20 分)
    1069 The Black Hole of Numbers(20 分)
    1059 Prime Factors(25 分)
    1050 String Subtraction (20)
    根据生日计算员工年龄
    动态获取当前日期和时间
    对计数结果进行4舍5入
  • 原文地址:https://www.cnblogs.com/pricks/p/7715238.html
Copyright © 2011-2022 走看看