3. 配置TZASC实现内存区域安全属性划分
任务说明
本案例使用TZASC(TrustZone Address Space Controller)将一段DRAM物理地址区域配置为安全世界独占,并验证非安全世界访问该区域时被阻止。目标地址区域为0x8000_0000 ~ 0x8000_FFFF(64KB),TZASC寄存器基地址为0xE120_0000。
TZASC配置实现
/* tzasc_config.c */
#include <stdint.h>
#define TZASC_BASE 0xE1200000UL
#define TZASC_REGION_CTRL 0x30 /* Region Control Register偏移 */
#define TZASC_REGION_ADDR 0x34 /* Region Address Register偏移 */
#define TZASC_REGION_SIZE 0x38 /* Region Size Register偏移 */
#define TZASC_REGION_ATTR 0x3C /* Region Attributes Register偏移 */
/* 安全区域起始地址(需按64KB对齐) */
#define SECURE_REGION_BASE 0x80000000UL
/* 区域大小:64KB = 0x10000 */
#define SECURE_REGION_SIZE 0x10000UL
/* 使能TZASC */
static void tzasc_enable(void)
{
volatile uint32_t *ctrl = (volatile uint32_t *)(TZASC_BASE + 0x00);
*ctrl |= 0x1; /* Bit0: TZASC_ENABLE */
}
/* 配置Region0为安全区域 */
static void tzasc_config_region0(void)
{
volatile uint32_t *reg_ctrl = (volatile uint32_t *)(TZASC_BASE + TZASC_REGION_CTRL);
volatile uint32_t *reg_addr = (volatile uint32_t *)(TZASC_BASE + TZASC_REGION_ADDR);
volatile uint32_t *reg_size = (volatile uint32_t *)(TZASC_BASE + TZASC_REGION_SIZE);
volatile uint32_t *reg_attr = (volatile uint32_t *)(TZASC_BASE + TZASC_REGION_ATTR);
/* 1. 关闭Region0 */
*reg_ctrl = 0x0;
/* 2. 设置区域起始地址(bit31:20为地址,低20位清零) */
*reg_addr = SECURE_REGION_BASE & 0xFFF00000UL;
/* 3. 设置区域大小:64KB对应编码值0x0F(2^(15+1)=64KB) */
*reg_size = 0x0F;
/* 4. 设置属性:bit0=1使能,bit1=0非安全世界不可访问 */
*reg_attr = 0x1;
/* 5. 重新使能Region0 */
*reg_ctrl = 0x1;
}
/* 初始化TZASC并配置安全区域 */
void tzasc_protect_dram(void)
{
tzasc_enable();
tzasc_config_region0();
}
非安全访问验证代码
/* tzasc_verify.c */
#include <stdint.h>
#include <stdio.h>
extern void tzasc_protect_dram(void);
/* 模拟非安全世界访问(实际环境中由NS-bit=1的CPU访问) */
static int ns_world_read(uint32_t addr)
{
volatile uint32_t *p = (volatile uint32_t *)addr;
uint32_t val;
/* 在真实硬件中,此访问会触发TZASC拒绝并产生异常 */
val = *p;
printf("NS read @0x%08X = 0x%08X\n", addr, val);
return 0;
}
int main(void)
{
/* 先配置TZASC */
tzasc_protect_dram();
/* 尝试从非安全世界读取被保护区域 */
printf("Attempt NS access to secure region...\n");
ns_world_read(0x80000000UL);
/* 若执行到这里说明访问未被阻止(仅用于演示流程) */
printf("Verification complete.\n");
return 0;
}
编译与运行
# 交叉编译(以ARMv8-A为例)
aarch64-linux-gnu-gcc -c tzasc_config.c -o tzasc_config.o
aarch64-linux-gnu-gcc -c tzasc_verify.c -o tzasc_verify.o
aarch64-linux-gnu-gcc tzasc_config.o tzasc_verify.o -o tzasc_test
# 在目标硬件上运行(需处于Secure World)
./tzasc_test
验证方法与判定标准
验证路径:在支持TrustZone的硬件平台(如ARM Juno或RPi3+TrustZone固件)上,先以安全世界身份运行tzasc_protect_dram()完成配置,然后切换CPU的NS位为1(非安全状态),再执行对0x8000_0000的读取指令。
预期结果:
- 若TZASC配置正确,非安全世界的读取会触发权限异常(Data Abort),系统进入异常处理,程序不会打印“NS read”成功信息;
- 若TZASC未生效或配置错误,非安全世界能正常读取该地址并打印数值。
判定标准:观察到非安全访问触发异常(异常向量指向TZASC错误处理)即判定为通过;若正常读取返回则判定失败。本案例代码中的ns_world_read()仅为演示调用流程,在真实硬件上该函数不会正常返回。
关键配置说明
- Region Size编码:0x0F表示区域大小为2^(15+1)=64KB,与目标区域匹配;
- 属性寄存器bit0:置1使能该区域的安全访问控制;
- 属性寄存器bit1:保持0,表示非安全世界对该区域无访问权限;
- 地址对齐:区域起始地址必须与大小编码对应的粒度对齐(64KB),本案例中
0x8000_0000满足要求。