zoukankan      html  css  js  c++  java
  • AR9331中Linux内核启动中与IRQ中断相关的文件

    先列出框架,具体后继再来分析。

    首先是lds文件,该文件设置了各个section在FLASH或RAM中的先后顺序。

    位于~/openwrt1407/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/arch/mips/kernel/vmlinux.lds

    另外一个名字相似的,~/openwrt1407/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/arch/mips/kernel/vmlinux.lds.S

    ...
    #undef
    mips #define mips mips OUTPUT_ARCH(mips) ENTRY(kernel_entry) PHDRS { text PT_LOAD FLAGS(7); /* RWX */ note PT_NOTE FLAGS(4); /* R__ */ } #ifdef CONFIG_32BIT #ifdef CONFIG_CPU_LITTLE_ENDIAN jiffies = jiffies_64; #else jiffies = jiffies_64 + 4; #endif #else jiffies = jiffies_64; #endif SECTIONS {
    ...

    表明入口地址为kernel_entry,该符号在:~/openwrt1407/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/arch/mips/kernel/head.S中定义

    ...
    NESTED(kernel_entry, 16, sp) # kernel entry point kernel_entry_setup # cpu specific setup setup_c0_status_pri /* We might not get launched at the address the kernel is linked to, so we jump there. */ PTR_LA t0, 0f jr t0 0: #ifdef CONFIG_MIPS_MT_SMTC /* * In SMTC kernel, "CLI" is thread-specific, in TCStatus. * We still need to enable interrupts globally in Status, * and clear EXL/ERL. * * TCContext is used to track interrupt levels under * service in SMTC kernel. Clear for boot TC before * allowing any interrupts. */ mtc0 zero, CP0_TCCONTEXT mfc0 t0, CP0_STATUS ori t0, t0, 0xff1f xori t0, t0, 0x001e mtc0 t0, CP0_STATUS #endif /* CONFIG_MIPS_MT_SMTC */ PTR_LA t0, __bss_start # clear .bss LONG_S zero, (t0) PTR_LA t1, __bss_stop - LONGSIZE 1: PTR_ADDIU t0, LONGSIZE LONG_S zero, (t0) bne t0, t1, 1b LONG_S a0, fw_arg0 # firmware arguments LONG_S a1, fw_arg1 LONG_S a2, fw_arg2 LONG_S a3, fw_arg3 MTC0 zero, CP0_CONTEXT # clear context register PTR_LA $28, init_thread_union /* Set the SP after an empty pt_regs. */ PTR_LI sp, _THREAD_SIZE - 32 - PT_SIZE PTR_ADDU sp, $28 back_to_back_c0_hazard set_saved_sp sp, t0, t1 PTR_SUBU sp, 4 * SZREG # init stack pointer j start_kernel END(kernel_entry)
    ...

    最终跳到kernel_entry中,该函数在~/openwrt1407/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/init/main.c中定义:

    asmlinkage void __init start_kernel(void)
    {
        char * command_line;
        extern const struct kernel_param __start___param[], __stop___param[];
    
        /*
         * Need to run as early as possible, to initialize the
         * lockdep hash:
         */
        lockdep_init();
        smp_setup_processor_id();
        debug_objects_early_init();
    
        /*
         * Set up the the initial canary ASAP:
         */
        boot_init_stack_canary();
    
        cgroup_init_early();
    
        local_irq_disable();
        early_boot_irqs_disabled = true;
    
    /*
     * Interrupts are still disabled. Do necessary setups, then
     * enable them
     */
        boot_cpu_init();
        page_address_init();
        pr_notice("%s", linux_banner);
        setup_arch(&command_line);
        mm_init_owner(&init_mm, &init_task);
        mm_init_cpumask(&init_mm);
        setup_command_line(command_line);
        setup_nr_cpu_ids();
        setup_per_cpu_areas();
        smp_prepare_boot_cpu();    /* arch-specific boot-cpu hooks */
    
        build_all_zonelists(NULL, NULL);
        page_alloc_init();
    
        pr_notice("Kernel command line: %s
    ", boot_command_line);
        parse_early_param();
        parse_args("Booting kernel", static_command_line, __start___param,
               __stop___param - __start___param,
               -1, -1, &unknown_bootoption);
    
        jump_label_init();
    
        /*
         * These use large bootmem allocations and must precede
         * kmem_cache_init()
         */
        setup_log_buf(0);
        pidhash_init();
        vfs_caches_init_early();
        sort_main_extable();
        trap_init();
        mm_init();
    
        /*
         * Set up the scheduler prior starting any interrupts (such as the
         * timer interrupt). Full topology setup happens at smp_init()
         * time - but meanwhile we still have a functioning scheduler.
         */
        sched_init();
        /*
         * Disable preemption - early bootup scheduling is extremely
         * fragile until we cpu_idle() for the first time.
         */
        preempt_disable();
        if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it
    "))
            local_irq_disable();
        idr_init_cache();
        perf_event_init();
        rcu_init();
        tick_nohz_init();
        radix_tree_init();
        /* init some links before init_ISA_irqs() */
        early_irq_init();
        init_IRQ();
        tick_init();
        init_timers();
        hrtimers_init();
        softirq_init();
        timekeeping_init();
        time_init();
        profile_init();
        call_function_init();
        WARN(!irqs_disabled(), "Interrupts were enabled early
    ");
        early_boot_irqs_disabled = false;
        local_irq_enable();
    
        kmem_cache_init_late();
    
        /*
         * HACK ALERT! This is early. We're enabling the console before
         * we've done PCI setups etc, and console_init() must be aware of
         * this. But we do want output early, in case something goes wrong.
         */
        console_init();
        if (panic_later)
            panic(panic_later, panic_param);
    
        lockdep_info();
    
        /*
         * Need to run this when irqs are enabled, because it wants
         * to self-test [hard/soft]-irqs on/off lock inversion bugs
         * too:
         */
        locking_selftest();
    
    #ifdef CONFIG_BLK_DEV_INITRD
        if (initrd_start && !initrd_below_start_ok &&
            page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
            pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.
    ",
                page_to_pfn(virt_to_page((void *)initrd_start)),
                min_low_pfn);
            initrd_start = 0;
        }
    #endif
        page_cgroup_init();
        debug_objects_mem_init();
        kmemleak_init();
        setup_per_cpu_pageset();
        numa_policy_init();
        if (late_time_init)
            late_time_init();
        sched_clock_init();
        calibrate_delay();
        pidmap_init();
        anon_vma_init();
    #ifdef CONFIG_X86
        if (efi_enabled(EFI_RUNTIME_SERVICES))
            efi_enter_virtual_mode();
    #endif
        thread_info_cache_init();
        cred_init();
        fork_init(totalram_pages);
        proc_caches_init();
        buffer_init();
        key_init();
        security_init();
        dbg_late_init();
        vfs_caches_init(totalram_pages);
        signals_init();
        /* rootfs populating might need page-writeback */
        page_writeback_init();
    #ifdef CONFIG_PROC_FS
        proc_root_init();
    #endif
        cgroup_init();
        cpuset_init();
        taskstats_init_early();
        delayacct_init();
    
        check_bugs();
    
        acpi_early_init(); /* before LAPIC and SMP init */
        sfi_init_late();
    
        if (efi_enabled(EFI_RUNTIME_SERVICES)) {
            efi_late_init();
            efi_free_boot_services();
        }
    
        ftrace_init();
    
        /* Do the rest non-__init'ed, we're now alive */
        rest_init();
    }

    上面调用了两个IRQ初始化函数early_irq_init和init_IRQ,分别在~/openwrt1407/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/kernel/irq/irqdesc.c和~/openwrt1407/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/arch/mips/kernel/irq.c中。

    early_irq_init函数

    int __init early_irq_init(void)
    {
        int i, initcnt, node = first_online_node;
        struct irq_desc *desc;
    
        init_irq_default_affinity();
    
        /* Let arch update nr_irqs and return the nr of preallocated irqs */
        initcnt = arch_probe_nr_irqs();
        printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d %d
    ", NR_IRQS, nr_irqs, initcnt);
    
        if (WARN_ON(nr_irqs > IRQ_BITMAP_BITS))
            nr_irqs = IRQ_BITMAP_BITS;
    
        if (WARN_ON(initcnt > IRQ_BITMAP_BITS))
            initcnt = IRQ_BITMAP_BITS;
    
        if (initcnt > nr_irqs)
            nr_irqs = initcnt;
    
        for (i = 0; i < initcnt; i++) {
            desc = alloc_desc(i, node, NULL);
            set_bit(i, allocated_irqs);
            irq_insert_desc(i, desc);
        }
        return arch_early_irq_init();
    }

    init_IRQ函数

    void __init init_IRQ(void)
    {
        int i;
    
    #ifdef CONFIG_KGDB
        if (kgdb_early_setup)
            return;
    #endif
    
        for (i = 0; i < NR_IRQS; i++)
            irq_set_noprobe(i);
    
        arch_init_irq();
    
    #ifdef CONFIG_KGDB
        if (!kgdb_early_setup)
            kgdb_early_setup = 1;
    #endif
    }

    上面调用的arch_init_irq函数位于~/openwrt1407/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/arch/mips/ath79/irq.c中

    arch_init_irq函数

    static void __init ath79_misc_irq_init(void)
    {
        void __iomem *base = ath79_reset_base;
        int i;
    
        __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
        __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
    
        if (soc_is_ar71xx() || soc_is_ar913x())
            ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
        else if (soc_is_ar724x() ||
             soc_is_ar933x() ||
             soc_is_ar934x() ||
             soc_is_qca953x() ||
             soc_is_qca955x())
            ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
        else
            BUG();
    
        for (i = ATH79_MISC_IRQ_BASE;
             i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
            irq_set_chip_and_handler(i, &ath79_misc_irq_chip,
                         handle_level_irq);
        }
    
        irq_set_chained_handler(ATH79_CPU_IRQ(6), ath79_misc_irq_handler);
    }
    
    ...
    void __init arch_init_irq(void) { if (soc_is_ar71xx()) { ath79_ip2_handler = ar71xx_ip2_handler; ath79_ip3_handler = ar71xx_ip3_handler; } else if (soc_is_ar724x()) { ath79_ip2_handler = ar724x_ip2_handler; ath79_ip3_handler = ar724x_ip3_handler; } else if (soc_is_ar913x()) { ath79_ip2_handler = ar913x_ip2_handler; ath79_ip3_handler = ar913x_ip3_handler; } else if (soc_is_ar933x()) { ath79_ip2_handler = ar933x_ip2_handler; ath79_ip3_handler = ar933x_ip3_handler; } else if (soc_is_ar934x()) { ath79_ip2_handler = ath79_default_ip2_handler; ath79_ip3_handler = ar934x_ip3_handler; } else if (soc_is_qca953x()) { ath79_ip2_handler = ath79_default_ip2_handler; ath79_ip3_handler = ath79_default_ip3_handler; } else if (soc_is_qca955x()) { ath79_ip2_handler = ath79_default_ip2_handler; ath79_ip3_handler = ath79_default_ip3_handler; } else { BUG(); } cp0_perfcount_irq = ATH79_MISC_IRQ(5); mips_cpu_irq_init(); ath79_misc_irq_init(); if (soc_is_ar934x()) ar934x_ip2_irq_init(); else if (soc_is_qca955x()) qca955x_irq_init(); }

    mips_cpu_irq_init函数位于~/openwrt1407/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/arch/mips/kernel/irq_cpu.c中,ath79_misc_irq_init同在irq.c文件中。

    void __init mips_cpu_irq_init(void)
    {
        int irq_base = MIPS_CPU_IRQ_BASE;
        int i;
    
        /* Mask interrupts. */
        clear_c0_status(ST0_IM);
        clear_c0_cause(CAUSEF_IP);
    
        /* Software interrupts are used for MT/CMT IPI */
        for (i = irq_base; i < irq_base + 2; i++)
            irq_set_chip_and_handler(i, cpu_has_mipsmt ?
                         &mips_mt_cpu_irq_controller :
                         &mips_cpu_irq_controller,
                         handle_percpu_irq);
    
        for (i = irq_base + 2; i < irq_base + 8; i++)
            irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
                         handle_percpu_irq);
    }
  • 相关阅读:
    C/C++ _wcsupr_s 函数 – unicode 字符串小写转大写 C语言零基础入门教程
    C/C++ atof函数 C语言零基础入门教程
    C/C++ ultoa函数 C语言零基础入门教程
    C/C++ _strlwr_s 函数 – 字符串大写转小写 C语言零基础入门教程
    C/C++ ceil 函数 C语言零基础入门教程
    C/C++ atol函数 C语言零基础入门教程
    idea在商店无法搜索到插件
    Go 关于 protoc 工具的小疑惑
    Golang 关于 proto 文件的一点小思考
    Go 如何编写 ProtoBuf 插件(二)?
  • 原文地址:https://www.cnblogs.com/tfanalysis/p/4210061.html
Copyright © 2011-2022 走看看