当前位置:首页>Linux>Linux+TF-A 多核启动:U-Boot 分流 vs Linux SMP 核心逻辑

Linux+TF-A 多核启动:U-Boot 分流 vs Linux SMP 核心逻辑

  • 2026-09-02 17:15:24
Linux+TF-A 多核启动:U-Boot 分流 vs Linux SMP 核心逻辑

搞懂:U-Boot 在“可能多核同时进来”的场景下,如何把主核/从核分流;以及在 LS1028 + TF-A(PSCI)体系下,Linux 的多核拉起真正依赖什么

一、先拆 3 件事:别把问题归错层

多核启动的核心误区是混淆「U-Boot 内部分流」和「Linux 多核拉起」,先明确三层边界:

  1. BootROM 层
    :是否让多个核同时进入 BL33(U-Boot);
  2. U-Boot 层
    :自身是否需要拉起从核跑内部 SMP 逻辑(仅 U-Boot 自保,≠Linux SMP);
  3. Linux 层
    :如何拉起从核(LS1028+TF-A 核心是 PSCI,Linux 通过 SMC 调用 TF-A 唤醒从核)。

👉 结论:start.S 的主从核分流只解决第 1 件事;Linux 只识别 1 核,90% 是第 3 件事出问题。

二、U-Boot start.S 主从核分流:编译宏决定是否生效

分流代码位置:arch/arm/cpu/armv8/start.S(lowlevel_init 后、跳_main 前)核心逻辑不是 “默认生效”,而是由编译宏控制:

5 个排错关键知识点

1. branch_if_master 宏的核心判断逻辑宏定义路径:arch/arm/include/asm/macro.h

  • 开启 CONFIG_ARMV8_MULTIENTRY:读取 mpidr_el1 寄存器,判定全 0 affinity 的核为主核;
  • 未开启该宏:无主从核判断逻辑,直接无条件跳转到 master_label 标签。

2. spin-table 多核唤醒路径本质核心代码:

arch/arm/cpu/armv8/spin_table_v8.S

从核等待逻辑

wfe(低功耗休眠)→ 读取 spin_table_cpu_release_addr → 地址非 0 则执行 br(跳转)。

唤醒关键

主核需完成两步操作:① 写入从核执行的入口地址;② 发送 sev/SGI 触发 wfe 退出(而非仅依赖中断),从核才会检查地址并执行。

3. CONFIG_ARMV8_MULTIENTRY 路径(主流方案)

生效条件:仅开启 CONFIG_ARMV8_MULTIENTRY 时生效核心代码:arch/arm/cpu/armv8/start.S

核心逻辑

从核采用「wfe 低功耗休眠 + 轮询可配置地址」机制:

  1. 从核先进入 wfe 降低功耗;
  2. 被唤醒后循环读取 CPU_RELEASE_ADDR 指向的地址;
  3. 仅读到非 0 有效唤醒指令时,退出循环并执行后续逻辑。

关键特性:非固定地址

CPU_RELEASE_ADDR 是可配置宏(而非代码写死的物理地址),可适配不同平台的内存布局,灵活性显著提升。

4. 从核 EL 等级切换的触发条件

在 lowlevel_init 初始化流程中:从核执行 armv8_switch_to_el2/el1(EL 等级切换)逻辑,仅在 CONFIG_ARMV8_MULTIENTRY 开启时生效。

5. LS1028 平台 CPU_RELEASE_ADDR 特殊设计

定义位置

include/configs/ls1028a_common.h

核心特殊点

  1. CPU_RELEASE_ADDR
     并非固定共享内存 mailbox,而是 secondary_boot_func 符号(平台自定义从核入口钩子);
  2. Layerscape 平台未依赖通用逻辑,更偏向自有 spin table 代码:arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S。

三、Linux 多核拉起核心:LS1028+TF-A 必走 PSCI

对 mydjls1028_tfa_defconfig,真实链路是:U-Boot 启用 PSCI 支持 → Linux DTB 配置 psci → TF-A/BL31 提供 PSCI 接口 → Linux 通过 SMC 唤醒从核。

Linux 只识别 1 核?按优先级查这 3 点

1. 最高优先级:DTB 配置(核心中的核心)

检查设备树路径:arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi#L20-L56关键配置:

✅ 验证指令:cat /proc/device-tree/cpus/cpu@1/enable-method → 输出必须是 psci。

2. 次优先级:TF-A/BL31 的 PSCI 实现

  • TF-A 编译需加:ENABLE_PSCI=1 PSCI_VERSION=1.0;
  • U-Boot 需开启:CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y CONFIG_ARMV8_PSCI_FW=y。

3. 最后排查:内核裁剪配置(别误删关键项)

必须保留的配置:

CONFIG_SMP=y // 多核核心开关CONFIG_ARM64_PSCI=y // PSCI核心支持CONFIG_ARM64_PSCI_1_0=y // 匹配TF-A的PSCI 1.0CONFIG_ARM_SMC=y // SMC指令(调用PSCI的基础)

✅ 验证指令:zcat /proc/config.gz | grep -E "SMP|PSCI|SMC" → 均为 y。

👉 反常识结论:

U-Boot 的 CONFIG_ARMV8_MULTIENTRY/SPIN_TABLE,多数情况下不直接决定 Linux SMP。

四、小测试 & 答案(实战排错优先级)

问题:内核开了 SMP,但启动后只识别到 1 个核心,最可能先查什么?答案(优先级从高到低):

  1. 1、查 DTB 中 /cpus 的 enable-method 是否为 psci,以及 psci 节点 / 属性是否存在;
  2. 2、查 TF-A(BL31)是否提供 PSCI(版本 / 配置 / 启动链是否一致);
  3. 3、查内核裁剪是否误删 PSCI/SMC 相关关键配置;
  4. 4、最后核对 U-Boot 的多核配置(优先级最低)。

核心总结

  1. LS1028+TF-A 平台:Linux 多核启动核心是 PSCI(DTB + 内核 + TF-A),U-Boot 分流仅为自保;
  2. CONFIG_ARMV8_MULTIENTRY:ARMv8 多核 U-Boot 主流方案,核心是 “wfe 低功耗休眠 + 轮询可配置的 CPU_RELEASE_ADDR”,地址可配置而非写死,适配性更强;
  3. 排错优先级:DTB > 内核 PSCI 配置 > TF-A 版本 > U-Boot 多核配置;
  4. 内核裁剪时,PSCI/SMC/SMP 相关配置绝对不能删,否则多核必失效。

最新文章

随机文章