<4,62,2,8>:smp_init();
smp_init()是我们的linux-smp映像中启动另外一个核的最重要的代码,该函数主要是引导SMP系统中的AP,该函数会依次调用:smp_init()->cpu_up()->_cpu_up()->__cpu_up()->smp_ops->kick_cpu
(kick_cpu是一个函数指针,指向smp_86xx_kick_cpu,故会执行smp_86xx_kick_cpu()函数)
smp_86xx_kick_cpu()->
smp_86xx_release_core()->__secondary_start_mpc86xx()->__secondary_start()来启动core
1,并调用set_cpu_online()函数将次CPU加入到cpu_online_map变量中,用以向主CPU通知该次CPU已经被激活。
下面我们就来分析主CPU(即Core
0,又称之为BSP)是如何启动次CPU,一直到linux系统中的所有CPU的地位均等为止。
该函数(linux-2.6.38/init/main.c)的源码如下:
static void __init
smp_init(void)
{
unsigned int cpu;
// FIXME: This should be done in userspace --RR
for_each_present_cpu(cpu)
{ <4,62,2,8,1>
if (num_online_cpus() >= setup_max_cpus)
break;
if (!cpu_online(cpu))
cpu_up(cpu); <4,62,2,8,2>
}
// Any cleanup work
printk(KERN_INFO "Brought up %ld CPUs\n",
(long)num_online_cpus());
smp_cpus_done(setup_max_cpus); <4,62,2,8,3>
}
<4,62,2,8,1>:
for_each_present_cpu(cpu)
通过该循环调用cpu_up()函数逐个启动目标系统中所有次CPU,它是如何找到系统中的所有CPU的呢?请看for_each_present_cpu(cpu)宏函数的展开(linux-2.6.38/include/linux/cpumask.h):
#define
for_each_present_cpu(cpu) for_each_cpu((cpu),
cpu_present_mask)
cpu_present_mask变量在<4,12>中的setup_arch(&command_line)函数中进行初始化的,该全局变量也是一个CPU位图,我们的目标系统中的每个CPU在该位图中都有对应的位。比如我们的MPC8641HPCN开发板有两个E600核心,所以cpu_present_mask的第0位和第1位均为1,其余为0。
for_each_present_cpu(cpu)宏函数就是通过扫描cpu_present_mask中的所有位来获得系统中的所有CPU,调用cpu_up()函数来逐个的启动各个AP。
<4,62,2,8,2>:cpu_up(cpu)
该函数在linux-2.6.38/kernel/cpu.c中定义,作用是启动指定的cpu。
输入:BSP要启动的cpu编号,在我们的MPC8641D处理器上就是Core
1,其编号为1。
int __cpuinit cpu_up(unsigned
int cpu)
{
int err = 0;
#ifdef CONFIG_MEMORY_HOTPLUG //本平台的.config文件没有定义该元素
int nid;
pg_data_t *pgdat;
#endif
if (!cpu_possible(cpu)) {
printk(KERN_ERR "can't online cpu %d because it is not "
"configured as may-hotadd at boot time\n", cpu);
#if
defined(CONFIG_IA64)
printk(KERN_ERR "please check additional_cpus= boot "
"parameter\n");
#endif
return -EINVAL;
}
#ifdef CONFIG_MEMORY_HOTPLUG//本平台的.config文件没有定义该元素
nid