05-Exception Handling Framework

引流关键词: 中断、同步异常、异步异常、irq、fiq、BL1,BL2,BL3,BL31,BL32,BL33,AP_BL1,AP_BL2,AP_BL3,AP_BL31,AP_BL32,AP_BL33,SCP_BL1,SCP_BL2,BL0,BL30, optee、ATF、TF-A、Trustzone、optee3.14、MMU、VMSA、cache、TLB、arm、armv8、armv9、TEE、安全、内存管理、页表…

快速链接:
.
??? 个人博客笔记导读目录(全部) ???


[专栏目录]-ATF/FF-A/specification学习

请添加图片描述

术语
EHF : Exception Handling Framework

5.异常处理框架

本文档描述了运行时固件 (BL31) 针对 EL3(而非 SMC)处理异常的framework。EHF将处理以下异常:

  • 中断
  • 同步外部中止 (Synchronous External Aborts)
  • 异步外部中止(Asynchronous External Aborts)

固件设计文档中描述了TF-A对从较低 EL 引发的同步SMC异常。然而, EHF描述了除 SMC之外的中断处理和同步异常的语义

通过将构建选项设置为 来选择EHF(EL3_EXCEPTION_HANDLING=1) ,并且仅适用于 AArch64 系统。

5.1 介绍

通过寄存器中的各种控制位SCR_EL3,Arm 架构允许将异步异常路由到 EL3。如 中断管理框架文档中所述,根据所选的中断路由模型,TF-A 适当地设置寄存器的FIQ和IRQ位 SCR_EL3以实现此路由。对于大多数用例,除了促进正常和安全世界之间的上下文切换之外,路由到 EL3 的 FIQ 和 IRQ 不需要在 EL3 中处理。

然而,不断发展的系统和标准环境要求在 EL3 中针对和处理各种异常。例如:

  • 从 ARMv8.2 架构扩展开始,许多 RAS 特性被引入到 Arm 架构中。实施 RAS 功能后,系统的各种组件可以使用其中一种异步异常来向 PE 发出错误信号。这些错误情况具有严重的性质,必须尽早采取纠正或补救措施。因此,通常遵循固件优先处理方法来响应系统中的 RAS 事件

  • Arm SDEI 规范定义了 Normal world 与 Runtime Firmware 交互以请求系统事件通知的接口。SDEI规范要求通知这些事件,即使在正常世界执行时屏蔽了异常。这也意味着需要固件优先处理,其中事件首先由 EL3 固件接收,然后通过纯软件机制发送到普通世界。

对于TF-A,固件优先处理意味着异步异常被适当地路由到 EL3,并且运行时固件 (BL31) 被扩展为包括能够处理以 EL3 为目标的那些异常的软件组件。这些组件(通常称为调度程序 : dispatchers )可以选择:

  • 完全在 EL3 中接收和处理异常,这意味着异常处理在 EL3 中终止。
  • 接收异常,但在 EL3 中处理部分异常,并将其余处理委托给在较低安全 EL 上运行的专用软件堆栈。在该方案中,处理跨越各种安全 EL。
  • 接收异常,但在 EL3 中处理部分异常,并将错误的处理委托给在较低安全 EL 上运行的专用软件堆栈(如上);此外,普通世界也可能需要参与处理,或被通知此类事件(例如,作为SDEI事件)。在此方案中,异常处理可能且最大程度地跨越安全和正常世界中的所有 EL。

在任何给定的系统上,所有上述处理模型都可以独立使用,具体取决于平台选择和接收到的异常的性质。

5.2. 异常处理框架的作用

作为上述用例的推论,EHF的主要作用是促进固件优先处理 Arm 系统上的异常。因此,EHF使运行时固件中的多个异常分派器能够共存、注册和处理针对 EL3 的异常。本节概述了基础知识,本文档的其余部分扩展了EHF的各个方面。

为了在调度程序之间仲裁异常处理,EHF操作基于优先级方案。这种优先级方案与 Arm GIC 架构如何定义它密切相关,尽管它也适用于非中断异常(例如 SErrors)。

平台需要将安全优先级空间划分为适用于安全软件堆栈的优先级。然后它将调度程序分配给一个或多个优先级。然后调度程序在运行时为优先级注册处理程序。调度程序可以为多个优先级注册处理程序。

../_images/ehf.svg

当处于该优先级的处理程序当前正在 EL3 中执行或已将执行委托给较低的 EL 时,该优先级处于活动状态。对于中断,当一个中断在 EL3 被定位和确认时,这是隐含的,并且已确认中断的优先级用于匹配其注册的处理程序。当中断处理通过 EOI 中断结束时,优先级同样被隐式禁用。

非中断异常(例如 SErrors)没有优先级的概念。为了使优先级仲裁起作用,EHF提供了 API,以便这些非中断异常具有优先级,并与中断交互。因此,处理此类异常的调度程序必须在处理或委派它们时显式激活和停用相应的优先级。

因为中断处理的优先级激活和停用是隐式的并且涉及 GIC 优先级屏蔽,所以较低优先级的中断不可能抢占较高优先级的中断。通过扩展,这意味着较低优先级的调度程序不能抢占较高优先级的调度程序。然而,非中断异常的优先级激活和停用必须是明确的。因此,EHF不允许在较高优先级处于活动状态时激活较低优先级,并且会导致恐慌。同样,如果在较高优先级处于活动状态时尝试停用较低优先级,则会导致恐慌。

本质上,优先级激活和停用在概念上就像一个堆栈——优先级以严格递增的方式堆叠,并且需要以严格的相反顺序取消堆叠。对于中断,GIC 确保是这种情况;对于非中断,EHF监控并断言这一点。请参阅 优先级转换。

5.3. 中断处理

EHF是中断管理框架的客户端,并为针对 EL3 的中断注册顶级处理程序,如 中断管理框架文档中所述。这具有以下含义:

  • 在 GICv3 系统上,当在 S-EL1 中执行时,具有足够优先级的未决非安全中断将作为 FIQ 发出信号,因此将被路由到 EL3。因此,S-EL1 软件不能期望在 S-EL1 处处理非安全中断。本质上,这不赞成描述为CSS=0, TEL3=0的路由模式。

  • 为了让 S-EL1 软件在 启用EHF时处理非安全中断,调度程序必须采用一种模型,即在 EL3 接收非安全中断,然后同步 处理到 S-EL1。

  • 在 GICv2 系统上,需要将构建选项GICV2_G0_FOR_EL3设置为,1以便Group 0中断以 EL3 为目标。

  • 在安全世界中执行时,EHF将 GIC 优先级掩码寄存器设置为最低安全优先级。这意味着没有非安全中断可以抢占安全执行。有关更多详细信息,请参阅对 SMC 调用的影响。

如上所述,使用EHF时,平台需要将Group 0 中断划分为不同的优先级。选择接收中断的调度程序然后可以拥有一个或多个优先级,并为它们注册中断处理程序。给定的优先级只能分配给一个处理程序。调度程序可以注册多个优先级。

分派器分两步分配中断优先级:

5.3.1。分区优先级

通过对中断进行分组和分配优先级的方式,中断与调度程序相关联。换句话说,所有针对特定调度程序的中断都应该属于特定的优先级。对于优先级分配:

  • Arm GIC 架构允许的 8 位优先级中,第 7 位必须为 0(安全空间)。

  • 根据要支持的调度程序的数量,平台必须选择使用剩余 7 个位中的前n位来识别中断并将其分配给各个调度程序。选择n位最多支持 2 n 个 不同的调度程序。例如,通过选择 2 个附加位(即位 6 和 5),平台可以划分为 4 个安全优先级范围:0x0、 0x20、0x40和0x60。请参阅中断处理示例。

注意: Arm GIC 架构要求支持两种安全状态的 GIC 实现必须实现至少 32 个优先级;即,8位中的至少5个高位是可写的。In the scheme described above, when choosing n bits for priority range assignment, the platform must ensure that at least n+1top bits of GIC priority are writeable.

因此分配给中断的优先级也用于确定较低 EL 中委派执行的优先级。较低 EL 中的委托执行与使用ehf_activate_priority()API 选择的优先级相关联(稍后描述)。选择的优先级还决定了在较低 EL 中执行时屏蔽的中断,因此控制了委托执行的抢占。

平台通过声明优先级描述符数组来表达选择的优先级。数组中的每个条目都是类型 ehf_pri_desc_t,并声明一个优先级,并应由 EHF_PRI_DESC()宏填充。

注意:宏EHF_PRI_DESC()将描述符安装在数组中的计算索引处,而不必将宏放置在数组中的位置。因此,数组的大小可能比它看起来的要大。因此ARRAY_SIZE()应该使用宏来确定数组的大小。

最后,这个描述符数组通过 宏暴露给EHF 。EHF_REGISTER_PRIORITIES()

使用方法请参考中断处理示例。另请参阅:中断优先级考虑。

5.3.2. 编程优先级

分区优先级中的文本仅描述了平台如何表达所需的优先级。然而,它不会选择中断,也不会在 GIC 中编程所需的优先级。

固件设计指南解释了配置安全中断的方法。EHF要求平台枚举安全中断的中断属性(而不仅仅是数量)。安全中断的优先级必须与上面分区优先级部分中确定的相匹配 。

请参阅限制,另请参阅中断处理示例以进行说明。

5.4. 注册处理程序

调度程序通过以下 API 为其优先级注册处理程序:

int ehf_register_priority_handler(int pri, ehf_handler_t handler)

API 有两个参数:

  • 注册处理程序的优先级;

  • 要注册的处理程序。处理程序必须对齐到 4 个字节。

如果调度程序拥有多个优先级,它必须为每个优先级调用 API。

API 将成功并返回0,仅在以下情况下:

  • 存在具有请求的优先级的描述符。

  • 之前调用 API 时没有注册处理程序。

否则,API 返回-1.

中断处理程序应具有以下签名:

typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle,
                void *cookie);

这些参数是从顶级EL3 中断处理程序中获得的。

例如,SDEI 调度程序期望平台分配两个不同的优先级 - PLAT_SDEI_CRITICAL_PRI和PLAT_SDEI_NORMAL_PRI- 并注册相同的处理程序来处理这两个级别。

5.5. 中断处理示例

以下带注释的片段演示了平台如何选择将中断分配给虚构的调度程序:

#include <common/interrupt_props.h>
#include <drivers/arm/gic_common.h>
#include <exception_mgmt.h>

...

/*
 * This platform uses 2 bits for interrupt association. In total, 3 upper
 * bits are in use.
 *
 *  7 6 5   3      0
 * .-.-.-.----------.
 * |0|b|b|  ..0..   |
 * '-'-'-'----------'
 */
#define PLAT_PRI_BITS        2

/* Priorities for individual dispatchers */
#define DISP0_PRIO           0x00 /* Not used */
#define DISP1_PRIO           0x20
#define DISP2_PRIO           0x40
#define DISP3_PRIO           0x60

/* Install priority level descriptors for each dispatcher */
ehf_pri_desc_t plat_exceptions[] = {
     EHF_PRI_DESC(PLAT_PRI_BITS, DISP1_PRIO),
     EHF_PRI_DESC(PLAT_PRI_BITS, DISP2_PRIO),
     EHF_PRI_DESC(PLAT_PRI_BITS, DISP3_PRIO),
};

/* Expose priority descriptors to Exception Handling Framework */
EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions),
     PLAT_PRI_BITS);

...

/* List interrupt properties for GIC driver. All interrupts target EL3 */
const interrupt_prop_t plat_interrupts[] = {
     /* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */
     INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
     INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),

     /* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */
     INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
     INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),

     /* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */
     INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
     INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
};

...

/* Dispatcher 1 registers its handler */
ehf_register_priority_handler(DISP1_PRIO, disp1_handler);

/* Dispatcher 2 registers its handler */
ehf_register_priority_handler(DISP2_PRIO, disp2_handler);

/* Dispatcher 3 registers its handler */
ehf_register_priority_handler(DISP3_PRIO, disp3_handler);

...

另请参阅构建时流程和运行时流程。

5.6. 激活和停用优先级

当处理该优先级的异常时,该优先级被认为是活动的:对于中断,这在中断被确认时是隐含的;对于非中断异常,例如 SErrors 或SDEI 显式调度,这必须通过调用来完成ehf_activate_priority()。请参阅运行时流程。

相反,当调度程序已经达到异常原因的逻辑解决方案时,相应的优先级应该被停用。如上,对于中断,当中断为 GIC 中的 EOId 时,这是隐含的;对于其他例外情况,这必须通过调用来完成 ehf_deactivate_priority()。

由于异常委派的不同规定,可能有不止一个工作流程用于停用:

  • 调度程序已解决异常的原因,并决定不采取进一步措施。在这种情况下,调度程序的处理程序在返回EHF之前停用优先级。运行时固件在通过 退出时,会ERET在中断发生之前恢复执行。

  • SMC调度程序必须将执行委托给较低的 EL,并且只有当较低的 EL在未来的某个时间点返回完成(通过 an )信号时,才能认为异常的原因已解决。出现以下顺序:
    (1)、调度员调用setjmp()设置一个跳转点,并安排在下一个 EL 时进入较低的 EL ERET。
    (2)、通过随后ERET的运行时固件,将执行委托给较低的 EL。
    (3)、较低的 EL 完成其执行,并通过 SMC.
    (4)、由SMC之前处理异常的同一调度程序处理。注意到异常处理的结束,调度程序确实longjmp()恢复到前一个跳转点之外。

如上所述,EHF提供以下 API 用于激活和停用中断:

  • ehf_activate_priority()激活提供的优先级,但前提是当前活动的优先级高于给定的优先级;否则恐慌。此外,为了防止被较低优先级的物理中断中断,EHF将对应于 PE 的优先级掩码寄存器编程为被激活的优先级。调度程序通常只需要在处理除中断以外的异常时调用它,并且它需要将执行委托给所需优先级的较低 EL。

  • ehf_deactivate_priority()停用给定的优先级,但前提是当前活动的优先级等于给定的优先级;否则恐慌。EHF 还将PE对应的Priority Mask Registerehf_activate_priority()恢复到调用之前的优先级。调度程序通常只需要在处理除中断以外的异常后调用它。

API 的调用取决于允许的转换。另请参见 运行时流程。

5.7. 优先级的转换

可以调用EHF APIehf_activate_priority()来转换 PE 上的当前优先级。ehf_deactivate_priority()对这些 API 的给定调用序列受以下条件的约束:

  • 对于激活,EHF只允许增加优先级(即数值减少);

  • 对于停用,EHF只允许降低优先级(即增加数值)。此外,被停用的优先级必须是当前优先级。

如果违反这些,就会导致恐慌。

5.8. 对 SMC 呼叫的影响

一般来说,安全执行被认为比非安全执行更重要。正如本文档其他地方所讨论的,EL3 执行以及之后的任何委派执行都具有提高 GIC 优先级掩码的效果——无论是通过确认安全中断隐含地,还是在调度程序调用ehf_activate_priority(). 因此,非安全中断不能抢占任何安全执行。

来自非安全世界的 SMC 是同步异常,是非安全世界请求安全服务的机制。它们被广泛归类为 快速或屈服(参见SMCCC)。

  • 从调用者的角度来看,快速SMC 是原子的。即,它们仅在安全世界完成服务请求时才返回给调用者。同时挂起的任何非安全中断都不能抢占安全执行。

  • Yielding SMC 带有可抢占的、低优先级请求的语义。挂起的非安全中断可以抢占处理 Yielding SMC 的安全执行。即,调用者可能会在以下任一情况下观察到 Yielding SMC 返回:
    (1)安全世界完成请求,调用者将找到SMC_OK 作为返回码。
    (2)非安全中断抢占安全执行。处理非安全中断,并在SMC指令后恢复非安全执行。

  • 处理 Yielding SMC 的调度程序必须向非安全调用方提供不同的返回码,以区分后一种情况。但是,此返回代码不是标准化的(例如,与SMC_UNKNOWNor不同SMC_OK),因此会因处理请求的调度程序而异。

对于上面的后一种情况,EHF之前的调度程序期望将非安全中断带到 S-EL1 2,因此将有机会在屈服于非安全世界之前填充指定的抢占错误代码。

EHF的引入改变了中断处理中描述的行为。

启用EHF时,为了允许非安全中断抢占 Yielding SMC 处理,调度程序必须调用ehf_allow_ns_preemption() API。API 采用一个参数,即在被抢占后返回到非安全世界的错误代码。

5.9. 构建时流程

构建时流程涉及以下步骤:

(1)平台通过为各个调度程序安装优先级描述符来分配优先级,如分区优先级中所述。

(2)平台为 GIC 驱动程序提供中断属性,如 编程优先级中所述。

(3)调度程序调用ehf_register_priority_handler()以注册中断处理程序。

5.10。运行时流

以下是中断的示例流程:

(1)GIC 驱动程序在初始化期间迭代平台提供的中断属性(请参阅编程优先级),并配置中断。这会对属于不同调度程序的中断编程适当的优先级和组(组 0)。

(2)EHF在其初始化过程中,向 EL3 中断的中断管理框架注册一个顶级中断处理程序。这也导致设置路由位SCR_EL3。

(3)当属于调度程序的中断触发时,GIC 引发 EL3/Group 0 中断,并被带到 EL3。

(4)执行顶级 EL3 中断处理程序。处理程序确认中断,读取其运行优先级,并据此确定调度程序处理程序。

(5)EHF将PE 的优先级屏蔽寄存器编程为接收到的中断的优先级。

(6)EHF将该优先级标记为active,并跳转到调度程序处理程序。

(7)一旦调度程序处理程序完成其工作,它必须在返回EHF之前立即 停用优先级。请参阅 停用工作流程。

以下是针对除中断以外的 EL3 的异常的示例流程:

(1)该平台为特定类型的异常提供处理程序。

(2)异常到来,相应的处理程序被执行。

(3)处理程序调用ehf_activate_priority()以激活所需的优先级。这也具有提高 GIC 优先级掩码的效果,从而防止较低优先级的中断抢占处理。处理程序可以选择完全在 EL3 中进行处理或委托给较低的 EL。

(4)一旦异常处理结束,处理程序将调用 ehf_deactivate_priority()以停用先前激活的优先级。这也具有将 GIC 优先级掩码降低到以前的效果。

5.11。中断优先级考虑

根据设计,GIC 优先级方案将安全中断优先于普通世界中断。该平台通过EHF进一步在安全调度员之间分配相对优先级。

如分区优先级中所述,针对不同调度程序的中断属于不同的优先级。因为它们是通过 GIC 路由的,所以到 PE 的中断传递受 GIC 优先级规则的约束。特别是,当 PE 正在处理中断时(即中断处于活动状态),即使具有相同或较低优先级的中断未决,也只有较高优先级的中断会被发送到 PE。这会产生一个副作用,即一个调度程序由于另一个调度程序处理其(更高优先级)中断而缺乏中断。

EHF不强制执行特定的优先级策略,但平台应仔细考虑将优先级分配给集成到运行时固件中的调度程序。平台应根据不同调度员的性质,明智地为其划分优先级。特别是,关键性质的调度程序(例如 RAS)应该被分配比其他调度程序更高的优先级(例如SDEI);在SDEI中,关键优先级 SDEI的优先级应高于正常优先级。

5.12。限制

EHF具有以下限制:

  • 尽管 GIC 优先级方案最多可支持 128 个安全调度程序,但 EHF_REGISTER_PRIORITIES()当前使用宏公开的描述符数组的大小限制为 32 个。这适用于大多数预期的用例。如果用例需要,这可能会在未来扩展。

  • 平台必须确保异常描述符中分配给调度程序的优先级与调度程序处理的中断的编程优先级匹配。EHF无法验证这是否已被遵循。


版权声明:本文为weixin_42135087原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。