news 2026/6/24 2:13:51

TEE-OS学习轨迹第十七篇: 深入解析NS-EL1调用SMC的BL31异常处理流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TEE-OS学习轨迹第十七篇: 深入解析NS-EL1调用SMC的BL31异常处理流程

一、NS-EL1 调用 SMC 时,BL31 内部的异常入口与路由

基于 runtime_exceptions 异常向量表,NS-EL1(AArch64 非安全内核态)执行 SMC 指令后,会严格按照以下路径在 BL31 内部完成异常入口与分发。

1. 异常向量入口命中

ARMv8 异常向量表按「当前异常级别 + 栈指针 + 低级别架构」分为 4 组,每组 4 个异常类型。NS-EL1 属于「低于 EL3 的 AArch64 异常级别」,触发同步异常(SMC 属于同步异常)时,固定命中:
.globl sync_exception_aarch64 .globl irq_aarch64 .globl fiq_aarch64 .globl serror_aarch64 vector_entry sync_exception_aarch64 // 0x400 ~ 0x600 区间:Lower EL using AArch64 的同步异常

2. 向量入口前置处理

进入 sync_exception_aarch64 后,依次执行 4 步前置操作:
vector_entry sync_exception_aarch64 /* * This exception vector will be the entry point for SMCs and traps * that are unhandled at lower ELs most commonly. SP_EL3 should point * to a valid cpu context where the general purpose and system register * state can be saved. */ save_x30 // 1. 保存 LR(x30) 到 CPU 上下文,释放 x30 给后续逻辑使用 apply_at_speculative_wa // 2. 执行推测执行漏洞硬件缓解补丁 sync_and_handle_pending_serror // 3. 同步错误,检查待处理 SError,按 FFH/KFH 模式处理或反射 unmask_async_ea // 4. 取消异步外部中止屏蔽,允许 EL3 处理异步错误 handle_sync_exception // 进入同步异常分发核心逻辑 end_vector_entry sync_exception_aarch64

3. 同步异常类别(EC)判断

在 handle_sync_exception 宏中,读取 ESR_EL3 寄存器提取异常类别 EC,按类型分流:
.macro handle_sync_exception #if ENABLE_RUNTIME_INSTRUMENTATION /* * Read the timestamp value and store it in per-cpu data. The value * will be extracted from per-cpu data by the C level SMC handler and * saved to the PMF timestamp region. */ mrs x30, cntpct_el0 str x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] mrs x29, tpidr_el3 str x30, [x29, #CPU_DATA_PMF_TS0_OFFSET] ldr x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] #endif mrs x30, esr_el3 ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH // 提取 EC 字段 /* Handle SMC exceptions separately from other synchronous exceptions */ cmp x30, #EC_AARCH32_SMC b.eq smc_handler32 // 32位SMC → smc_handler32 cmp x30, #EC_AARCH64_SMC b.eq sync_handler64 cmp x30, #EC_AARCH64_SYS b.eq sync_handler64 // 64位SMC → sync_handler64 cmp x30, #EC_IMP_DEF_EL3 b.eq imp_def_el3_handler
NS-EL1(AArch64)发起的 SMC,EC 值为 EC_AARCH64_SMC,因此跳转到 sync_handler64,进入 SMC 运行时服务分发逻辑。

4. SMC 运行时服务分发(核心路由)

sync_handler64 位于 sync_exception_handler 函数内,是所有 AArch64 SMC 的统一分发入口,流程如下:
sync_handler64: /* NOTE: The code below must preserve x0-x4 */ /* * Save general purpose and ARMv8.3-PAuth registers (if enabled). * Also save PMCR_EL0 and set the PSTATE to a known state. */ bl prepare_el3_entry #if ENABLE_PAUTH /* Load and program APIAKey firmware key */ bl pauth_load_bl31_apiakey #endif /* * Populate the parameters for the SMC handler. * We already have x0-x4 in place. x5 will point to a cookie (not used * now). x6 will point to the context structure (SP_EL3) and x7 will * contain flags we need to pass to the handler. */ mov x5, xzr mov x6, sp /* * Restore the saved C runtime stack value which will become the new * SP_EL0 i.e. EL3 runtime stack. It was saved in the 'cpu_context' * structure prior to the last ERET from EL3. */ ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] /* Switch to SP_EL0 */ msr spsel, #MODE_SP_EL0 /* * Save the SPSR_EL3 and ELR_EL3 in case there is a world * switch during SMC handling. * TODO: Revisit if all system registers can be saved later. */ mrs x16, spsr_el3 mrs x17, elr_el3 stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] /* Load SCR_EL3 */ mrs x18, scr_el3 /* check for system register traps */ mrs x16, esr_el3 ubfx x17, x16, #ESR_EC_SHIFT, #ESR_EC_LENGTH cmp x17, #EC_AARCH64_SYS b.eq sysreg_handler64 /* Clear flag register */ mov x7, xzr #if ENABLE_RME /* Copy SCR_EL3.NSE bit to the flag to indicate caller's security */ ubfx x7, x18, #SCR_NSE_SHIFT, #1 /* * Shift copied SCR_EL3.NSE bit by 5 to create space for * SCR_EL3.NS bit. Bit 5 of the flag corresponds to * the SCR_EL3.NSE bit. */ lsl x7, x7, #5 #endif /* ENABLE_RME */ /* Copy SCR_EL3.NS bit to the flag to indicate caller's security */ bfi x7, x18, #0, #1 mov sp, x12 /* * Per SMCCC documentation, bits [23:17] must be zero for Fast * SMCs. Other values are reserved for future use. Ensure that * these bits are zeroes, if not report as unknown SMC. */ tbz x0, #FUNCID_TYPE_SHIFT, 2f /* Skip check if its a Yield Call*/ tst x0, #(FUNCID_FC_RESERVED_MASK << FUNCID_FC_RESERVED_SHIFT) b.ne smc_unknown /* * Per SMCCCv1.3 a caller can set the SVE hint bit in the SMC FID * passed through x0. Copy the SVE hint bit to flags and mask the * bit in smc_fid passed to the standard service dispatcher. * A service/dispatcher can retrieve the SVE hint bit state from * flags using the appropriate helper. */ 2: and x16, x0, #(FUNCID_SVE_HINT_MASK << FUNCID_SVE_HINT_SHIFT) orr x7, x7, x16 bic x0, x0, #(FUNCID_SVE_HINT_MASK << FUNCID_SVE_HINT_SHIFT) /* Get the unique owning entity number */ ubfx x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTH ubfx x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTH orr x16, x16, x15, lsl #FUNCID_OEN_WIDTH /* Load descriptor index from array of indices */ adrp x14, rt_svc_descs_indices add x14, x14, :lo12:rt_svc_descs_indices ldrb w15, [x14, x16] /* Any index greater than 127 is invalid. Check bit 7. */ tbnz w15, 7, smc_unknown /* * Get the descriptor using the index * x11 = (base + off), w15 = index * * handler = (base + off) + (index << log2(size)) */ adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE) lsl w10, w15, #RT_SVC_SIZE_LOG2 ldr x15, [x11, w10, uxtw] /* * Call the Secure Monitor Call handler and then drop directly into * el3_exit() which will program any remaining architectural state * prior to issuing the ERET to the desired lower EL. */ #if DEBUG cbz x15, rt_svc_fw_critical_error #endif blr x15 b el3_exit

1.上下文保存:调用 prepare_el3_entry,将 NS 世界的通用寄存器、PAuth 寄存器完整保存到 CPU 上下文结构

2.栈切换:从 SP_EL3(异常专用栈)切换到 SP_EL0(EL3 C 语言运行时栈),为调用 C 函数做准备

2.参数封装:保留 x0~x4 的 SMC 入参,x6 指向 CPU 上下文,x7 携带安全状态、SVE 提示等标志位

4.服务索引计算

ubfx x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTH // 提取 SMC FID 的 OEN(所属服务组) ubfx x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTH // 提取调用类型:Fast / Yielding orr x16, x16, x15, lsl #FUNCID_OEN_WIDTH // 组合成服务索引

5.查表分发

adrp x14, rt_svc_descs_indices ldrb w15, [x14, x16] // 从索引表查对应服务的描述符下标 adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE) lsl w10, w15, #RT_SVC_SIZE_LOG2 ldr x15, [x11, w10, uxtw] // 取出对应服务的 handler 函数指针 blr x15 // 调用对应运行时服务的处理函数

6.异常返回:服务处理完成后,调用 el3_exit 恢复上下文,通过 ERET 指令返回 NS-EL1。

二、从 BL31 路由到 OP-TEE 运行实体的链路

OP-TEE(BL32)运行在S-EL1(安全 EL1),NS-EL1 无法直接跳转访问,必须经过 EL3 的安全监视器BL31(ATF )做「世界切换」。承担这个转发角色的,是 ATF 内置的OP-TEE SPD(Secure Payload Dispatcher,简称 opteed)

1. opteed 的注册:预先绑定 SMC 范围

opteed 在 BL31 启动阶段,通过 DECLARE_RT_SVC 宏向运行时服务框架注册了两个服务实例:
// 快速 SMC 服务:不可中断,用于简单控制指令 DECLARE_RT_SVC( optee_fast, OEN_TOS_START, OEN_TOS_END, // OEN 范围:50 ~ 63(SMCCC 规定的 Trusted OS 组) SMC_TYPE_FAST, opteed_setup, opteed_smc_handler ); // 标准 Yielding SMC 服务:可中断挂起,用于 TA 调用等复杂业务 DECLARE_RT_SVC( optee_std, OEN_TOS_START, OEN_TOS_END, SMC_TYPE_YIELD, NULL, opteed_smc_handler );
对应 SMCCC 规范,所有发往可信操作系统的 SMC,Function ID 的 OEN 字段(bit29:24)都属于 50~63 范围。因此 NS-EL1 发起的 OP-TEE 相关 SMC,都会被上一步的分发逻辑路由到 opteed_smc_handler 函数。

2. NS → OP-TEE 的世界切换流程

opteed_smc_handler 收到请求后,负责完成「非安全世界 → 安全世界」的上下文切换与跳转,核心步骤:
(1)确认 NS 上下文已归档
前面 prepare_el3_entry 已经把 NS-EL1 的完整寄存器状态、系统寄存器都存入了NS 上下文结构体,opteed 只需确认上下文位置,无需重复保存。
(2)切换到 OP-TEE 安全上下文
每个 CPU 都维护两套独立的上下文:NS(非安全)和 S(安全)。opteed 从 per-CPU 的 opteed_sp_context 中,取出 OP-TEE 的 S-EL1 上下文,替换当前的上下文指针。这套上下文在 OP-TEE 初始化完成时就已保存,包含 OP-TEE 的栈指针、页表基址、异常向量基址等完整运行状态。
(3)配置返回目标与安全状态
opteed 修改上下文结构体中的关键字段,决定 el3_exit 后 CPU 的去向:
  • SCR_EL3.NS = 0:标记 ERET 后进入安全世界
  • ELR_EL3 = OP-TEE SMC 入口:指向 OP-TEE 内部的 SMC 向量表(如 vector_std_smc_entry / vector_fast_smc_entry)
  • SPSR_EL3:配置为 S-EL1 特权级、EL1h 栈模式、开中断等运行状态
  • x0~x4:原样保留 SMC 参数,透传给 OP-TEE
(4)el3_exit 完成最终跳转
opteed_smc_handler 返回后,sync_handler64 调用 el3_exit。此时上下文已替换为安全世界的快照,el3_exit 执行:
  1. 从上下文恢复 S-EL1 的所有通用寄存器、系统寄存器
  2. 配置 SCR_EL3.NS = 0 切换安全状态
  3. 执行 ERET 指令,CPU 从 EL3 退出,跳转到 OP-TEE 的 S-EL1 异常向量入口

补充:两类 SMC 的差异

  • Fast SMC:关中断执行,不支持挂起,用于简单操作(如版本查询、状态控制),全程不涉及 OP-TEE 线程调度
  • Yielding SMC:开中断执行,支持线程挂起与 RPC 交互,是业务层 TA 调用、加密服务的主路径,也是最常用的类型

三、初始化阶段的关联

BL31 启动时会通过 opteed 加载并启动 BL32(OP-TEE),OP-TEE 初始化完成后通过 TEESMC_OPTEED_RETURN_ENTRY_DONE 这个 SMC 返回 EL3,opteed 会保存 OP-TEE 的向量表基地址,后续所有 SMC 请求都固定转发到该入口。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/24 2:13:28

青年长江答辩PPT 3大致命坑 避开直接提分

青年CJ属于国家级高层次人才项目&#xff0c;答辩 PPT 核心评审逻辑&#xff1a;学术潜力突出、平台匹配度高、育人成效扎实、未来规划可行&#xff0c;很多申报人栽在内容逻辑、视觉呈现、答辩适配三类问题&#xff0c;中科致研结合多年深耕科研领域可视化经验&#xff0c;整理…

作者头像 李华
网站建设 2026/6/24 2:10:17

五眼联盟警告:AI网络攻击或在数月内成真

西方情报机构近日发出警告&#xff0c;强大的AI模型可能在数月内被用于发动网络攻击&#xff0c;这将使各国政府和企业面临更大的安全风险。五眼联盟网络安全机构的负责人——来自英国、美国、加拿大、澳大利亚和新西兰的情报官员——今日联合发出警告&#xff0c;称"前沿…

作者头像 李华
网站建设 2026/6/24 2:09:13

048、从MemRef到LLVM的最终降级路径

048、从MemRef到LLVM的最终降级路径 昨晚调试一个MLIR生成的向量化代码,跑在RISC-V开发板上,发现内存访问总是错位。GDB进去一看,MemRef的offset计算完全不对——明明是个二维数组的连续内存,结果每次load都跳到奇怪的位置。折腾到凌晨两点,最后发现是MemRef降级到LLVM时…

作者头像 李华
网站建设 2026/6/24 2:04:19

灯箱制作公司怎么选?内行人揭秘关键考量因素

在商业标识与户外广告领域&#xff0c;灯箱制作公司是连接品牌展示需求与实体落地执行的关键服务方。无论是连锁门店的门头升级&#xff0c;还是独立商铺的招牌安装&#xff0c;选择一家合适的灯箱制作公司直接关系到最终呈现效果、使用耐久度以及后期维护成本。本文从行业实操…

作者头像 李华
网站建设 2026/6/24 2:02:10

企业云盘选型避坑指南:5个中小团队最容易踩的文档管理误区

企业云盘选型避坑指南:5个中小团队最容易踩的文档管理误区 企业在选择云盘产品时&#xff0c;IT 负责人最头疼的不是功能不够用&#xff0c;而是"功能用了等于没用"。尤其是中小团队&#xff0c;人员精简、分工模糊&#xff0c;一个人往往同时是管理员、使用者、外部…

作者头像 李华
网站建设 2026/6/24 1:58:59

ATAES132加密芯片电源管理与状态切换实战指南

1. 项目概述&#xff1a;为什么我们需要关注加密芯片的“心跳”&#xff1f;在嵌入式安全领域&#xff0c;ATAES132这颗芯片对很多开发者来说并不陌生。它是一款硬件加密芯片&#xff0c;常被用于物联网设备、支付终端、版权保护等场景&#xff0c;负责安全地存储密钥、执行加解…

作者头像 李华