其他分享
首页 > 其他分享> > smp启动-setup_nr_cpu_ids-smp_prepare_boot_cpu

smp启动-setup_nr_cpu_ids-smp_prepare_boot_cpu

作者:互联网

上一篇: setup_arch->smp_init_cpus

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

 

start_kernel -> setup_nr_cpu_ids & smp_prepare_boot_cpu

 848asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
 849{

 873        setup_nr_cpu_ids();
 874        setup_per_cpu_areas();
 875        smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
 876        boot_cpu_hotplug_init();
 877

 

873  - 设置 nr_cpu_ids 这个变量,表示真实存在的 possible cpus 。因为前面setup_arch 里面已经根据 dtb ,知道了设备的 cpu 信息。

874  - setup_pre_cpu_areas ,为每一个cpu , 设置 per cpu 变量存储空间 。

875 smp_prepare_boot_cpu , 将 boot cpu 的 信息 存储在 per cpu 变量 cpu_data 里面。

 

smp_prepare_boot_cpu

1、cpu_data 这个 per_cpu 结构体对象里面填充 cpu 寄存器的值。

2、根据cpu_data  值,初始化 cpu features 模块

3、根据cpu feature 模块初始化结果,再初始化 boot cpu alternatives

4、如果系统使用 irq prio mask, 调用 init_gic_priority_masking

 

arch/arm64/kernel/smp.c

 450void __init smp_prepare_boot_cpu(void)
 451{
 452        set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
 453        cpuinfo_store_boot_cpu();
 454
 455        /*
 456         * We now know enough about the boot CPU to apply the
 457         * alternatives that cannot wait until interrupt handling
 458         * and/or scheduling is enabled.
 459         */
 460        apply_boot_alternatives();
 461
 462        /* Conditionally switch to GIC PMR for interrupt masking */
 463        if (system_uses_irq_prio_masking())
 464                init_gic_priority_masking();
 465}

452  -  set my cpu offset , 因为 在进入  smp_prepare_boot_cpu 前,使用setup_per_cpu_areas 真正 设置了 各个CPU 的per cpu data 区域和偏移。

    后面,boot cpu 应使用自己的一份拷贝,而不是  原始的 per cpu data . 所以,使用 set_my_cpu_offset 设置 offset

 

   相关信息: 前面设置 boot cpu offset 为 0 : https://www.cnblogs.com/zhangzhiwei122/p/16051676.html

                      per cpu 相关: https://www.cnblogs.com/zhangzhiwei122/p/16054141.html

 

453 设置 cpu info

         arch/arm64/include/asm/cpu.h 中定义  struct cpuinfo_arm64 

         arch/arm64/kernel/cpuinfo.c 定义函数 cpuinfo_store_boot_cpu

 414void __init cpuinfo_store_boot_cpu(void)
 415{
 416        struct cpuinfo_arm64 *info = &per_cpu(cpu_data, 0);
 417        __cpuinfo_store_cpu(info);
 418
 419        boot_cpu_data = *info;
 420        init_cpu_features(&boot_cpu_data);
 421}

416  - 取得 cpu_data 这个 struct  cpuinfo_arm64 结构体对象的指针

417 - 指针传入  __cpuinfo_store_cpu ,在次函数中,读取 cpu 寄存器,将寄存器里面的值,写入 cpu_data 指向对象

419   拷贝一份   cpuinfo_arm64 对象,放在 boot_cpu_data 里面

420  调用 init_cpu_features ,这个在  arch/arm64/kernel/cpufeature.c 中,cpu feature ,cpu 特定的功能,根据寄存器某个bit 位的值,来判断某个feature 是否启用? 这个暂时略

       在 arch/arm64/kernel/cpufeature.c 中,定义了 boot_capabilities ,init_cpu_features 初始化这个值, 然后 apply_boot_altenatives 依赖它里面的值。

 102 DECLARE_BITMAP(boot_capabilities, ARM64_NPATCHABLE);

apply_boot_alternatives

arch/arm64/kernel/alternative.c

 

 135static void __apply_alternatives(void *alt_region,  bool is_module,
 136                                 unsigned long *feature_mask)
 137{


 232/*
 233 * This is called very early in the boot process (directly after we run
 234 * a feature detect on the boot CPU). No need to worry about other CPUs
 235 * here.
 236 */
 237void __init apply_boot_alternatives(void)
 238{
 239        struct alt_region region = {
 240                .begin  = (struct alt_instr *)__alt_instructions,
 241                .end    = (struct alt_instr *)__alt_instructions_end,
 242        };
 243
 244        /* If called on non-boot cpu things could go wrong */
 245        WARN_ON(smp_processor_id() != 0);
 246
 247        __apply_alternatives(&region, false, &boot_capabilities[0]);
 248}

135 - 定义了  __apply_alternatives 函数,具体实现,需要 了解  alternative instruction 背景,暂时略。

237 定义 apply_boot_alternatives

239 ~ 242 取 kernel image 里面的  __alt_instructions 节的开始和结尾,组成 alt_region 对象,247 行,用这个对象调用   135 行定义的函数。

 

priority masking

检查 是否是否使用 irq priority masking ,这个在  arch/arm64/include/asm/cpufeature.h 中,根据 menuconfig 配置和 cpu 寄存器值共同决定

 702static __always_inline bool system_uses_irq_prio_masking(void)
 703{
 704        return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) &&
 705               cpus_have_const_cap(ARM64_HAS_IRQ_PRIO_MASKING);
 706}

Priority Masking(优先级屏蔽)
GICC_PMR定义了目标处理器的优先级阈值。GIC仅上报那些优先级高于这个阈值的pending中断。初始值为0,屏蔽所有的中断。

 181static void init_gic_priority_masking(void)
 182{

 192        gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
 193}

向 gic pmr 寄存器写入内容,初始化 priority masking

 

标签:__,prepare,boot,smp,init,arm64,cpu
来源: https://www.cnblogs.com/zhangzhiwei122/p/16091458.html