良许Linux教程网 干货合集 Linux中arm64多核启动流程分析

Linux中arm64多核启动流程分析

本篇文章为大家分享一下linux中arm64多核启动流程分析,我们说的普通linux指的是X86 linux,他们都是linux系统,但是由于ARM和X86是不同的CPU架构,他们的指令集不同,所以软件编译环境不同,软件代码一般不能互用。

u=683570609,2557492579&fm=26&gp=0

Kernel :4.12.8

arm64多核启动流程

smp_init_cpus() //设置多核启动参数和动作
=>static int __init smp_cpu_setup(int cpu) //位于 arch/arm64/kenerl/smp.c
=> cpu_read_ops
=> cpu_get_ops
{ ops = acpi_disabled ? dt_supported_cpu_ops : acpi_supported_cpu_ops; }

.cpu_init    = smp_spin_table_cpu_init,

//分析从dts获取启动多核的两种方式 spin_table 和 psci
static const struct cpu_operations *dt_supported_cpu_ops[] __initconst = {
&smp_spin_table_ops,
&cpu_psci_ops,
NULL,
};

// spin_table 方式的几个动作接口
const struct cpu_operations smp_spin_table_ops = {
.name        = “spin-table”,
.cpu_init    = smp_spin_table_cpu_init,
.cpu_prepare    = smp_spin_table_cpu_prepare,
.cpu_boot    = smp_spin_table_cpu_boot, //bring up实际动作
};

bringup_cpu
=>int __cpu_up(unsigned int cpu, struct task_struct *idle)
=>ret = boot_secondary(cpu, idle);
cpu_ops[cpu]->cpu_boot(cpu); //实际调用 smp_spin_table_cpu_boot 之类的启动

==============================
下面分析怎么执行cpu_boot的过程
==============================
static struct cpuhp_step cpuhp_bp_states[] =
/* Kicks the plugged cpu into life */
[CPUHP_BRINGUP_CPU] = {
.name            = “cpu:bringup”,
.startup.single        = bringup_cpu,
.teardown.single    = NULL,
.cant_stop        = true,
},

cpuhp_get_step() //唤起一个核有多步,这个是根据state选择对应的状态动作
sp = cpuhp_is_ap_state(state) ? cpuhp_ap_states : cpuhp_bp_states;
return sp + state;

 

kernel_init() =>kernel_init_freeable()

|=>void __init smp_prepare_cpus(unsigned int max_cpus)
/*
* Initialise the present map (which describes the set of CPUs
* actually populated at the present time) and release the
* secondaries from the bootloader.
*/
for_each_possible_cpu(cpu) {
err = cpu_ops[cpu]->cpu_prepare(cpu);
|=>smp_init => cpu_up=>do_cpu_up  // 同样是从kernel_init_freeable()调用下来的
=>_cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
=>cpuhp_up_callbacks
=>cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
bool bringup, struct hlist_node *node)
{
if (!step->multi_instance) {
cb = bringup ? step->startup.single : step->teardown.single;
ret = cb(cpu);
//这里实际就是拿出了bringup_cpu,调用之

}

   spin table方式启动

实际就是把地址写入spin table中,然后发出sev (send envent,是一个指令)从核就奔跑起来了。

在smp_prepare_cpus() 中调用了smp_spin_table_cpu_prepare() 从核就开始跑了,不过内核设置了wfe 等待真正任务才能真正执行任务。

smp_init()中调用了smp_spin_table_cpu_boot()就是真正的启动了一个idle任务了(待确认)

 
 static int smp_spin_table_cpu_prepare(unsigned int cpu)
 {
  __le64 __iomem *release_addr;
 
  if (!cpu_release_addr[cpu])
   return -ENODEV;
 
  /*
   * The cpu-release-addr may or may not be inside the linear mapping.
   * As ioremap_cache will either give us a new mapping or reuse the
   * existing linear mapping, we can use it to cover both cases. In
   * either case the memory will be MT_NORMAL.
   */
  release_addr = ioremap_cache(cpu_release_addr[cpu],
          sizeof(*release_addr));
  if (!release_addr)
   return -ENOMEM;
 
  /*
   * We write the release address as LE regardless of the native
   * endianess of the kernel. Therefore, any boot-loaders that
   * read this address need to convert this address to the
   * boot-loader's endianess before jumping. This is mandated by
   * the boot protocol.
   */
  writeq_relaxed(__pa_symbol(secondary_holding_pen), release_addr);
  __flush_dcache_area((__force void *)release_addr,
        sizeof(*release_addr));
 
  /*
   * Send an event to wake up the secondary CPU.
   */
  sev();
 
  iounmap(release_addr);
 
  return 0;
 }
 
 static int smp_spin_table_cpu_boot(unsigned int cpu)
 {
  /*
   * Update the pen release flag.
   */
  write_pen_release(cpu_logical_map(cpu));
 
  /*
   * Send an event, causing the secondaries to read pen_release.
   */
  sev();
 
  return 0;
 }

以上就是良许教程网为各位朋友分享的Linux系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你!

137e00002230ad9f26e78-265x300

本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部