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(); // 返回cpu号,单核cpu返回0
debug_objects_early_init(); // 对调试对象进行早期的初始化
cgroup_init_early(); // 对Control Groups进行早期的初始化
local_irq_disable(); // 关闭当前cpu的中断
early_boot_irqs_disabled = true;
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
boot_cpu_init(); // 设置当前cpu位激活状态
page_address_init(); // 初始化高端内存的,arm没有用到
pr_notice("%s", linux_banner);
setup_arch(&command_line); // 内核架构相关初始化函数
/*
* Set up the the initial canary ASAP:
*/
boot_init_stack_canary(); //
初始化栈canary值,canary值用于防止栈溢出攻击的堆栈的保护字
mm_init_owner(&init_mm, &init_task); // mm.owner =
&init_task
mm_init_cpumask(&init_mm);
setup_command_line(command_line); // 对cmdline进行备份
setup_nr_cpu_ids(); //
nr_cpu_ids
setup_per_cpu_areas(); //
每个cpu的per-cpu变量副本分配空间
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
build_all_zonelists(NULL, NULL); //
建立系统内存页区(zone)链表
page_alloc_init(); // 内存页初始化
pr_notice("Kernel command line: %s\n", boot_command_line);
parse_early_param(); // 解析
需要'早期'处理的启动参数
用?
setup_arch已经调用了一次
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
-1, -1, &unknown_bootoption); // 解析cmdline中的启动参数
jump_label_init(); // 处理静态定义在跳转标号
/*
* These use large bootmem allocations and must precede
* kmem_cache_init()
*/
setup_log_buf(0); // 使用memblock_alloc分配一个启动时log缓冲区
pidhash_init(); // 初始化pid散列表
vfs_caches_init_early(); // 初始化
dentry和inode的hashtable
sort_main_extable(); // 对内核异常向量表进行排序
trap_init(); // 对内核陷阱异常进行初始化,arm没有用到
mm_init(); //
初始化内核内存分配器,过度到伙伴系统,启动slab机制,初始化非连续内存区
/*
* 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(); // 创建idr(整数id管理机制)高速缓存
perf_event_init(); // 初始化性能诊断工具
rcu_init(); // 初始化rcu机制(读-写-拷贝)
tick_nohz_init(); // 初始化动态时钟框架
radix_tree_init(); // 初始化内核基数树
/* init some links before init_ISA_irqs() */
early_irq_init(); // arm64没有用到
init_IRQ(); // 初始化中断
tick_init(); // 初始化时钟滴答控制器
init_timers(); // 初始化内核定时器
hrtimers_init(); // 初始化高精度时钟
softirq_init(); // 初始化软中断
timekeeping_init(); //
初始化了大量的时钟相关全局变量
time_init(); // 时钟初始化
profile_init(); //
对内核的一个性能测试工具profile进行初始化
call_function_init(); //
smp下跨cpu的函数传递初始化
WARN(!irqs_disabled(), "Interrupts were enabled early\n");
early_boot_irqs_disabled = false;
local_irq_enable(); // 使能当前cpu中断
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 = 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();
}
int __init cgroup_init_early(void)
{
int i;
atomic_set(&init_css_set.refcount, 1);
INIT_LIST_HEAD(&init_css_set.cg_links);
INIT_LIST_HEAD(&init_css_set.tasks);
INIT_HLIST_NODE(&init_css_set.hlist);
css_set_count = 1;
init_cgroup_root(&rootnode);
root_count = 1;
init_task.cgroups = &init_css_set;
init_css_set_link.cg = &init_css_set;
init_css_set_link.cgrp = dummytop;
list_add(&init_css_set_link.cgrp_link_list,
&rootnode.top_cgroup.css_sets);
list_add(&init_css_set_link.cg_link_list,
&init_css_set.cg_links);
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
struct cgroup_subsys *ss = subsys[i];
/* at bootup time, we don't worry about modular subsystems */
if (!ss || ss->module)
continue;
BUG_ON(!ss->name);
BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN);
BUG_ON(!ss->css_alloc);
BUG_ON(!ss->css_free);
if (ss->subsys_id != i) {
printk(KERN_ERR "cgroup: Subsys %s id == %d\n",
ss->name, ss->subsys_id);
BUG();
}
if (ss->early_init)
cgroup_init_subsys(ss);
}
return 0;
}
#define local_irq_disable() \
do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
void trace_hardirqs_off(void)
{
trace_hardirqs_off_caller(CALLER_ADDR0);
}
void trace_hardirqs_off_caller(unsigned long ip)
{
struct task_struct *curr = current;
time_hardirqs_off(CALLER_ADDR0, ip);
if (unlikely(!debug_locks || current->lockdep_recursion))
return;
/*
* So we're supposed to get called after you mask local IRQs, but for
* some reason the hardware doesn't quite think you did a proper job.
*/
if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
return;
if (curr->hardirqs_enabled) {
/*
* We have done an ON -> OFF transition:
*/
curr->hardirqs_enabled = 0;
curr->hardirq_disable_ip = ip;
curr->hardirq_disable_event = ++curr->irq_events;
debug_atomic_inc(hardirqs_off_events);
} else
debug_atomic_inc(redundant_hardirqs_off);
}