3. 配置TZASC实现内存区域安全属性划分

配置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满足要求。
TZASC安全区域配置与访问验证流程 Secure World TZASC配置阶段 Non-Secure World 访问尝试阶段 结果判定 异常/拒绝 TZASC寄存器配置序列 1. 使能TZASC: CTRL[0] = 1 2. Region0: ADDR=0x80000000, SIZE=0x0F(64KB), ATTR=0x1(仅安全可访问) 3. Region0 CTRL = 0x1 (使能该区域) 非安全访问验证流程 NS CPU读0x80000000 TZASC检查 Region0属性 NS-bit=1 无权限 触发Data Abort 异常处理 判定标准:非安全访问触发异常 → 配置成功;正常读取返回 → 配置失败 注:实际验证需在支持TrustZone的硬件上切换CPU安全状态执行