smp启动-smp_prepare_cpus

上一篇:time_init() 调用 drivers/clocksource/arm_arch_timer.c 中 arch_timer_of_init 注册CPUHP_AP_ARM_ARCH_TIMER_STARTING的回调函数

https://www.cnblogs.com/zhangzhiwei122/p/16092867.html

 

参考-总流程:https://www.cnblogs.com/pengdonglin137/p/11925299.html

 

start_kernel -> rest_init-> kernel_thread(kernel_init) & kernel_init-> kernel_init_freeable->smp_prepare_cpus

start_kernel -> rest_init-> kernel_thread 函数创建新 task, 新task 执行 kernel_init 函数

kernel_init 调用 kernel_init_freeable

1497 - 等待 kthreadd_done , 这个在 rest_init 函数里面  713        complete(&kthreadd_done);

1492static noinline void __init kernel_init_freeable(void)
1493{
1494        /*
1495         * Wait until kthreadd is all set-up.
1496         */
1497        wait_for_completion(&kthreadd_done);

1507        cad_pid = task_pid(current);
1508
1509        smp_prepare_cpus(setup_max_cpus);
1510
1511        workqueue_init();
1512
1513        init_mm_internals();
1514
1515        do_pre_smp_initcalls();
1517
1518        smp_init();

 

smp_prepare_cpus

setup_max_cpus - 这个在 kernel/smp.c 里面,

 738/* Setup configured maximum number of CPUs to activate */
 739unsigned int setup_max_cpus = NR_CPUS;
 740EXPORT_SYMBOL(setup_max_cpus);

去掉 numa 相关信息,smp_prepare_cpus 如下

 743void __init smp_prepare_cpus(unsigned int max_cpus)
 744{
 745        const struct cpu_operations *ops;
 746        int err;
 747        unsigned int cpu;
 748        unsigned int this_cpu;
 749
 750        init_cpu_topology();

 752        this_cpu = smp_processor_id();
 753        store_cpu_topology(this_cpu);
 756
 757        /*
 758         * If UP is mandated by "nosmp" (which implies "maxcpus=0"), don't set
 759         * secondary CPUs present.
 760         */
 761        if (max_cpus == 0)
 762                return;
 763
 764        /*
 765         * Initialise the present map (which describes the set of CPUs
 766         * actually populated at the present time) and release the
 767         * secondaries from the bootloader.
 768         */
 769        for_each_possible_cpu(cpu) {
 770
 771                per_cpu(cpu_number, cpu) = cpu;
 772
 773                if (cpu == smp_processor_id())
 774                        continue;
 775
 776                ops = get_cpu_ops(cpu);
 777                if (!ops)
 778                        continue;
 779
 780                err = ops->cpu_prepare(cpu);
 781                if (err)
 782                        continue;
 783
 784                set_cpu_present(cpu, true);
 786        }
 787}
 788

cpu topology

750 ~ 753 ,先 init_cpu_topology 和 store_cpu_topology

drivers/base/arch_topology.c 中,init_cpu_topology 

489  -  定义数组  cpu_topology ,就是这个数组 来记录 cpu 拓扑关系。 结构定义在  include/linux/arch_topology.h 中

588 - reset_cpu_topology 将数组里面的值都设置为 无效 值。

594 ~ 598 先后尝试使用 parse_acpi_topology 和 parse_dt_topology 来填充 上面的数组信息。

更多细节,可以参考: https://blog.csdn.net/u013910383/article/details/110082275

 486/*
 487 * cpu topology table
 488 */
 489struct cpu_topology cpu_topology[NR_CPUS];
 490EXPORT_SYMBOL_GPL(cpu_topology);


 585#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
 586void __init init_cpu_topology(void)
 587{
 588        reset_cpu_topology();
 589
 590        /*
 591         * Discard anything that was parsed if we hit an error so we
 592         * don't use partial information.
 593         */
 594        if (parse_acpi_topology())
 595                reset_cpu_topology();
 596        else if (of_have_populated_dt() && parse_dt_topology())
 597                reset_cpu_topology();
 598}
 599#endif

 

753 store_cpu_topology  ,在 arch/arm64/kernel/topology.c 里面,在arm64 arch 上面,cpu 指示的是 core ,所以 cpuid 赋值到 core_id 里面。

注释 解释了这样赋值的原因。

  25void store_cpu_topology(unsigned int cpuid)
  26{
  27        struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];


  39        /*
  40         * This would be the place to create cpu topology based on MPIDR.
  41         *
  42         * However, it cannot be trusted to depict the actual topology; some
  43         * pieces of the architecture enforce an artificial cap on Aff0 values
  44         * (e.g. GICv3's ICC_SGI1R_EL1 limits it to 15), leading to an
  45         * artificial cycling of Aff1, Aff2 and Aff3 values. IOW, these end up
  46         * having absolutely no relationship to the actual underlying system
  47         * topology, and cannot be reasonably used as core / package ID.
  48         *
  49         * If the MT bit is set, Aff0 *could* be used to define a thread ID, but
  50         * we still wouldn't be able to obtain a sane core ID. This means we
  51         * need to entirely ignore MPIDR for any topology deduction.
  52         */
  53        cpuid_topo->thread_id  = -1;
  54        cpuid_topo->core_id    = cpuid;
  55        cpuid_topo->package_id = cpu_to_node(cpuid);

 

769 ~ 786 for each cpu 循环

771   对 cpu_number 这个 per cpu变量 赋值

773 ~ 774 跳过 boot cpu 【当前执行代码的cpu】,因为对于 boot cpu ,不需要 调用 cpu ops 的  cpu_prepare ,也不需要 set_preset

对于其他cpu,调用  cpu_ops[cpu]->cpu_prepare  &  set_cpu_preset

 

cpu_prepare 对于 psci 机制而言,就是 arch/arm64/kernel/psci.c 里面的 cpu_psci_cpu_prepare ,

里面仅仅检查了 psci_ops.cpu_on ,如果不存在,就输出 错误告警。

psci_ops 这个在 drivers/firmware/psci/psci.c 中定义,在 psci_0_2_set_functions(void) 函数中赋值。

psci_0_2_set_functions 函数调用见  smp启动-psci模块初始化   https://www.cnblogs.com/zhangzhiwei122/p/16090641.html

  28
  29static int __init cpu_psci_cpu_prepare(unsigned int cpu)
  30{
  31        if (!psci_ops.cpu_on) {
  32                pr_err("no cpu_on method, not booting CPU%d\n", cpu);
  33                return -ENODEV;
  34        }
  35
  36        return 0;
  37}

 

下一篇: smp_init 开核,新核心执行secondary entry

https://www.cnblogs.com/zhangzhiwei122/p/16093602.html

 

posted @ 2022-04-02 18:03  张志伟122  阅读(276)  评论(0编辑  收藏  举报