01.void __init x86_64_start_kernel(char * real_mode_data)
02.{
03. int i;
04.
05. /* 内核映像和模块区域映射的完整性检查 */
06. ...
07.
08. /* clear bss before set_intr_gate with early_idt_handler */
09. clear_bss();
10.
11. /* Make NULL pointers segfault */
12. zap_identity_mappings();
13.
14. /* KERNEL_IMAGE_START = 0xffffffff80000000UL KERNEL_IMAGE_SIZE = 512M
15. * PAGE_OFFSET = 0xffff880000000000UL PAGE_SHIFT = 12
16. */
17. max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
18.
19. for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) // segment.h中定义NUM_EXCEPTION_VECTORS = 32
20. set_intr_gate(i, early_idt_handler); // 往idt_table[i]数组中写入一个门描述符,处理函数是early_idt_handler
21.
22. /* struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table };
23. * lidt汇编指令利用idt_descr变量初始化idtr寄存器,NR_VECTORS = 256 */
24. load_idt((const struct desc_ptr *)&idt_descr);
25.
26. x86_64_start_reservations(real_mode_data);
27.}
28.
29.static void __init zap_identity_mappings(void)
30.{
31. /* (pgd_t *)(init_mm.pgd + pgd_index(addr)) = (pgd_t)0 */
32. pgd_t *pgd = pgd_offset_k(0UL);
33. pgd_clear(pgd);
34.
35. /* Read-Modify-Write to CR4 */
36. __flush_tlb_all();
37.}
38.
39.static void __init clear_bss(void)
40.{ memset(__bss_start, 0, (unsigned long) __bss_stop - (unsigned long) __bss_start); }
41.
42.static void __init copy_bootdata(char *real_mode_data)
43.{
44. char * command_line;
45.
46. memcpy(&boot_params, real_mode_data, sizeof boot_params);
47. if (boot_params.hdr.cmd_line_ptr) {
48. command_line = __va(boot_params.hdr.cmd_line_ptr);
49. memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
50. }
51.}
52.void __init x86_64_start_reservations(char *real_mode_data)
53.{
54. copy_bootdata(__va(real_mode_data));
55. memblock_init();
56. memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
57.
58.#ifdef CONFIG_BLK_DEV_INITRD
59. /* Reserve INITRD */
60. if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
61. /* Assume only end is not page aligned */
62. unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
63. unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
64. unsigned long ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size);
65. memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");
66. }
67.#endif
68.
69. reserve_ebda_region();
70. /* At this point everything still needed from the boot loader or BIOS or kernel text
71. * should be early reserved or marked not RAM in e820. All other memory is free game. */
72. start_kernel();
73.}
74.
75.
76.asmlinkage void __init start_kernel(void)
77.{
78. char * command_line;
79. extern const struct kernel_param __start___param[], __stop___param[];
80.
81. /* 当只有一个CPU的时候这个函数什么都不做,SMP时,返回在启动的时候的那个CPU号 */
82. smp_setup_processor_id();
83.
84. /* Need to run as early as possible, to initialize the lockdep hash: */
85. lockdep_init();
86. debug_objects_early_init();
87.
88. /* Set up the the initial canary ASAP: */
89. boot_init_stack_canary();
90. cgroup_init_early(); /* 系统启动时的cgroup初始化,初始化那些要求early init的子系统 */
91. local_irq_disable();
92. early_boot_irqs_disabled = true;
93. /* Interrupts are still disabled. Do necessary setups, then enable them */
94. tick_init();
95. boot_cpu_init();
96. /* 初始化页地址,使用链表将其链接起来 */
97. page_address_init();
98. printk(KERN_NOTICE "%s", linux_banner);
99.
100. /* 体系结构相关函数,由源码树顶层目录下的Makefile中的ARCH变量决定 */
101. setup_arch(&command_line);
102. mm_init_owner(&init_mm, &init_task); /* init_mm.owner = &init_task */
103. mm_init_cpumask(&init_mm);
104. setup_command_line(command_line);
105. setup_nr_cpu_ids(); /* nr_cpu_ids = NR_CPUS */
106. setup_per_cpu_areas();
107. smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
108.
109. build_all_zonelists(NULL);
110. page_alloc_init();
111.
112. printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
113.
114. /* 对内核选项的两次解析 */
115. parse_early_param();
116. parse_args("Booting kernel", static_command_line, __start___param,
117. __stop___param - __start___param, &unknown_bootoption);
118.
119. /* These use large bootmem allocations and must precede kmem_cache_init() */
120. setup_log_buf(0);
121.
122. /* 初始化hash表,便于从进程的PID获得对应的进程描述符指针 */
123. pidhash_init();
124.
125. /* 虚拟文件系统初始化,包括dcache\inode\files\mnt\bdev_cache\chrdev_init() */
126. vfs_caches_init_early();
127. sort_main_extable();
128.
129. /* trap_init函数完成对系统保留中断向量(异常、非屏蔽中断以及系统调用)的初始化
130. * init_IRQ函数则完成其余中断向量的初始化
131. */
132. trap_init();
133. mm_init();
134.
135. /* Set up the scheduler prior starting any interrupts (such as the
136. * timer interrupt). Full topology setup happens at smp_init()
137. * time - but meanwhile we still have a functioning scheduler.
138. */
139. sched_init();
140. /*
141. * Disable preemption - early bootup scheduling is extremely
142. * fragile until we cpu_idle() for the first time.
143. */
144. preempt_disable();
145. if (!irqs_disabled()) {
146. printk(KERN_WARNING "start_kernel(): bug: interrupts were "
147. "enabled *very* early, fixing it\n");
148. local_irq_disable();
149. }
150. idr_init_cache();
151.
152. /* NOTE: */
153. perf_event_init();
154.
155. rcu_init();
156. radix_tree_init();
157. /* init some links before init_ISA_irqs() */
158. early_irq_init();
159. init_IRQ();
160. prio_tree_init();
161.
162. /* 初始化定时器相关的数据结构*/
163. init_timers();
164.
165. /* 对高精度时钟进行初始化 */
166. hrtimers_init();
167.
168. softirq_init();
169. timekeeping_init();
170.
171. /* 初始化系统时钟源 */
172. time_init();
173.
174. /* 对内核的profile功能(一个内核性能调试工具)进行初始化 */
175. profile_init();
176. call_function_init();
177. if (!irqs_disabled())
178. printk(KERN_CRIT "start_kernel(): bug: interrupts were "
179. "enabled early\n");
180. early_boot_irqs_disabled = false;
181. local_irq_enable();
182.
183. /* Interrupts are enabled now so all GFP allocations are safe. */
184. gfp_allowed_mask = __GFP_BITS_MASK;
185.
186. /* slab初始化 */
187. kmem_cache_init_late();
188.
189. /*
190. * HACK ALERT! This is early. We're enabling the console before
191. * we've done PCI setups etc, and console_init() must be aware of
192. * this. But we do want output early, in case something goes wrong.
193. */
194. /* 控制台初始化以显示printk的内容,在此之前调用的printk只是把数据存到缓冲区里 */
195. console_init();
196. if (panic_later)
197. panic(panic_later, panic_param);
198.
199. /* 如果定义了CONFIG_LOCKDEP宏,则打印锁依赖信息,否则什么也不做 */
200. lockdep_info();
201.
202. /*
203. * Need to run this when irqs are enabled, because it wants
204. * to self-test [hard/soft]-irqs on/off lock inversion bugs
205. * too:
206. */
207. locking_selftest();
208.
209.#ifdef CONFIG_BLK_DEV_INITRD
210. if (initrd_start && !initrd_below_start_ok &&
211. page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
212. printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
213. "disabling it.\n",
214. page_to_pfn(virt_to_page((void *)initrd_start)),
215. min_low_pfn);
216. initrd_start = 0;
217. }
218.#endif
219. page_cgroup_init();
220. enable_debug_pagealloc();
221. debug_objects_mem_init();
222. kmemleak_init();
223. setup_per_cpu_pageset();
224. numa_policy_init();
225. if (late_time_init)
226. late_time_init();
227. sched_clock_init();
228.
229. /* 根据CPU在1s内执行极短循环的次数,得到BogoMIPS值 */
230. calibrate_delay();
231. pidmap_init();
232. anon_vma_init();
233.#ifdef CONFIG_X86
234. if (efi_enabled)
235. efi_enter_virtual_mode();
236.#endif
237. thread_info_cache_init();
238. cred_init();
239.
240. /* 根据物理内存大小计算允许创建进程数量 */
241. fork_init(totalram_pages);
242. proc_caches_init();
243. buffer_init();
244. key_init();
245. security_init();
246. dbg_late_init();
247. vfs_caches_init(totalram_pages);
248. signals_init();
249. /* rootfs populating might need page-writeback */
250. page_writeback_init();
251.#ifdef CONFIG_PROC_FS
252. proc_root_init();
253.#endif
254. cgroup_init(); /* 注册cgroup文件系统并创建/proc/cgroup文件,初始化所有在cgroup_init_early中没有初始化的子系统 */
255. cpuset_init();
256. taskstats_init_early();
257. delayacct_init();
258.
259. /* 测试CPU的各种缺陷,记录检测到的缺陷,以便于内核的其他部分可以使用它们的工作
260. * check_bugs=>identify_boot_cpu=>identify_cpu会做很多工作,包括select_idle_routine以及intel_init_thermal
261. */
262. check_bugs();
263.
264. acpi_early_init(); /* before LAPIC and SMP init */
265. sfi_init_late();
266.
267. ftrace_init();
268.
269. /* Do the rest non-__init'ed, we're now alive */
270. /* 创建init进程 */
271. rest_init();
272.}