菜单

kaoqi
kaoqi
发布于 2026-09-22 / 4 阅读
0
0

kernel的第6个函数展开

从这个函数开始,boot_cpu_init,开始正式初始化CPU。

这是一个位于/kernel/cpu.c处展开的函数:

void __init boot_cpu_init(void)
{
	int cpu = smp_processor_id();

	/* Mark the boot cpu "present", "online" etc for SMP and UP case */
	set_cpu_online(cpu, true);
	set_cpu_active(cpu, true);
	set_cpu_present(cpu, true);
	set_cpu_possible(cpu, true);

#ifdef CONFIG_SMP
	__boot_cpu_id = cpu;
#endif
}

其中,smp_processor_id函数在/include/linux/smp.h中被展开为raw_smp_processor_id函数:

然后会在具体的arm64文件夹中展开为偏移量计算函数:

或者是直接给0

这里的smp id机制其实及其迷惑,并没有看懂具体的关联关系。

总之,在此时根据cpu值0进行四个操作

set_cpu_online(cpu, true);

set_cpu_active(cpu, true);

set_cpu_present(cpu, true);

set_cpu_possible(cpu, true);

它的代码为:

void set_cpu_online(unsigned int cpu, bool online)
{
	if (online) {
		if (!cpumask_test_and_set_cpu(cpu, &__cpu_online_mask)) // 这就是一个简单的判断标准
			atomic_inc(&__num_online_cpus); // 这就是一个简单的原子位+1
	} else {
		if (cpumask_test_and_clear_cpu(cpu, &__cpu_online_mask))
			atomic_dec(&__num_online_cpus);
	}
}

set_cpu_active(unsigned int cpu, bool active)
{
	if (active)
		cpumask_set_cpu(cpu, &__cpu_active_mask);
	else
		cpumask_clear_cpu(cpu, &__cpu_active_mask);
}

static inline void
set_cpu_present(unsigned int cpu, bool present)
{
	if (present)
		cpumask_set_cpu(cpu, &__cpu_present_mask);
	else
		cpumask_clear_cpu(cpu, &__cpu_present_mask);
}

static inline void
set_cpu_possible(unsigned int cpu, bool possible)
{
	if (possible)
		cpumask_set_cpu(cpu, &__cpu_possible_mask);
	else
		cpumask_clear_cpu(cpu, &__cpu_possible_mask);
}

看上去是很简单的,首先进行依次cpu的online检测,如果没在位,旧把__num_online_cpus+1。

其他的函数也几乎执行的是一模一样的动作,似乎就是针对对应的mask做了一个维护。

CPU子系统

上文提及的针对boot_cpu_init函数的动作,应该理解为一种软件上的标识准备。具体来说就是,这是一个针对CPU Subsystem资源池进行的,CPU0的一种初始化设置。

Subsystem本身包含了core层与Driver层两层,其中Core层主要提供一系列的API接口,用于被调用,而Driver层则是进行一系列的函数实例化。注意,只要是子系统,就一定会在虚拟文件系统中生成对应的file句柄,层级结构也将直接依托虚拟文件系统产生。

cpu mask定义在/kernel/cpu.c文件中:

相应的struct cpumask,则是一个直白的无穷长数组:

目前暂时没有什么好办法进一步确认里面的东西。


评论