目录
13.1.1 多核启动基本概念
在ARM多核系统中,TF-A需要协调多个CPU核心的启动过程,主要分为两种启动模式:
-
冷启动(Cold Boot)
- 所有CPU核心从复位状态启动
- 由主核(Primary Core)执行完整启动流程
- 从核(Secondary Cores)在特定同步点等待唤醒
-
热启动(Warm Boot)
- 系统从低功耗状态恢复时触发
- 各核心可能保持缓存一致性
- 需要快速恢复执行上下文
13.1.2 启动阶段划分
TF-A的多核启动流程分为三个关键阶段:
阶段 | 执行核心 | 主要任务 |
---|---|---|
主核初始化 | 主核(通常CPU0) | 硬件初始化、BL1/BL2执行、BL31加载 |
从核唤醒 | 所有核心 | 建立核间通信、设置运行环境 |
运行时同步 | 所有核心 | 进入BL31/操作系统前的最终同步 |
13.1.3 主从核启动流程
主核执行流程
// 典型的主核执行路径
bl1_main() → bl2_main() → bl31_main() → bl33_entry()
从核启动机制
-
等待机制:
从核上电后执行spin_table
或PSCI
协议等待唤醒:/* 典型从核自旋等待代码 */ secondary_hold: wfe // 等待事件 ldr x0, [x1] // 检查唤醒地址 cbz x0, secondary_hold // 如果为0则继续等待 br x0 // 跳转到指定地址
-
唤醒方式:
- Mailbox机制:通过共享内存传递启动地址
- PSCI_CPU_ON:通过安全监控调用唤醒从核
13.1.4 同步机制实现
内存屏障使用
// 数据同步屏障确保内存访问顺序
dsb sy
// 指令同步屏障确保指令顺序
isb
核间锁实现
TF-A使用bakery
算法实现自旋锁:
void bakery_lock(int cpu_id) {
entering[cpu_id] = true;
number[cpu_id] = max(number) + 1;
entering[cpu_id] = false;
for (int other = 0; other < CPU_COUNT; other++) {
while (entering[other]); // 等待其他CPU完成选号
while (number[other] &&
(number[other] < number[cpu_id] ||
(number[other] == number[cpu_id] && other < cpu_id)));
}
}
13.1.5 多核启动配置
平台相关配置
# 在平台定义文件中指定核心数量
ARM_PLAT_MT := 1
PLATFORM_CORE_COUNT := 4
设备树配置示例
cpus {
#address-cells = <2>;
#size-cells = <0>;
cpu0: cpu@0 {
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
cpu1: cpu@1 {
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
};
13.1.6 常见问题与调试
典型问题排查
-
从核无法启动:
- 检查
cpu-release-addr
是否正确配置 - 验证主核是否写入了正确的唤醒地址
- 检查
-
核间死锁:
- 使用JTAG检查各核心PC指针
- 检查
bakery
锁算法实现
-
缓存一致性问题:
- 确保正确使用
flush_dcache_range()
- 检查共享内存区域的缓存配置
- 确保正确使用
调试技巧
# 通过TF-A日志观察启动顺序
make LOG_LEVEL=40 DEBUG=1
13.1.7 性能优化建议
-
并行初始化:
- 在BL31阶段允许从核并行初始化外设
-
延迟唤醒:
- 对非关键从核采用按需唤醒策略
-
缓存预热:
- 主核预先加载共享代码到缓存
注意:多核同步机制必须与具体SoC的微架构特性相匹配,特别是对于支持乱序执行的现代ARM处理器,需要严格遵循ARM内存模型规范。