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