4. S32G启动流程与虚拟化环境搭建

S32G 的启动不是“上电后直接跑 Linux”这么简单,而是一条由硬件信任根逐级向软件世界传递控制权的链。理解这条链,是搭建虚拟化环境的前提:只有知道每一级镜像由谁校验、被放到哪里、以什么异常等级运行,才能在 Hypervisor 启动失败时快速定位是 HSE 固件没起来、ATF 没切到 EL2,还是 U-Boot 的设备树把 CPU 释放错了。

一、启动链的五个阶段与信任传递

S32G 上电后,CPU 首先执行片内 BootROM。BootROM 读取启动模式引脚(如从 QSPI、SD、eMMC 启动),从对应介质加载第一级镜像,并用芯片内固化的密钥或 HSE 提供的服务校验其签名。校验通过后,控制权交给 HSE 固件与引导加载程序。HSE(Hardware Security Engine)固件运行在独立的安全核上,负责密钥管理、加解密、安全启动校验和生命周期管理,它先于应用核的软件就绪,后续每一级镜像的验签都可以请求 HSE 完成。

应用核侧的顺序通常是:BootROM → HSE 固件 → BL2(ATF 的第一阶段)→ BL31(ATF 运行时)→ U-Boot → Hypervisor → Guest OS。其中 ATF(Arm Trusted Firmware)承担异常等级切换与 PSCI 服务:BL2 在 EL3 完成平台初始化并加载 BL31、BL33(即 U-Boot),BL31 常驻 EL3,提供电源管理、CPU 上下电和系统复位等 SMC 调用。U-Boot 运行在 EL2 或 EL1,负责加载 Hypervisor 镜像与各 Guest 的内核、设备树,最后通过 booti/bootm 跳转。Hypervisor 接管 EL2 后创建虚拟机,把 Guest 内核放到 EL1 运行。

S32G 启动链与异常等级映射 启动阶段(时间顺序) BootROM 读启动模式 · 验签 · 加载 HSE 固件 安全核 · 密钥 · 验签服务 BL2(ATF) 平台初始化 · 加载 BL31/BL33 BL31(ATF 运行时) EL3 常驻 · PSCI · SMC U-Boot(BL33) 加载 HV · Guest 内核/DTB Hypervisor + Guest EL2 创建 VM · Guest 跑 EL1 异常等级 / 运行域 BootROM(片内 ROM,不可修改) 信任根 HSE 安全核(独立于应用核) 安全服务 应用核异常等级 EL3:BL31 常驻 EL2:Hypervisor EL1:U-Boot / Guest OS 内核 U-Boot:加载 HV 与各 Guest 镜像、设备树 Hypervisor 创建 VM,Guest 在 EL1 隔离运行 验签请求

二、镜像布局与加载地址

在 S32G 的典型工程中,各镜像按固定偏移写入启动介质。以 QSPI 启动为例,BootROM 从 0x0 读取头部并加载 HSE 固件与 BL2;BL2 依据镜像头中的加载地址把 BL31 放到 SRAM 或 DDR 的保留区,把 U-Boot 放到 DDR 的代码段。U-Boot 再从存储或网络加载 Hypervisor 与 Guest 镜像。下面是一份示例性的镜像布局,实际地址需以所用 BSP 的链接脚本和启动头为准:

QSPI 偏移        镜像              目标地址        说明
0x0000_0000     BootROM 头/BL2    片内 SRAM       BootROM 直接加载
0x0001_0000     HSE 固件          安全核专用区     由 BootROM 校验后启动
0x0004_0000     BL31 (ATF)        DDR 保留区       EL3 运行时
0x0010_0000     U-Boot (BL33)     DDR 代码段       EL2/EL1 引导
0x0080_0000     Hypervisor        DDR 高地址       EL2 接管
0x0100_0000     Guest0 内核+DTB   DDR 低地址       EL1 运行
0x0180_0000     Guest1 内核+DTB   DDR 中地址       EL1 运行

需要强调的是,BL31 必须放在所有 Guest 都不会覆盖的区域,因为它是 EL3 的常驻代码,任何一次 PSCI CPU_ON 都要回到这里执行。若把 Guest 内核加载到与 BL31 重叠的地址,典型现象是启动到某个 Guest 时系统直接挂死或复位,而不是给出明确报错。

三、多核启动:从 BootROM 到 PSCI

S32G 有多个 Cortex-A53 核。上电时并非所有核都从 BootROM 开始执行,通常只有一个核被 BootROM 选为引导核,其余核处于等待状态。引导核依次完成 HSE、BL2、BL31、U-Boot 和 Hypervisor 的加载,最后由 Hypervisor 通过 PSCI 的 CPU_ON 调用唤醒从核。BL31 收到 SMC 后,负责给目标核设置入口地址、异常等级和栈,再释放该核。

在虚拟化场景下,从核的入口地址通常指向 Hypervisor 的次级核启动代码,而不是 Guest 内核。Hypervisor 在次级核上完成每核的虚拟化初始化(如设置 HCR_EL2、VTCR_EL2、每核的 vCPU 上下文),然后才把该核交给某个 vCPU 调度。因此,多核启动失败最常见的原因有三类:一是设备树中 CPU 节点与 PSCI 使能属性不匹配,导致 Hypervisor 找不到可唤醒的核;二是 BL31 的 PSCI 版本或 CPU 数量配置与实际芯片不符;三是从核入口地址被 Guest 镜像覆盖。

四、搭建虚拟化环境的实操要点

搭建时建议按“先裸机、再 ATF、后 Hypervisor”的顺序逐级验证,每一级都保留可观察的输出。第一步,确认 HSE 固件版本与安全启动策略:如果启用了安全启动,所有后续镜像都必须签名,否则 BootROM 会在校验阶段停止。第二步,编译 ATF 时确认 BL31 的 PSCI 实现和平台端口,S32G 的电源域、复位控制器与通用平台不同,需要对应的平台代码。第三步,U-Boot 中通过 bootargs 和 bootcmd 指定 Hypervisor 镜像与 Guest 配置,并确保 cpu-release-addr 指向 BL31 的 PSCI 入口。

调试建议:在 U-Boot 阶段用 md 查看 BL31 所在内存是否被改写,用 cpu detail 或平台命令确认各核状态;进入 Hypervisor 后,通过串口日志确认每个 vCPU 是否成功上线,再检查 Guest 是否在 EL1 正常启动。

五、启动顺序检查表

检查项期望结果异常表现
BootROM 启动模式从目标介质读取并验签通过无串口输出或停在 ROM 代码
HSE 固件安全核就绪,可提供验签后续镜像校验失败
BL2 → BL31BL31 常驻 EL3,PSCI 可用从核无法唤醒
U-Boot加载 HV 与 Guest 镜像镜像地址重叠、加载失败
HypervisorEL2 接管,创建 VMGuest 无法启动或反复复位
Guest OSEL1 运行,串口登录正常内核 panic 或卡在 earlycon