spin-table启动方法
我们都知道,一个系统的启动的基本流程是先bootloader然后运行kernel。当对所有CPU上电后,那么所有的CPU都会从bootrom里面开始执行代码,为了防止并发的一些问题,有必要将除了primary cpu以外的cpu拦截下来。使boot的过程是顺序的,而不是并发的。
在
启动的过程中,bootloader中有一道栅栏,它拦住了除了cpu0外的其他cpu。cpu0直接往下运行,进行设备初始化以及运行Linux
Kernel。其他cpu0则在栅栏外进入睡眠状态。cpu0在初始化smp的时候,会在cpu-release-addr里面填入一个地址并唤醒其他
cpu。这时候,在睡眠的这个cpu接受到了信号,醒来的时候先检查下cpu-release-addr这个地址里面的数据是不是不等于0。如果不等于
0,意味着主cpu填入了地址,该它上场了。它就会直接填入该地址执行。
下面我们看看arm64里面的实现,在arch/arm64/boot/dts/xxx.dts中有如下描述:
cpu@0 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x0="">;
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8="">;
};
在arch/arm64/kernel/smp_spin_table.c中有相关的处理。我们现在只关注一下,怎么给其他cpu发信号,关注一下下面函数中的几行关键代码:
static int smp_spin_table_cpu_prepare(unsigned int cpu):
..........
release_addr[0] = (void *) cpu_to_le64(__pa(secondary_holding_pen));
__flush_dcache_area(release_addr, sizeof(release_addr[0]));
/*
* Send an event to wake up the sec