目录
2.1 ARMv8-A
ARMv8-A引入众多改变:
3. ARMv8的基础
在ARMv8中,执行发生在四个异常级别(Exception levels)中的一个。在AArch64状态中,异常级别决定了特权级别,这与ARMv7中定义的特权级别类似。异常级别决定了特权级别,因此在异常级别ELn上的执行对应于特权级别PLn。同样,如果一个异常级别的n值比另一个大,它就处于更高的异常级别。一个异常级别如果n值比另一个小,就被称为处于较低的异常级别。
异常级别为软件执行特权提供了逻辑上的分离,这适用于ARMv8架构的所有操作状态。它类似于并且支持计算机科学中常见的分层保护域的概念。
通常,软件(例如应用程序、操作系统的内核或虚拟机监视器)占据单一的异常级别。这个规则的一个例外是内核级虚拟机监视器,如KVM,它在EL2和EL1两个异常级别上操作。
ARMv8-A提供了两种安全状态:安全状态(Secure)和非安全状态(Non-secure)。非安全状态也被称为普通世界(Normal World)。这使得操作系统(OS)能够与受信任的操作系统在相同的硬件上并行运行,并提供对某些软件攻击和硬件攻击的保护。ARM TrustZone技术允许系统在普通世界和安全世界之间进行分区。与ARMv7-A架构一样,安全监视器(Secure monitor)作为在普通世界和安全世界之间移动的网关。
在安全状态和非安全状态之间进行转换通常是由安全监视器软件控制的,它负责管理两个世界之间的安全过渡。当软件需要访问安全世界提供的服务或资源时,它会请求安全监视器进行状态转换。这种机制确保了敏感操作和数据受到保护,并且只能通过受信任的代码访问。
安全状态提供了额外的控制和保护机制,包括:
- 对内存和外设的访问控制。
- 对异常处理程序的特殊安全属性。
- 对某些系统寄存器的访问限制。
这些特性使得安全状态成为执行安全敏感操作,如安全启动、加密操作和安全数据存储的理想环境。通过使用TrustZone技术,设备制造商可以创建具有强大安全特性的系统,以抵御恶意软件和各种攻击向量。
ARMv8-A提供了对虚拟化的支持,但仅限于普通世界(Normal World)。这意味着虚拟机监视器(Hypervisor)或虚拟机管理器(Virtual Machine Manager, VMM)代码可以在系统上运行,并托管多个客户操作系统(Guest Operating Systems)。本质上,每个操作系统都在一个虚拟机上运行。每个操作系统都意识不到它正在与系统中的其他客户操作系统共享时间。
ARMv8-A的虚拟化支持包括以下特点:
-
硬件辅助虚拟化:ARMv8-A提供了硬件级别的支持,使得虚拟化更加高效和安全。这包括对虚拟化专用的寄存器和指令的支持。
-
虚拟化异常级别:在ARMv8-A中,EL2被用作虚拟化异常级别,允许VMM在该级别上运行,同时客户操作系统在更低的异常级别(如EL1或EL0)上运行。
-
客户操作系统隔离:每个客户操作系统都在自己的虚拟环境中运行,与其他客户操作系统隔离。这确保了操作系统之间的操作不会相互干扰。
-
高效的资源管理:VMM负责管理虚拟资源,包括CPU时间、内存和外设等。它可以根据需要在不同的客户操作系统之间动态分配这些资源。
-
安全性:虚拟化环境可以提供额外的安全层,因为客户操作系统在隔离的环境中运行,减少了潜在的攻击面。
-
灵活的部署:虚拟化允许在同一硬件平台上部署多个操作系统和应用程序,提高了硬件的利用率和灵活性。
通过这些特性,ARMv8-A架构能够支持复杂的虚拟化场景,适用于云计算、数据中心和企业环境,其中需要同时运行多个操作系统和应用程序。
在ARMv8架构中,普通世界(Normal World,对应于非安全状态Non-secure state)和安全世界(Secure World)是两个主要的执行环境,它们具有不同的特权组件:
普通世界(Non-secure state)的特权组件:
-
客户操作系统内核(Guest OS Kernels):
- 这些内核包括在非安全EL1上运行的Linux或Windows。在虚拟机监视器(Hypervisor)下运行时,这些丰富的操作系统内核可以作为客户或主机运行,这取决于虚拟机监视器的模型。
-
虚拟机监视器(Hypervisor):
- 运行在总是非安全的EL2上。当虚拟机监视器存在并启用时,它为丰富的操作系统内核提供虚拟化服务。
安全世界(Secure state)的特权组件:
-
安全固件(Secure Firmware):
- 在应用处理器上,安全固件必须是启动时首先运行的组件。它提供多种服务,包括平台初始化、安装可信操作系统以及路由安全监视器调用。
-
可信操作系统(Trusted OS):
- 可信操作系统为普通世界提供安全服务,并为执行安全或可信应用程序提供运行时环境。
安全监视器(Secure Monitor):
- 在ARMv8架构中,安全监视器位于更高的异常级别,比其他所有级别都具有更高的特权。这提供了一个逻辑上的软件特权模型。
- 安全监视器作为普通世界和安全世界之间的网关,控制着两个世界之间的转换和通信。
- 它负责管理安全状态和非安全状态之间的安全转换,确保只有经过验证和授权的代码才能访问安全世界。
这种分层的特权模型为操作系统、应用程序和安全服务提供了清晰的分离,增强了系统的安全性和可靠性。通过将敏感操作和数据隔离在安全世界中,ARMv8架构有助于防止恶意软件攻击和未经授权的数据访问。同时,普通世界可以支持传统的操作系统和应用程序,而不会暴露安全关键的组件。
3.1 execution states 执行状态
ARMv8架构定义了两种执行状态:AArch64和AArch32。每种状态分别用于描述使用64位宽通用寄存器或32位宽通用寄存器的执行环境。
-
AArch64执行状态:
- 在AArch64状态下,处理器使用64位宽的通用寄存器。
- 特权级别由异常级别(Exception level, EL)决定。例如,在EL1上的执行对应于特权级别1(Privilege level 1, PL1)。
- 处理器执行的是A64指令集,这是ARMv8架构中新增的64位指令集。
-
AArch32执行状态:
- 在AArch32状态下,处理器使用32位宽的通用寄存器。
- ARMv8 AArch32状态保留了ARMv7的特权定义,但特权级别仍然可以由异常级别决定,如果系统配置为这种方式。
- 处理器可以执行A32指令集,这在早期的架构版本中被称为ARM指令集,或者执行T32(Thumb)指令集,后者是一种更紧凑的编码形式,用于节省内存空间。
3.2改变异常级别
在ARMv7架构中,处理器模式可以在特权软件控制下更改,或者在发生异常时自动更改。当异常发生时,核心会保存当前的执行状态和返回地址,进入所需的模式,并可能禁用硬件中断。以下是对这些概念的总结:
-
处理器模式:ARMv7架构定义了多种处理器模式,每种模式都有其特定的权限级别,用于执行不同类型的操作。
-
异常:当程序执行过程中遇到特定的条件或错误时,处理器会触发异常。异常可以导致处理器从当前模式切换到处理该异常的特定模式。
-
执行状态和返回地址:在进入异常处理程序之前,处理器会保存当前的执行状态,包括寄存器值和程序计数器,以便在异常处理完成后能够返回到异常发生的位置。
-
模式切换:异常发生时,处理器会自动切换到处理该异常的模式。例如,从用户模式切换到内核模式,以便操作系统可以处理异常。
-
硬件中断:在某些模式下,可能会禁用硬件中断,以确保异常处理的原子性和系统的稳定性。
AArch64中processor mode按下图map AArch32的exception level。
在ARM架构中,异常级别(Exception Levels, EL)之间的转换遵循以下规则:
-
提升特权:向更高异常级别的转换,例如从EL0到EL1,表示软件执行权限的增加。
-
不允许降低级别:异常不能被触发到更低的异常级别。
-
EL0无异常处理:在异常级别0(EL0),没有异常处理机制。异常必须在更高的异常级别上处理。
-
异常流程改变:异常会导致程序流程的改变。异常处理程序的执行从高于EL0的异常级别开始,从一个与触发的异常相关的预定义向量(vector)开始。异常包括:
- 中断,例如IRQ(中断请求)和FIQ(快速中断请求)。
- 内存系统中止(Memory system aborts)。
- 未定义指令(Undefined instructions)。
- 系统调用(System calls),允许非特权软件向操作系统发起系统调用。
- 安全监视器或虚拟机监视器陷阱(Secure monitor or hypervisor traps)。
-
异常处理结束:通过执行ERET(Exception Return)指令来结束异常处理并返回到之前的异常级别。
-
返回异常级别:从异常返回时,可以保持在同一异常级别,或者进入更低的异常级别。它不能移动到更高的异常级别。
-
安全状态与异常级别:异常级别的改变通常不会引起安全状态的改变,除非是从EL3返回到非安全状态。在这种情况下,安全状态会根据从安全监视器或虚拟机监视器接收到的指令而改变。
3.3 改变execution state (执行状态)
在ARM架构中,改变系统执行状态是必要的,尤其是在需要在64位操作系统上运行32位应用程序,或者在不同执行状态之间进行切换时。以下是一些关于在AArch64和AArch32执行状态之间切换的关键点:
-
操作系统和应用程序的执行状态:如果你正在运行一个64位操作系统,并希望在EL0上运行一个32位应用程序,则系统必须切换到AArch32状态。应用程序完成后或执行返回到操作系统时,系统可以切换回AArch64状态。相反,一个AArch32操作系统不能托管64位应用程序。
-
在同一异常级别之间切换执行状态:要在相同异常级别之间切换执行状态,系统需要先切换到更高的异常级别,然后再返回到原始异常级别。例如,一个64位操作系统下可能同时运行32位和64位应用程序。在这种情况下,32位应用程序可以执行并生成一个超级调用(SVC)指令,或接收到中断,导致切换到EL1和AArch64状态。然后操作系统可以执行任务切换并返回到AArch64的EL0。
-
混合32位和64位应用程序的限制:实际上,你不能同时拥有混合32位和64位的应用程序,因为它们之间没有直接的调用方式。
-
通过改变异常级别来改变执行状态:只能通过改变异常级别来改变执行状态。触发异常可能会从AArch32切换到AArch64,从异常返回可能会从AArch64切换回AArch32。
-
EL3的异常限制:在EL3上的代码不能触发到更高异常级别的异常,因此不能改变执行状态,除非通过重置。
-
AArch64和AArch32执行状态的切换摘要:
- AArch64和AArch32执行状态都有相似的异常级别,但在安全和非安全操作之间存在一些差异。
- 切换到AArch32需要从更高的异常级别到更低的异常级别,这是通过执行ERET指令退出异常处理程序的结果。
- 切换到AArch64需要从更低的异常级别到更高的异常级别,异常可能是由于指令执行或外部信号引起的。
- 如果在触发异常或从异常返回时异常级别保持不变,执行状态不能改变。
- 在特定的异常级别上,ARMv8处理器在AArch32执行状态下使用与ARMv7相同的异常模型。在AArch64执行状态下,它使用第10章AArch64异常处理中描述的异常处理模型。
-
两种状态之间的互操作:因此,两种状态之间的互操作是在安全监视器、虚拟机监视器或操作系统层面上执行的。在AArch64状态下执行的虚拟机监视器或操作系统可以支持在较低特权级别上的AArch32操作。这意味着在AArch64下运行的操作系统可以托管AArch32和AArch64应用程序。同样,AArch64虚拟机监视器可以托管AArch32和AArch64客户操作系统。然而,32位操作系统不能托管64位应用程序,32位虚拟机监视器也不能托管64位客户操作系统。
在ARMv8架构中,Cortex-A53和Cortex-A57处理器实现了最高异常级别EL3。对于每个异常级别(Exception Level, EL),在触发异常时使用的执行状态是固定的。这意味着,对于EL3,异常级别只能通过重置处理器来改变。以下是一些具体的细节:
-
EL3的固定执行状态:在Cortex-A53和Cortex-A57处理器上,当处理器处于EL3时,它使用的是AArch32执行状态。这是因为EL3主要用于安全相关的操作,而安全相关的代码和指令集在ARMv8中主要是基于32位的。
-
重置处理器以改变异常级别:由于EL3的执行状态是固定的,如果需要改变异常级别,必须通过重置处理器来实现。这通常是通过系统控制寄存器(System Control Register)或其他系统级别的机制来触发的。
-
EL2和EL1的执行状态控制:对于异常级别2(EL2)和异常级别1(EL1),它们的执行状态可以通过系统寄存器来控制。这些寄存器允许操作系统或虚拟机监视器(Hypervisor)来配置处理器在这些异常级别上使用AArch64还是AArch32执行状态。
-
系统寄存器:系统寄存器提供了对处理器模式和执行状态的控制。例如,
CPACR_EL1
(协处理器访问控制寄存器)和SCTLR_ELx
(系统控制寄存器)等寄存器可以用来配置处理器的行为。 -
异常处理:当处理器从EL0或EL1触发异常到EL2或EL3时,它会根据当前的配置进入AArch32或AArch64执行状态。异常处理完成后,通过执行ERET(异常返回)指令返回到异常发生前的执行状态。
-
安全和虚拟化:EL3通常用于安全监控和虚拟化场景。在安全场景中,它提供了一个受信任的执行环境,用于安全启动和安全数据存储。在虚拟化场景中,EL3可以作为虚拟机监视器运行的环境。