在早期的Cortex-M系列处理器(如M0、M3、M4)中,状态管理采用的是二维结构,包含两个核心要素:执行模式(线程模式与处理模式)和特权等级(特权与非特权)。这种架构设计简洁且运行高效,但随着系统安全需求的不断提升,其内在缺陷逐渐显现:
以Cortex-M4为例,其状态转换逻辑如下图所示。该线性二维模型已难以满足现代高安全性应用场景的需求,亟需引入更先进的架构范式。
复位
↓
特权处理模式 ←┐
↓ │
特权线程模式 │
↓ │
非特权线程模式 ┘
↑
异常返回
实现有效的安全隔离,本质上需要对处理器状态进行复制与隔离。然而,若采用简单的全状态复制方式,将带来以下问题:
针对此问题,TrustZone-M提出了创新解决方案——引入正交状态维度,通过有限维度的组合实现精准、高效的隔离控制。
TrustZone-M采用了三个相互正交的状态维度,各自独立地控制特定的安全属性:
这种设计具备显著优势:
选择哪几个维度作为正交基础,是经过深入分析与权衡的结果。最终确定使用上述三个核心维度,主要基于以下考虑:
整个处理器状态被组织为一个由安全、特权、执行三个维度构成的立方体空间,每个顶点代表一种唯一的状态组合。该结构提供了全局视角下的状态分布与转换路径。
通过将三维空间投影到不同平面上(如安全-特权平面、执行-特权平面等),可以更直观地理解各子系统的状态行为及其交互关系。
每个角点对应一组具体的(安全, 特权, 执行)配置,例如“安全+特权+线程”用于安全内核执行,“非安全+非特权+线程”用于普通应用运行。
安全世界与非安全世界的切换依赖于若干关键寄存器中的NS位(Non-Secure Bit),这些位分布在SCR、AIRCR等系统控制寄存器中,统一协调安全状态的一致性。
NS位不仅存在于SCR寄存器中,还贯穿于栈指针、MSP/PSP选择、中断目标设定等多个环节,确保整个执行上下文中安全属性的连贯性。
安全状态之间的切换受到严格限制,必须通过预定义的安全 gateway(SG指令)或安全异常入口完成,防止非法跳转。
特权等级由CONTROL寄存器中的nPRIV位控制:
关键设计在于:安全世界与非安全世界分别拥有独立的CONTROL寄存器(即CONTROL_S与CONTROL_NS),使得两者的特权控制互不干扰。
执行模式由硬件自动管理,无需软件干预:
特殊设计:处理模式下的安全属性由触发异常的安全特性决定——安全异常进入安全处理流程,非安全异常则进入非安全处理流程。
状态切换由一套复杂的有限状态机硬件逻辑实现,以下为概念性伪代码描述:
void handle_state_transition(TransitionEvent event) {
// 获取当前状态
current_state_t state = {
.security = SCR.NS ? NON_SECURE : SECURE,
.privilege = CONTROL.nPRIV ? UNPRIVILEGED : PRIVILEGED,
.mode = IPSR == 0 ? THREAD_MODE : HANDLER_MODE
};
switch (event.type) {
case EVENT_SG_INSTRUCTION:
// SG指令:实现从非安全世界调用安全世界
if (state.security != NON_SECURE) FAULT();
if (!is_valid_gateway(event.target)) FAULT();
// 保存返回信息至LR_S
LR_S = encode_exc_return(
.security = NON_SECURE,
.mode = THREAD_MODE,
.stack = state.stack_pointer
);
// 切换至安全状态
SCR.NS = 0;
state.security = SECURE;
// 执行模式与特权等级保持不变
break;
case EVENT_EXCEPTION_ENTRY:
// 异常进入:线程模式 → 处理模式
uint8_t exception_number = get_exception_number();
security_attribute_t target_security = get_exception_security(exception_number);
// 检查是否允许安全状态切换
...
break;
}
}
上述机制确保所有状态转换均符合安全策略,任何违规操作都将触发故障异常,保障系统完整性。
// 异常进入处理:通过硬件触发或软件指令进入
if (!can_switch_to(state, target_security, HANDLER_MODE)) {
FAULT();
}
// 硬件自动执行上下文保存
hardware_push_context(
.security = state.security,
.mode = state.mode,
.stack_pointer = get_current_sp()
);
// 更新处理器当前运行状态
state.mode = HANDLER_MODE;
state.privilege = PRIVILEGED; // 处理模式始终运行在特权级
// 若目标安全状态与当前不同,则更新SCR寄存器并切换安全域
if (target_security != state.security) {
SCR.NS = (target_security == NON_SECURE) ? 1 : 0;
state.security = target_security;
}
break;
case EVENT_EXCEPTION_RETURN:
// 处理异常返回流程,解析LR中的EXC_RETURN标识
exc_return_t exc_return = decode_exc_return(LR);
// 校验返回目标状态是否合法,防止非法跳转
if (!is_valid_return_target(state, exc_return)) {
FAULT();
}
// 由硬件从栈中恢复先前保存的上下文信息
hardware_pop_context(exc_return);
// 同步更新处理器三重状态
state.security = exc_return.security;
state.mode = exc_return.mode;
state.privilege = exc_return.privilege; // 权限等级从异常帧中还原
break;
}
在三维状态模型中,确保各状态组合的合法性是核心难点。硬件层面集成了多重边界校验机制以维持系统稳定:
切换序列:保存旧状态 → 更新状态寄存器 → 加载新上下文
↑___________________________________|
原子性保证:不可中断
鉴于状态切换对性能影响显著,Cortex-M33架构引入多项加速策略:
需要保存的上下文 = 共享寄存器 + 部分状态寄存器
不需要保存的 = bank化寄存器(自动切换)
// 浮点单元上下文按需保存
if (using_fpu && CONTROL_S.FPCA == 1) {
// 仅当FPU处于活跃状态时才执行保存
hardware_save_fpu_context();
}
// 其他情况下跳过浮点寄存器存储,提升响应速度
以Cortex-M33 r1p1版本为例,其内部状态寄存器的具体实现如下:
// 基于ARM官方文档定义的物理寄存器布局
typedef struct {
// 安全相关控制字段
union {
struct {
uint32_t NS:1; // Bit 0: 当前安全状态(0=安全, 1=非安全)
uint32_t ALLNS:1; // Bit 1: 初始安全配置锁定
uint32_t reserved:30;
};
uint32_t SCR; // 安全配置寄存器镜像
};
// 特权与执行控制(区分安全/非安全世界)
union {
struct {
uint32_t nPRIV:1; // Bit 0: 特权等级(0=特权, 1=非特权)
uint32_t SPSEL:1; // Bit 1: 栈指针选择(MSP/PSP)
uint32_t FPCA:1; // Bit 2: 浮点上下文活跃标志
uint32_t reserved:29;
};
uint32_t CONTROL;
} control_s, control_ns; // 分别对应安全和非安全CONTROL寄存器副本
// 当前中断服务状态
union {
struct {
uint32_t ISR_NUMBER:9; // Bits 0-8: 正在处理的异常编号
uint32_t reserved:23;
};
uint32_t IPSR; // 中断程序状态寄存器
};
} processor_state_registers;
设备完成安全启动后的常见状态初始化流程:
// 初始化处理器多维状态
void initialize_processor_states(void) {
// 第一阶段:复位后默认设置
// 初始安全状态由SAU_CTRL.ALLNS位或BLOCK_NS引脚决定
// 默认进入安全域、特权级、处理模式,并使用主栈指针(MSP)
// 第二阶段:安全世界初始化配置
// 设置SAU区域、启用MPU、配置安全例外向量等
}
// 阶段3:非安全世界的创建
__set_CONTROL_NS(0x02); // 设置为非安全、特权模式,使用MSP
__set_MSP_NS(ns_msp_top); // 初始化非安全主栈指针
__set_PSP_NS(ns_psp_top); // 设置非安全进程栈指针
// 阶段4:切换至非安全世界
// 利用EXC_RETURN的设置实现状态迁移
uint32_t exc_return = 0xFFFFFFFD; // 指示返回非安全线程模式,使用PSP
__TZ_set_CONTROL_NS(0x03); // 转换为非安全、非特权状态,启用PSP
__asm volatile("mov lr, %0" : : "r" (exc_return));
__asm volatile("bx %0" : : "r" (ns_reset_handler));
// 安全环境初始化(阶段1)
__set_CONTROL_S(0x00); // 配置为安全、特权级别,采用MSP
__set_PSP_S(secure_psp_top); // 安全进程栈顶初始化
__set_MSP_S(secure_msp_top); // 安全主栈顶初始化
基于某款实际芯片的测量结果如下:
| 切换类型 | 最小周期 | 最大周期 | 影响因素 |
|---|---|---|---|
| 同安全状态异常 | 12 | 18 | 压栈深度,FPU状态 |
| 跨安全状态异常 | 20 | 30 | 额外上下文保存 |
| SG指令调用 | 10 | 15 | 网关验证时间 |
| 异常返回 | 8 | 12 | 栈帧类型,浮点恢复 |
关键发现:跨安全状态切换带来的额外开销主要来源于以下两个方面:
三维状态模型显著提升了嵌入式系统在架构设计上的灵活性,具体体现在以下几个方面:
多样化的安全架构支持:
精细化的资源分配能力:
平滑的系统演进路径:
该模型为通过权威安全认证提供了坚实的技术基础:
三维模型为系统性能调优提供清晰指引:
此模型对未来的设计具有深远影响:
TrustZone-M的三维状态模型表明:
通过精心设计的正交状态空间,即便在有限的硬件复杂度下,也能实现强大的安全隔离能力。
这一设计理念不仅适用于Cortex-M系列处理器,更为整个嵌入式处理器架构的发展提供了重要参考。
复位
↓
特权处理模式 ←┐
↓ │
特权线程模式 │
↓ │
非特权线程模式 ┘
↑
异常返回
在接下来的章节中,将详细展示这一精巧的状态模型如何与内存管理系统、异常处理机制以及外设访问控制协同工作,共同构建一个兼具高安全性与高效能的嵌入式系统。各个组件充分利用三维状态所提供的细粒度控制能力,实现了安全防护与运行性能之间的理想平衡。
扫码加好友,拉您进群



收藏
