想象你走进一栋 30 层的科技大厦。访客临时卡只能到一楼大厅;正式员工的卡能刷开 2-12 层的办公室;安保主管的卡多了一把监控室钥匙;而 CEO 的卡还能打开地下 B2 的保险库。这座大厦的设计师早就规定:每一级人只能去自己权限对应的楼层,想去更高层,必须通过电梯旁的呼叫机请求楼上的管理员来“带人”。现代 ARM 芯片就像一个微型大厦,它的四级门禁编号为 EL0、EL1、EL2、EL3。你手机里每一款 App 都住在 EL0 大厅,操作系统管家在 EL1 办公室,虚拟机监控器在 EL2 监控室里巡视整栋楼,而 EL3 的保险库藏着最敏感的密钥——连操作系统都不能触碰。这一切,就是 ARM 架构最核心的安全地基:特权级。理解了“哪级能去哪里、怎么进门、怎么出门”,你就看懂了系统安全与虚拟化的骨架。

岗位关联

特权级是理解 ARM 汇编、系统内核与 TrustZone 安全方案的钥匙;掌握 EL0-EL3 的切换规则,是从事固件、虚拟化与安全开发的硬性门槛。

目录
  1. 可视化演示
  2. 特权级总体架构
  3. EL0用户态
  4. EL1内核态
  5. EL2虚拟化
  6. EL3安全监控
  7. 异常级别转换
  8. 安全设计实践
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示AArch64四个异常级别EL0-EL3的权限层次、SVC/HVC/SMC/ERET指令触发的异常切换流程、以及TrustZone通过EL3实现安全世界与普通世界的隔离切换。

本节配有交互动效(进入视口后自动加载,约 3KB)。

ARM异常级别层次 EL0用户态权限最低,EL3安全监控权限最高 每级拥有独立系统寄存器集 EL_n → EL_m via SVC/HVC/SMC 异常级别转换由特定指令触发

特权级总体架构

想象你走进一座叫 ARM 大厦的摩天楼。电梯里的按钮不是每一层都亮着:访客临时卡只能按亮大厅层,正式员工卡能按亮办公层,安保主管卡能按亮监控层,而 CEO 的卡还能按亮地下保险库。ARM 芯片内部就是这样一座大厦,只是它的“楼层”只有四个,编号叫 EL0、EL1、EL2、EL3。

这四个编号对应真实系统里的四大角色:EL0 是普通应用(App、浏览器、算法库),EL1 是操作系统内核(Linux、Android、RTOS),EL2 是虚拟机监控器(Hypervisor、KVM),EL3 是安全监控固件(TrustZone ATF、TEE)。数字越大,能触碰的硬件资源越多,能下的“命令”越底层。

ARMv8-A 架构在设计时就规定好了一个全局排序:EL3 最大,EL0 最小。这个排序不是概念上的“强弱”,而是实实在在的硬件隔离:高特级可以访问低特级的资源,反过来则不行。比如内核可以看应用的页表,应用却碰不到内核的一行数据结构。

这就像电梯按钮的规则:拿着管理员的卡,你能到 1 楼到 12 楼的所有办公层;而拿着访客卡,连办公层的走廊都进不去。ARM 大厦正是靠这道看不见的“电梯规则”,把恶意程序死死挡在门外。

EL3>EL2>EL1>EL0\displaystyle EL_3 > EL_2 > EL_1 > EL_0
这个式子像一个门禁等级表:右边的层级能进的门,左边的层级都能进;反过来则被电梯拦截。
  1. ELx 符号EL 是 Exception Level 的缩写,x 是 0 到 3 的整数,代表异常级别编号,数字越大权限越高。
    ELx,x∈{0,1,2,3}EL_x, \quad x \in \{0, 1, 2, 3\}
  2. 大于号的语义这里的“大于”表示资源支配关系的方向,高特级拥有低特级的全部访问权。
    ELi+1>ELi  ⟹  Perm(ELi)⊆Perm(ELi+1)EL_{i+1} > EL_i \implies \text{Perm}(EL_i) \subseteq \text{Perm}(EL_{i+1})
  3. 不等号链的传递性整个链条说明特权级是一个全序关系,EL3 位于所有级联权限的顶端。
    ELa>ELb∧ELb>ELc  ⟹  ELa>ELcEL_a > EL_b \land EL_b > EL_c \implies EL_a > EL_c

EL0用户态

访客拿着临时卡走进 ARM 大厦,活动范围只限一楼大厅:那里有沙发、绿植和一台公用的自动售货机。访客想去 3 楼的财务室,门禁会亮红灯,除非他按响前台的服务铃,让管理员下来带他上去。EL0 就是这个“访客层”。

EL0 是四个特权级里权限最低、但运行代码最多的一层。你手机上所有 App、后台服务、机器学习推理框架都跑在 EL0。它们看不见内核页表,写不了硬件寄存器,也读不了其他 App 的私密内存。这一切由 MMU(内存管理单元)的页表权限位(AP 位)保证:EL0 只能访问标记为“用户可读”的页。

当 App 确实需要内核帮忙——打开摄像头、读取文件、申请内存——它不能直接操作,而是执行一条 SVC 指令。SVC 会制造一个同步异常,像访客按响服务铃一样,把控制权“陷”进 EL1,由内核代表它执行那些高权限操作。这个“按铃”机制,就是系统调用(syscall)的硬件底座。

访客永远借不到管理员的卡,只能借管理员的手。这就是 EL0 的设计哲学:你可以请求能力,但不能持有能力。

SVCcall:EL0→系统调用EL1\displaystyle SVC_{\text{call}}: \quad EL_0 \xrightarrow{\text{系统调用}} EL_1
SVC 就是访客按铃的动作:自己上不去,呼叫管理员下来处理。
  1. SVC 指令SVC 是 Supervisor Call 的缩写,执行后会触发一个同步异常,把当前处理器从 EL0 抬升到 EL1。
    SVCcallSVC_{\text{call}}
  2. 箭头方向箭头表示控制权转移方向,从低特权级指向高特权级,方向永远向上。
    EL0→EL1,∄ 从 EL1 向 EL0 的 SVCEL_0 \rightarrow EL_1, \quad \nexists \text{ 从 EL1 向 EL0 的 SVC}
  3. 结果含义经过这次转移,CPU 已经在内核态代表 App 运行,但返回时必须用后续要讲的 ERET 降回来。
    After: ELcurrent=EL1\text{After: } EL_{\text{current}} = EL_1

EL1内核态

ARM 大厦的 2 到 12 层是物业办公区。物业管理员拿着员工卡,能打开每一间办公室的门,能更换灯泡、检修水管、处理报警。但他们也有进不去的地方:中央监控室和地下保险库。EL1 就是这位“物业管理员”。

操作系统内核(Linux、Android、鸿蒙等)运行在 EL1。它负责页表管理(虚拟地址到物理地址的映射)、进程调度、中断处理和设备驱动。EL0 层的所有 App 都要向它申请资源,所以 EL1 的代码质量直接决定了整个系统的稳定性。一旦内核崩溃,蓝屏是轻的,整个设备直接宕机。

内核不是无条件让任何人进来的。当异常发生时,硬件会根据目标特权级和当前特权级做一次判定:如果目标 EL 严格大于当前 EL,异常入口才生效;否则异常会被拒绝或按非法操作处理。这个判定公式如下。

物业管理员能修水管,但修不了监控主机的电路——那不是他的权限范围。EL1 也一样:它能管理整个用户态,但对虚拟化和安全隔离世界的干预,必须交给更高的层。

EntryEL1={1if ELtarget>ELcurrent0otherwise\displaystyle \text{Entry}_{EL1} = \begin{cases} 1 & \text{if } EL_{\text{target}} > EL_{\text{current}} \\ 0 & \text{otherwise} \end{cases}
这是一个门禁闸机:只有“向上走”的请求才会被放行进内核,横向或向下的请求直接亮红灯。
  1. Entry 变量表示“这次异常是否允许进入目标特权级”的布尔结果,1 放行,0 拒绝。
    EntryEL1∈{0,1}\text{Entry}_{EL1} \in \{0, 1\}
  2. 比较条件异常进入的前提是目标层级严格高于当前层级。
    ELtarget>ELcurrentEL_{\text{target}} > EL_{\text{current}}
  3. 分支语义条件成立时处理器携带异常向量跳转到 EL1 入口,不成立时行为如同未触发。
    ELtarget>ELcurrent→PC←VBAR_EL1+offsetEL_{\text{target}} > EL_{\text{current}} \rightarrow \text{PC} \leftarrow \text{VBAR\_EL1} + \text{offset}

EL2虚拟化

ARM 大厦的 13 层是中央监控室。安保主管坐在一整面监视墙前,能看到每一层走廊的实时画面。某个区域出现异常时,他能通过遥控器切换监控视角、封锁闸机门。但他并不需要亲自去那层楼。EL2 就是这位“安保主管”。

虚拟机监控器(Hypervisor)运行在 EL2,它管理着多个“Guest 系统”。每个 Guest 由一台客户操作系统(运行在 EL1)和一堆客户应用(运行在 EL0)组成。当 Guest 想执行特权操作——比如改写页表、关中断、操作定时器——Hypervisor 可以决定“放行”还是“拦截”。

这个拦截动作叫 trap(陷入)。硬件会把 Guest 的敏感指令截获并路由到 EL2,由 Hypervisor 决定下一步。trap 是否发生由配置寄存器 HCR_EL2 等决定。一个典型的 trap 条件可以写成下面的公式。

监控室里的安保主管不需要亲身下楼,一个按钮就能控制整栋楼的走廊。虚拟化的美妙也在这里:多个操作系统共享一台物理机,却彼此毫不知情。

Trap=(ELguest<EL2)∧(HCR_EL2[TGE]=0)\displaystyle \text{Trap} = \left( EL_{\text{guest}} < EL_2 \right) \land \left( HCR\_EL2[\text{TGE}] = 0 \right)
监控室的自动报警逻辑:只要访客出现在不该出现的楼层(低于 EL2),且报警开关开启(TGE=0),监控就会截获画面。
  1. Trap 变量表示敏感操作是否被虚拟化层截获,1 表示陷入 EL2,0 表示放行。
    Trap∈{0,1}\text{Trap} \in \{0, 1\}
  2. 第一条件Guest 的当前特权级必须低于 EL2,常见情况是 EL1 的 Guest 内核或 EL0 的 Guest 应用。
    ELguest<EL2EL_{\text{guest}} < EL_2
  3. 第二条件HCR_EL2 是 EL2 的虚拟化配置寄存器,TGE 位为 0 时允许把 Guest 的异常 trap 到 EL2。
    HCR_EL2[TGE]=0HCR\_EL2[\text{TGE}] = 0
  4. 逻辑与门两个条件同时成立才会触发 trap,任何一个不满足,操作直接下放给 Guest。

EL3安全监控

ARM 大厦有个秘密:地下 B2 层有一个从未画在楼层导览图上的保险库。只有极少数人知道它的存在,普通员工以为大楼只有 15 层。保险库大门由 CEO 和首席安保官双重认证控制,里面存放着整栋大楼的备用钥匙、加密证书和紧急预案。EL3 就是这座“秘密保险库”。

EL3 是 ARM 特权级的最高层,它的核心使命是管理 TrustZone——一个把芯片切成两个平行世界的机制:普通世界(Normal World)运行常规操作系统,安全世界(Secure World)运行可信固件(如 OP-TEE、Trusted Firmware)。两个世界共享 CPU,但资源被物理隔离:安全世界的内存,普通世界无论如何都读不到。

从普通世界进入安全世界,只能通过一条指令:SMC(Secure Monitor Call)。执行 SMC 后,处理器陷入 EL3,由 EL3 固件完成世界切换后,再以降级的方式把控制权交给安全世界中的某个 EL1 系统。EL3 本身就是世界切换的不可绕过仲裁者,因此被称为信任根(Root of Trust)。

保险库的秘密不在于钥匙多坚固,而在于它的存在本身就被隐藏了。TrustZone 的威力也是如此:攻击者就算攻陷了普通世界的操作系统,也根本看不到安全世界的地图。

SMC:NS_EL1→EL3 仲裁S_EL1\displaystyle SMC: \quad NS\_EL1 \xrightarrow{\text{EL3 仲裁}} S\_EL1
这就是通往保险库的唯一电梯:按下 SMC 按钮,在 EL3 完成身份核验后,电梯才把你送到安全世界。
  1. SMC 指令SMC 是 Secure Monitor Call 的缩写,触发后陷入 EL3,是普通世界进入安全世界的唯一入口。
    SMCcall:∀EL<EL3SMC_{\text{call}}: \forall EL < EL_3
  2. NS 与 S 标记NS 表示普通世界(Normal World),S 表示安全世界(Secure World),箭头表示控制权移交方向。
    NS_EL1≠S_EL1NS\_EL1 \neq S\_EL1
  3. EL3 仲裁世界切换必须由 EL3 完成,EL3 是天生的信任根,掌握最高裁决权。
    EL3=Root of Trust,∄ bypass\text{EL}_3 = \text{Root of Trust}, \quad \nexists \text{ bypass}

异常级别转换

现在你已经走遍了大厦的四个楼层,是时候聊聊“怎么上楼、怎么下楼”的完整流程了。去高特级层必须走“异常通道”:按下电梯旁的呼叫按钮(SVC/HVC/SMC),中央控制台验证你的身份,然后电梯把你带上去。而下来时,ARM 设计了一个专门的“下行电梯”——ERET 指令。

进入异常时,硬件会悄悄做两件事:把返回地址存进 ELR_ELx 寄存器,把当时的处理器状态存进 SPSR_ELx 寄存器。这两个寄存器就像电梯里的“楼层记忆卡”:它记着你从哪层上来、以什么身份上来。等任务处理完毕,一条 ERET 指令就会取出这些信息,把程序计数器(PC)和处理器状态精确恢复到异常发生前的样子。

注意 ERET 恢复的不是“当前电梯所在的楼层”,而是“你原来所在的那一层”。比如一个 EL1 内核代码调用 SMC 进入 EL3 办事,ERET 回到的是 EL1,而不是一路降到 EL0。这正是 SPSR 中保存的状态字段决定的。

这就像你从办公室坐电梯到监控室汇报问题,汇报结束按 ERET,电梯把你送回办公室空调房——绝不会好心把你送回一楼大厅吹冷风。

ERET:PC←ELR_ELx,PSTATE←SPSR_ELx\displaystyle ERET: \quad PC \leftarrow ELR\_ELx, \quad PSTATE \leftarrow SPSR\_ELx
ERET 是电梯的下行按钮:一切以“楼层记忆卡”为准,从哪层上来的,就回哪层去。
  1. PC 恢复程序计数器 PC 从 ELR_ELx 中取出异常发生前的下一条指令地址。
    PC←ELR_ELxPC \leftarrow ELR\_ELx
  2. PSTATE 恢复处理器状态 PSTATE 从 SPSR_ELx 中还原,包括异常屏蔽位和之前的特权级。
    PSTATE←SPSR_ELxPSTATE \leftarrow SPSR\_ELx
  3. 整体语义ERET 一次性完成“回到哪里”和“以什么身份执行”两个恢复动作。
    ELreturn=SPSR_ELx[M]EL_{\text{return}} = SPSR\_ELx[\text{M}]

安全设计实践

大厦运营十年后,安保团队总结出一套制度:每张门禁卡只开通该员工工作必需的楼层,临时访客必须登记证件并由专人陪同,维修工进机房必须有主管在旁监督,同时要定期演练以平衡“查得太严影响办公效率”与“查得太松导致安全隐患”。这套制度的原则同样适用于 ARM 特权级的使用。

最小特权原则是特权级设计的黄金法则:每个软件组件运行时,只应该获得它完成任务所需的最低特权级。比如闹钟 App 只需要 EL0,绝不该被授权操作 EL1 的驱动;某个只做浮点计算的固件模块,就不该被放到 EL3。权限越大,一旦漏洞被利用,爆炸半径就越大。

ARM 的硬件对“访问”的定义也严格遵循一个判定公式:当前代码所在的特权级必须不低于资源要求的最低特权级。这就像员工卡上印着“可进入楼层范围”,刷卡时闸机自动核对,而不是靠员工自觉。

ARM 大厦的安保制度说到底就一句话:权限是借来的,不是拥有的。给每个程序发一张刚好够用的门禁卡,让攻击者拿到任何一张卡都只能进入一小块区域——这就是特权级设计最终极的智慧。

Access=TRUE  ⟺  ELcurrent≥ELrequired\displaystyle \text{Access} = \text{TRUE} \iff EL_{\text{current}} \ge EL_{\text{required}}
每次访问都是一次刷卡验证:你的楼层等级够高,门才开;不够,硬闯就会被拦截。
  1. Access 结果表示访问是否被允许的布尔值,TRUE 放行,FALSE 拒绝。
    Access∈{TRUE,FALSE}\text{Access} \in \{\text{TRUE}, \text{FALSE}\}
  2. 比较条件当前执行环境的特权级必须不小于资源要求的最低特权级。
    ELcurrent≥ELrequiredEL_{\text{current}} \geq EL_{\text{required}}
  3. 当且仅当语义这个条件是充要条件,不存在“特殊通道”“内部关系”之类的例外。
      ⟺   表示双向蕴含\iff \text{ 表示双向蕴含}

AI 应用场景

手机 App 沙箱与隐私保护

阶段:数据获取与隐私保护

解决的问题:AI 类 App 需要读取相册、通讯录和传感器数据,传统做法是给应用最高权限导致隐私泄露甚至系统被攻陷。ARM 特权级将 App 限制在 EL0,所有敏感操作必须通过内核(EL1)审核,即使应用被攻破,攻击者也看不到内核和别的 App 内存。

具体案例:一款人脸识别 App 在 EL0 采集摄像头帧,通过 Android 的 Binder 系统调用(SVC 陷入 EL1)读取媒体数据。相机驱动运行在 EL1,指纹等密钥运算则交给 EL3 的 TEE。App 的一次崩溃,不会把整个 Android 内核拖下水。

云服务器多租户隔离

阶段:模型训练集群资源隔离

解决的问题:AI 训练要租用云 GPU 服务器,多租户共享物理机,恶意租户可能通过旁路攻击或内核漏洞探测其他租户的模型参数。EL2 Hypervisor 配合 stage-2 页表做二次地址翻译,让每个 Guest 都以为自己在独占整台机器。

具体案例:某云厂商的 ARM 实例使用 KVM 在 EL2 运行 Hypervisor,每个训练任务跑在一个独立的 Guest OS 中(EL1)。当 Guest 尝试执行特权指令时,Hypervisor 在 EL2 拦截并模拟,同时 stage-2 页表保证 Guest 无法访问邻居的内存物理页。

移动支付与生物识别密钥保护

阶段:敏感密钥与模型保护

解决的问题:支付密钥、人脸特征模型是 AI 应用中最敏感的数据,一旦设备被 root 就可能被提取。TrustZone 在 EL3 建立安全世界,把所有密钥运算放进去,普通世界的系统即使被完全攻破,也无法读取安全世界内存。

具体案例:手机厂商在 EL3 的 OP-TEE 中运行指纹比对算法。用户解锁时,普通世界的指纹驱动通过 SMC 调用进入安全世界,在隔离内存里完成特征比对后只返回一个“成功/失败”结果。密钥全程不落地到普通世界。

Python 演示

python77 行
"""ARM 特权级 (EL0-EL3) 门禁模拟器 模拟异常级别之间的权限升降规则:- EL0 用户态: 应用运行, 只能发起 SVC 系统调用- EL1 内核态: 操作系统, 可发起 HVC 虚拟化调用- EL2 虚拟化: Hypervisor, 可发起 SMC 安全调用- EL3 安全态: 安全监控, 只能通过 ERET 逐级返回"""  class PrivilegeLevel:    """模拟一个虚拟 CPU 的当前特权级与转换指令"""     NAMES = ["EL0", "EL1", "EL2", "EL3"]     def __init__(self):        # 初始态: 模拟系统启动完成后, 应用回到 EL0        self._level = 0        self.svc_count = 0        self.hvc_count = 0        self.smc_count = 0        self.eret_count = 0     @property    def current(self):        return self.NAMES[self._level]     def svc(self):        """系统调用: EL0 -> EL1, 请求内核服务"""        if self._level != 0:            return "SVC 被忽略: 需处于 EL0"        self._level = 1        self.svc_count += 1        return "SVC 成功: 陷入 EL1 内核态"     def hvc(self):        """虚拟化调用: EL1 -> EL2, 请求虚拟机监控器"""        if self._level != 1:            return "HVC 被忽略: 需处于 EL1"        self._level = 2        self.hvc_count += 1        return "HVC 成功: 陷入 EL2 虚拟化层"     def smc(self):        """安全监控调用: EL2 -> EL3, 进入安全世界"""        if self._level != 2:            return "SMC 被忽略: 需处于 EL2"        self._level = 3        self.smc_count += 1        return "SMC 成功: 到达 EL3 安全监控层"     def eret(self):        """异常返回: 逐级降回低特权级"""        if self._level == 0:            return "ERET 无效: 已在 EL0 最低层"        self._level -= 1        self.eret_count += 1        return "ERET 返回: 降到 " + self.NAMES[self._level]  def run_demo():    cpu = PrivilegeLevel()    print("初始层级:", cpu.current)    print(cpu.svc())    print(cpu.hvc())    print(cpu.smc())    print("非法场景:", cpu.svc())    print(cpu.eret())    print(cpu.eret())    print(cpu.eret())    print("非法场景:", cpu.eret())    print("统计: SVC=%d HVC=%d SMC=%d ERET=%d"          % (cpu.svc_count, cpu.hvc_count, cpu.smc_count, cpu.eret_count))  if __name__ == "__main__":    run_demo()
目的:用一个小型状态机模拟 ARM 四级特权级之间通过 SVC/HVC/SMC 上升、通过 ERET 下降的门禁规则。
  1. NAMES = ["EL0", "EL1", "EL2", "EL3"]定义四个特权级的顺序表,索引即级数,越大权限越高。
  2. self._level = 0初始态放在 EL0,因为真实系统引导完内核后,应用都从用户态开始跑。
  3. if self._level != 0:模拟 SVC 的门禁检查:只有处于 EL0 的代码才能发起系统调用。
  4. self._level = 1权限提升动作,相当于电梯把访客从大厅送到办公层。
  5. if self._level != 2:SMC 检查当前必须处于 EL2,这符合实际固件里 SMC 常在 Hypervisor 或内核中被调用的习惯。
  6. self._level -= 1ERET 每次只降一级,而不是一口气回到 EL0。
  7. print("统计: SVC=%d ..." % ...)输出各指令触发次数,方便观察哪层被访问得最多。

常见误区

误区“EL0 是最底层,权限最小,那它一定没什么好保护的,安全重点应该全放在 EL3。”

正解EL0 恰恰是攻击面最大的一层。所有 App、浏览器、第三方库都跑在 EL0,每一个都是潜在入口。一旦 EL0 被攻破,攻击者会立刻尝试利用漏洞向 EL1 或更高层提权。ARM 的隔离设计,正是为了在 EL0 与 EL1 之间筑起高墙,让“即使 EL0 出事,内核也安全”。就像大厦最需要安保的不是保险库门口,而是访客大厅——那里人流最杂。

为何常见:人们看到“数字最小”就直觉认为“最弱最不重要”,忽略了安全体系的价值在于守住最容易被攻击的那一层。

误区“执行完 ERET 后,特权级一定会回到 EL0,因为要返回用户态。”

正解ERET 是“从异常中返回”,它恢复到异常发生前所在的特权级,而不是固定降到 EL0。比如 Linux 内核在 EL1 中通过 SMC 进入 EL3 办事,完成后 ERET 回到 EL1;内核中的中断处理例程 ERET 也回到 EL1。只有原本从 EL0 发起系统调用,ERET 才会回到 EL0。这就像电梯从 13 层下到 5 层的办公室,不会直接把你送到 1 楼大厅。

为何常见:初学者只接触过“App 调系统调用然后返回到用户态”这一条路径,就以偏概全。

误区“SMC 是银行 App 或军用系统才用的,我做通用软件不需要知道。”

正解SMC 是 EL3 的入口,任何涉及 TrustZone 的固件、任何要保护密钥的 AI 推理、任何需要安全启动的设备都会用到它。现代手机的开机引导、DRM 播放、生物识别都经过 SMC 往返安全世界。甚至你在云上跑的 ARM 服务器,固件更新也依赖 EL3 的安全监控。SMC 就像大厦的秘密通道,入口不起眼,但维护整栋楼的安保体系都在用它。

为何常见:日常开发中没人会直接写 SMC 汇编,它被封装在厂商固件里,导致开发者误以为它离自己很远。

误区“TrustZone 相当于把一部分存储空间加密,App 需要密钥时去解锁读取。”

正解TrustZone 是芯片级的安全世界隔离,不是加密分区。它隔离的是整个处理环境:安全世界有独立的内存区域、独立的外设访问权限、独立的中断处理。普通世界的代码在物理层面无法访问安全世界的地址空间。类比来说,它不像保险柜(加密存储),而像大院里单独盖了一栋只有特定人知道的小楼——门禁、监控、通道全部独立。

为何常见:很多人把“数据加密”和“环境隔离”混为一谈,因为两者都让数据“看起来不可见”。

误区“如果 EL3 权限最高,那把整个操作系统都放到 EL3 跑,是不是就不需要切换、性能拉满?”

正解EL3 的代表不是“更快”,而是“更严格的检查和更多隔离约束”。把代码放到 EL3 意味着每次服务调用都要经过安全校验,而且安全世界资源通常更少、切换更慢。真实系统的性能优化方向恰恰相反:让热点路径尽量在 EL0/EL1 完成,只在必要时陷入更高层。这就像把前台接待员安排到 CEO 办公室办公,不但不会更快,反而会让所有人排队更久。

为何常见:人们把“权限高”误解为“能力强、效率高”,忽略了权限层级的核心价值是安全边界而非算力。

面试题

Q1. ARM AArch64 一共定义了哪几个异常级别?

单选题 · easy

  • A.2 个
  • B.3 个
  • C.4 个← 正确答案
  • D.8 个

答案:C。ARMv8-A 定义 EL0、EL1、EL2、EL3 共四个异常级别。2 个和 3 个是凭感觉猜的常见错误,8 个则混淆了“位”或“寄存器组”的数量。就像 ARM 大厦只有四个门禁楼层,不是每层楼再分成若干个隔间。

Q2. 操作系统内核通常运行在哪个异常级别?

单选题 · easy

  • A.EL0
  • B.EL1← 正确答案
  • C.EL2
  • D.EL3

答案:B。Linux、Android、RTOS 等操作系统内核都运行在 EL1,负责内存管理、中断和设备驱动。EL0 是应用层,EL2 是 Hypervisor,EL3 是安全监控。内核像物业管理员,比访客(EL0)权限高,但进不了监控室(EL2)和保险库(EL3)。

Q3. 从 EL0 进入 EL1 通常执行什么指令?

单选题 · mid

  • A.SMC
  • B.HVC
  • C.SVC← 正确答案
  • D.ERET

答案:C。SVC 是系统调用指令,专门把 EL0 的应用请求陷入 EL1 的内核。SMC 通向 EL3,HVC 通向 EL2,ERET 是反向降级指令。选 SMC/HVC 的考生记住了“调用指令”却搞混了目标层级,ERET 则完全是把电梯开回原楼层的动作。

Q4. EL3 层最核心的安全能力是什么?

单选题 · easy

  • A.内存管理
  • B.安全隔离← 正确答案
  • C.缓存管理
  • D.中断处理

答案:B。EL3 的核心能力是 TrustZone 安全世界与普通世界的隔离与切换。内存管理、缓存、中断在 EL0-EL2 都有对应机制,唯独“世界切换”只有 EL3 资格。类比大厦里只有 CEO 能打开通往地下保险库的秘密电梯。

Q5. 虚拟机监控器 Hypervisor 运行在哪个异常级别?

单选题 · mid

  • A.EL0 层
  • B.EL1 层
  • C.EL2 层← 正确答案
  • D.EL3 层

答案:C。Hypervisor 运行在 EL2,负责管理多个 Guest OS(它们运行在 EL1)。EL0 是 Guest 应用,EL1 是 Guest 内核,EL3 是安全监控。把 Hypervisor 放 EL1 就无法隔离内核,放 EL3 则会让安全世界被虚拟化逻辑污染。

Q6. ERET 指令执行后,特权级通常会发生什么变化?

单选题 · hard

  • A.提升特权级
  • B.降低特权级← 正确答案
  • C.触发中断
  • D.刷新缓存

答案:B。ERET 从异常中返回,把 PC 从 ELR_ELx 恢复、PSTATE 从 SPSR_ELx 恢复,因此回到异常发生前所在的较低特权级。它不触发中断、不刷缓存,也不负责提升权限。这个“下行电梯”是每次系统调用返回到用户态的必经之路。

Q7. 以下哪些指令可以主动触发异常级别转换?

多选题 · mid

  • A.SVC 系统调用← 正确答案
  • B.HVC 虚拟化调用← 正确答案
  • C.SMC 安全监控调用← 正确答案
  • D.RET 普通函数返回

答案:ABC。SVC 从 EL0 进 EL1,HVC 从 EL1 进 EL2,SMC 进 EL3,三者都是主动发起异常完成特权上升。RET 是普通函数返回,只改变 PC,不改变特权级。像三种不同楼层的呼叫按钮,其中 RET 只是办公室内部挪动。

Q8. 关于 TrustZone 的描述,下列哪些是正确的?

多选题 · mid

  • A.由 EL3 管理← 正确答案
  • B.通过 SMC 切换← 正确答案
  • C.只能用于手机
  • D.分安全与普通世界← 正确答案

答案:ABD。TrustZone 由 EL3 仲裁,SMC 是关键切换指令,将世界划分为普通世界和安全世界。C 项“只能用于手机”是错误观点,ARM 服务器、路由器、IoT 设备同样使用 TrustZone 保护固件和密钥。它的本质是通用芯片安全基座。

Q9. EL2 Hypervisor 决定拦截 Guest 的敏感操作时,控制权会发生什么?

单选题 · extreme

  • A.放行给 Guest
  • B.陷入到 EL2← 正确答案
  • C.陷入到 EL0
  • D.处理器重启

答案:B。当 HCR_EL2 等配置位开启 trap 后,Guest 执行敏感指令会引起异常,处理器控制权自动移交 EL2 的 Hypervisor。A 是“不拦截”,C 是误解了 trap 目标(EL0 是 Guest 应用层),D 是灾难性后果。安保主管按下拦截键后,画面切到自己面前,而不是让访客自己处理。

Q10. 最小权限原则在 ARM 特权级设计中的最佳实践是什么?

单选题 · hard

  • A.以最高权限运行
  • B.只取所需最低权限← 正确答案
  • C.所有代码跑 EL3
  • D.完全关闭特权级

答案:B。每个软件组件只获得完成任务所需的最低特权级,能放 EL0 就不放 EL1,能放 EL1 就不放 EL2。A/C 会把攻击面无限放大,D 不现实。这就像配门禁卡:只给员工开他工位所在楼层的权限,而不是把整栋楼的钥匙都挂在他腰间。