引流关键词: 中断、同步异常、异步异常、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学习
20.颗粒保护表库
本文档描述了 Trusted Firmware-A (TF-A) 使用的颗粒保护表 (GPT) 库的设计。该库提供基于包含系统内存布局信息的数据结构初始化 GPT、配置系统寄存器以启用基于这些表的颗粒保护检查以及在运行时在不同 PAS(物理地址空间)之间转换颗粒所需的 API .
Arm CCA 添加了两种新的安全状态,总共四种:root、realm、secure 和 non-secure。除了新的安全状态外,还添加了相应的物理地址空间来控制每个状态的内存访问。下表中可以看到允许对每个安全状态的 PAS 访问。
GPT 可以用作 1 级或 2 级查找,具体取决于 PAS 区域的配置方式。第一步是0级表,0级表中的每个条目控制对内存中相对较大的区域(块描述符)的访问,当使用单步映射时,整个区域可以属于单个PAS,或者0 级条目可以链接到 1 级表,其中相对较小的内存区域(颗粒)可以通过 2 步映射分配给不同的 PAS。每个 PAS 使用的映射类型由用户在设置配置结构时确定。
20.1。设计概念和界面
本节介绍 GPT 库中使用的一些重要概念和数据结构。
决定表的组织方式和功能的三个主要参数:PPS(受保护的物理空间)是系统中受保护的物理地址空间的总量,PGS(物理颗粒大小)是每个级别 1 颗粒的大小是,以及 L0GPTSZ(0 级 GPT 大小),它确定每个 0 级条目控制多少物理内存。颗粒是可以独立分配给 PAS 的最小内存单元。
L0GTSZ 由硬件决定,从 GPCCR_EL3 寄存器中读取。PPS 和 PGS 在运行时传递到 API 中,可以通过某种算法或固件中的硬编码以最适合给定平台的任何方式确定。
GPT 设置分为两部分:表创建和运行时初始化。在表创建步骤中,包含有关所需 PAS 区域信息的数据结构被传递到库中,该库验证映射,在内存中创建表,并启用颗粒保护检查。在运行时初始化步骤中,运行时固件使用 GPT 寄存器配置定位内存中的现有表,并将重要数据保存到粒度转换服务使用的结构中,这将在下面详细介绍。
在 FVP 模型的参考实现中,您可以在文件中找到 PAS 区域定义的示例include/plat/arm/common/arm_pas_def.h。表创建 API 调用可以在 中找到plat/arm/common/arm_bl2_setup.c,运行时初始化 API 调用可以在 中 找到plat/arm/common/arm_bl31_setup.c。
20.1.1。定义 PAS 区域
结构是一种pas_region_t表示物理地址空间及其属性的方法,GPT 库可以使用它来初始化表。
该结构由以下部分组成:
(1) 基本物理地址
(2) 区域大小
(3) 此内存区域的所需属性(映射类型、PAS 类型)
请参阅 中的pas_region_t类型include/lib/gpt_rme/gpt_rme.h。
程序员应该为 API 提供一个包含结构的数组pas_region_t ,然后库将检查所需的内存访问布局的有效性并创建表来实现它。
pas_region_t是一种公共类型,但是建议使用宏 GPT_MAP_REGION_BLOCK和GPT_MAP_REGION_GRANULE来填充这些结构,而不是手动填充,以减少将来出现兼容性问题的风险。这些宏将基本物理地址、区域大小和 PAS 类型作为参数来生成 pas_region_t 结构。顾名思义,GPT_MAP_REGION_BLOCK仅使用 L0 映射 GPT_MAP_REGION_GRANULE创建区域,同时使用 L0 和 L1 映射创建区域。
20.1.2. 0 级和 1 级表
GPT 初始化 API 需要为要构建的表传入内存,gpt_init_l0_tables获取内存地址和大小来构建级别 0 表,并gpt_init_pas_l1_tables获取地址和大小来构建从级别 0 描述符链接的级别 1 表。这些表应该具有 PAS 类型GPT_GPI_ROOT,典型的系统可能会将其 0 级表放在 SRAM 中,将其 1 级表放在 DRAM 中。
20.1.3. 颗粒转化服务
Granule Transition Service 允许使用 SMC 调用更改使用 GPT_MAP_REGION_GRANULE 所有权映射的内存。非安全颗粒可以转换到领域或安全空间,领域和安全颗粒可以转换回非安全。此库仅允许转换为颗粒的内存映射,映射为块的内存在表创建后固定其 GPI。
20.2. 库 API
可以在中找到公共 API 和类型include/lib/gpt_rme/gpt_rme.h,本节旨在提供更多详细信息和说明。
要创建 GPT 并启用粒度保护检查,需要在系统启动过程中以正确的顺序和正确的时间调用 API。
(1) 固件必须启用 MMU。
(2) 固件必须调用gpt_init_l0_tables以将 0 级表初始化为默认状态,即初始化所有 L0 描述符以允许对所有内存的所有访问。PPS 作为参数提供给此函数。
(3) DDR 由系统发现和初始化,然后将发现的 DDR 区域添加到 L1 PAS 区域以在下一步中初始化并由 GTSI 在运行时使用。
(4) 固件必须使用指向包含所需内存访问布局的结构gpt_init_pas_l1_tables数组的指针进行 调用。pas_region_tPGS 作为参数提供给该函数。
(5) 固件必须调用gpt_enable以通过设置正确的寄存器值来启用颗粒保护检查。
(6) 在使用粒度转换服务的系统中,运行时固件必须调用gpt_runtime_init以设置 GTSI 所需的数据结构,以查找 PAS 类型之间的表和转换粒度。
20.2.1. API 约束
API 允许的 PPS 和 PGS 值是文件中定义的枚举类型include/lib/gpt_rme/gpt_rme.h。
PPS 的允许值及其相应的大小。
- GPCCR_PPS_4GB(4GB 保护空间,0x100000000 字节)
- GPCCR_PPS_64GB(64GB 保护空间,0x1000000000 字节)
- GPCCR_PPS_1TB(1TB 保护空间,0x10000000000 字节)
- GPCCR_PPS_4TB(4TB 保护空间,0x40000000000 字节)
- GPCCR_PPS_16TB(16TB 保护空间,0x100000000000 字节)
- GPCCR_PPS_256TB(256TB 保护空间,0x1000000000000 字节)
- GPCCR_PPS_4PB(4PB 保护空间,0x10000000000000 字节)
PGS 的允许值及其相应的大小。
- GPCCR_PGS_4K(4KB 颗粒,0x1000 字节)
- GPCCR_PGS_16K(16KB 颗粒,0x4000 字节)
- GPCCR_PGS_64K(64KB 颗粒,0x10000 字节)
L0GPTSZ 的允许值以及相应的大小。
- GPCCR_L0GPTSZ_30BITS(1GB 区域,0x40000000 字节)
- GPCCR_L0GPTSZ_34BITS(16GB 区域,0x400000000 字节)
- GPCCR_L0GPTSZ_36BITS(64GB 区域,0x1000000000 字节)
- GPCCR_L0GPTSZ_39BITS(512GB 区域,0x8000000000 字节)
请注意,PPS、PGS 和 L0GPTSZ 定义的值是与大小相对应的编码值,而不是大小本身。为方便起见,提供了大小的解码十六进制表示。
L0 表内存有一些必须考虑的约束。
L0 表必须与表大小或 4096 字节对齐,以较大者为准。L0 表大小是总保护空间 (PPS) 除以每个 L0 区域 (L0GPTSZ) 的大小乘以每个 L0 描述符的大小(8 字节)。((PPS / L0GPTSZ) * 8)
L0 内存大小必须大于或等于表大小。
L0 内存必须属于 GPT_GPI_ROOT 类型的 PAS。
L1 内存也有一些限制。
L1 表必须与其大小对齐。每个 L1 表的大小是每个 L0 区域的大小 (L0GPTSZ) 除以颗粒大小 (PGS) 除以每个字节中控制的颗粒 (2)。((L0GPTSZ / PGS) / 2)
必须提供足够的 L1 内存来构建所有请求的 L1 表。
L1 内存必须属于 GPT_GPI_ROOT 类型的 PAS。
如果提供了无效的参数组合,API 将打印错误消息并返回负值。应检查 API 的返回值以确保配置成功。
20.2.2. L0 内存大小和对齐的示例计算
让 PPS=GPCCR_PPS_4GB 和 L0GPTSZ=GPCCR_L0GPTSZ_30BITS
我们可以用 ((PPS / L0GPTSZ) * 8) 找到总 L0 表大小
替换值得到这个:((0x100000000 / 0x40000000) * 8)
并求解得到 32 个字节。在这种情况下,4096 大于 32,因此 L0 表必须对齐到 4096 字节。
20.2.3. L1 表大小和对齐的示例计算
设 PGS=GPCCR_PGS_4K 和 L0GPTSZ=GPCCR_L0GPTSZ_30BITS
我们可以用 ((L0GPTSZ / PGS) / 2) 找到每个 L1 表的大小。
替代值:((0x40000000 / 0x1000) / 2)
并解决每个 L1 表获得 0x20000 字节。