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(); /* RWX */
note PT_NOTE FLAGS(); /* R__ */
} #ifdef CONFIG_32BIT
#ifdef CONFIG_CPU_LITTLE_ENDIAN
jiffies = jiffies_64;
#else
jiffies = jiffies_64 + ;
#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, , 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
: #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
:
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 $, init_thread_union
/* Set the SP after an empty pt_regs. */
PTR_LI sp, _THREAD_SIZE - - PT_SIZE
PTR_ADDU sp, $
back_to_back_c0_hazard
set_saved_sp sp, t0, t1
PTR_SUBU sp, * 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\n", boot_command_line);
parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
-, -, &unknown_bootoption); jump_label_init(); /*
* These use large bootmem allocations and must precede
* kmem_cache_init()
*/
setup_log_buf();
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\n"))
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\n");
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.\n",
page_to_pfn(virt_to_page((void *)initrd_start)),
min_low_pfn);
initrd_start = ;
}
#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\n", 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 = ; 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 = ; i < NR_IRQS; i++)
irq_set_noprobe(i); arch_init_irq(); #ifdef CONFIG_KGDB
if (!kgdb_early_setup)
kgdb_early_setup = ;
#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(, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
__raw_writel(, 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(), 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();
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 + ; 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 + ; i < irq_base + ; i++)
irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
handle_percpu_irq);
}
AR9331中Linux内核启动中与IRQ中断相关的文件的更多相关文章
- 如何调整Linux内核启动中的驱动初始化顺序-驱动加载优先级
Linux内核为不同驱动的加载顺序对应不同的优先级,定义了一些宏: include\linux\init.h #define pure_initcall(fn) __define_initcall(& ...
- TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现
题记:本系列文章的目的是抛开书本从Linux内核源代码的角度详细分析TCP/IP协议栈内核相关技术 轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.com linu ...
- 嵌入式C语言自我修养 02:Linux 内核驱动中的指定初始化
2.1 什么是指定初始化 在标准 C 中,当我们定义并初始化一个数组时,常用方法如下: ] = {,,,,,,,,}; 按照这种固定的顺序,我们可以依次给 a[0] 和 a[8] 赋值.因为没有对 a ...
- linux内核启动参数
Linux内核启动参数 Console Options 参数 说明 选项 内核配置/文件 console=Options 用于说明输出设备 tt ...
- Linux内核启动代码分析二之开发板相关驱动程序加载分析
Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c start_ke ...
- 【内核】linux内核启动流程详细分析
Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件,包括内核入口ENTRY(stext)到start_kernel间的初始化代码, 主要作用 ...
- 【内核】linux内核启动流程详细分析【转】
转自:http://www.cnblogs.com/lcw/p/3337937.html Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件 ...
- Linux内核启动过程概述
版权声明:本文原创,转载需声明作者ID和原文链接地址. Hi!大家好,我是CrazyCatJack.今天给大家带来的是Linux内核启动过程概述.希望能够帮助大家更好的理解Linux内核的启动,并且创 ...
- linux内核启动以及文件系统的加载过程
Linux 内核启动及文件系统加载过程 当u-boot 开始执行 bootcmd 命令,就进入 Linux 内核启动阶段.普通 Linux 内核的启动过程也可以分为两个阶段.本文以项目中使用的 lin ...
随机推荐
- 如何实现Web聊天
假设你web聊天不知道这件事情,那么最好的方法可能是:openfire+jsjac openfire它是java做开源xmppserver,jsjac它是javascript做开源的Web版本xmpp ...
- Android.mk中的经常使用语法
Android.mk编译文件是用来向Android NDK描写叙述你的C,C++源码文件的, 今天查了一些经常使用的的语法. 一 概述: 一个Android.mk文件用来向编译系统描写叙述你的源码. ...
- mahout源码KMeansDriver分析之五CIMapper初探
接着上篇,继续分析代码.下面就到了MR的循环了,这里MR应该算是比较好理解的,重点是退出循环的条件设置,即如何判断前后两次中心点误差小于给定阈值. 首先,while循环: while (iterati ...
- ABP项目中的使用AutoMapper
AutoMapper之ABP项目中的使用 最近在研究ABP项目,昨天写了Castle Windsor常用介绍以及其在ABP项目的应用介绍 欢迎各位拍砖,有关ABP的介绍请看阳光铭睿 博客 AutoMa ...
- linux 字符界面浏览器 w3m(转)
最近找到了几个linux终端下使用的浏览器,主要用来测试本机web服务器是否搭建成功.因为我们一般是用ssh客户端连接linux的,所以很需要一个字符界面的浏览器.找了几个显示都不理想,只有w3m用起 ...
- avalon组件
如何做一个avalon组件 在avalon1.5中改用更直观的自定义标签来声明组件,废掉ms-widget,引入更强大的生命周期管理,可以让组件任意套嵌. 组件是由JS,HTML,CSS构成 JS 以 ...
- NET ERP系统架构设计
解析大型.NET ERP系统架构设计 Framework+ Application 设计模式 我对大型系统的理解,从数量上面来讲,源代码超过百万行以上,系统有超过300个以上的功能,从质量上来讲系统应 ...
- 照片总结---选择适当的NoSQL
版权声明:本文博客原创文章,博客,未经同意,不得转载.
- 网络资源(5) - Android视频
2014_08_24 http://v.youku.com/v_show/id_XMjM5NjU2OTI0.html?f=5486194 Android开发视频教程1 http://v.youku.c ...
- Tyvj P1016 包装问题 (DP)
底 Background 太原诚成中学2模拟法庭竞赛 第三条道路 描写叙述 Description 有一个箱子容量为v(正整数.o≤v≤20000).同一时候有n个物品(o≤n≤30).每一个物品有一 ...