start_kernel 早期初始化机制与实现详解

start_kernel 早期初始化机制与实现详解

源码路径rk3588/kernel-6.1/init/main.cstart_kernel
内核版本:Linux 6.1(RK3588 / ARM64)
文档目录linuxDoc/init/


目录


一、原理

1.1 角色

start_kernel()架构无关 的内核主初始化函数:在 boot CPU、中断关闭 的早期环境中,依次建立内存管理、调度器、中断与时间子系统的基础,再打开中断并完成进程/VFS/cgroup 等“晚期”初始化,最后交给 rest_init() 进入多任务世界。

1.2 与 arch 的分工

层次 典型工作
arch/arm64 页表、异常向量、setup_arch、DT、SMP 表
start_kernel 通用子系统顺序、命令行解析、调用 mm_init

二、实现方式

2.1 入口与早期安全

1
2
3
4
5
6
7
8
9
10
11
12
asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
{
// ...
local_irq_disable();
early_boot_irqs_disabled = true;
boot_cpu_init();
page_address_init();
setup_arch(&command_line);
setup_boot_config();
setup_command_line(command_line);
build_all_zonelists(NULL);
page_alloc_init();
  • set_task_stack_end_magic(&init_task):栈溢出检测魔数
  • cgroup_init_early():最早 cgroup 钩子
  • setup_boot_config():可选 bootconfig blob

2.2 命令行与早期参数

  1. setup_command_line 合并 DT / 内置 / 用户 cmdline → saved_command_line
  2. RK:分段 pr_cont 打印(见第四节)
  3. parse_early_param()__setupearly 标记的选项
  4. parse_args:内核模块参数表 __param-- 之后交给 init 的 argv

2.3 内存与陷阱

调用 作用
mm_init() slab、vmalloc、buddy 相关晚期 mm 初始化
trap_init() 陷阱/异常表(架构相关实现)
sort_main_extable() 内核异常表排序

须在 kmem_cache_init() 之前完成大块 bootmem 分配(如 setup_log_buf)。

2.4 调度、RCU、中断、时间

1
2
3
4
5
6
7
8
9
10
11
sched_init();
// ...
rcu_init();
early_irq_init();
init_IRQ();
tick_init();
init_timers();
hrtimers_init();
softirq_init();
timekeeping_init();
time_init();

注意:完整 CPU 拓扑与 SMP 负载均衡在 kernel_init_freeablesmp_init() / sched_init_smp(),此处仅为 单 CPU 可调度 的最小环境。

2.5 开中断后的“晚期”初始化

1
2
3
4
5
6
7
8
9
10
11
local_irq_enable();
kmem_cache_init_late();
console_init();
lockdep_init();
// ...
cred_init();
fork_init();
vfs_caches_init();
cgroup_init();
// ...
arch_call_rest_init();
  • calibrate_delay():BogoMIPS(见 06
  • arch_call_rest_init():通常直接调用 rest_init(),且 不再返回

三、关键接口与顺序

setup_arch + memparse paramsmm_init sched_initIRQ timerslocal_irq_enableconsole vfs cgrouparch_call_rest_init
全局状态 设置时机
system_state rest_init 中设为 SYSTEM_SCHEDULING
gfp_allowed_mask kernel_init_freeable 开头放开

四、RK3588 平台说明

CONFIG_ARCH_ROCKCHIP 时,首次 pr_notice 打印 cmdline 后,用循环 pr_cont 输出剩余字符,避免 单条日志长度限制 导致启动参数截断(排查 root=console= 时很重要)。


五、调试与观测

手段 说明
earlyprintk / console= console_init 前后观察
initcall_debug 对 initcall 更有效,但 start_kernel 末尾可开 trace
ignore_loglevel 强制打印级别
启动 stall 对比 printk 时间戳,定位卡在 calibrate_delayconsole_init

附录:源码索引

符号 文件 约行
start_kernel init/main.c 939
parse_early_options init/main.c 755
arch_call_rest_init arch 或 weak 默认

下一篇02 rest_init 与 kernel_init

文章互动

阅读 --

留言

0 条留言

正在加载留言…