MAIR_EL1 简介
MAIR_EL1是 ARMv8 架构内存管理的核心它通过一个索引机制来定义内存的“性格”。简单来说页表项通过一个3位索引AttrIndx来引用MAIR_EL1中预先定义好的8种内存属性之一从而避免了在每个页表项中都重复描述这些复杂的属性。寄存器结构MAIR_EL1是一个64位寄存器它被均匀地划分为8个字段每个字段宽度为8位用于定义一种内存属性。assemblyMAIR_EL1 的位域分布如下63-0 位: -------------------------------------------------- | Attr7 (63-56) | Attr6 (55-48) | ... | Attr0 (7-0) | --------------------------------------------------字段索引 (n): 8个字段的索引从0到7。选择机制: 页表描述符的bit[4:2](即AttrIndx字段) 用于选择Attrn。例如若页表项的AttrIndx为0b001则 CPU 会使用MAIR_EL1中Attr1字段的值。支持的属性值ARMv8 架构将内存主要分为两大类设备内存 (Device Memory)和普通内存 (Normal Memory)。MAIR_EL1的每个8位字段必须填入符合特定编码规则的值。1. 设备内存 (Device Memory)编码格式:0b0000dd00(8位)属性说明: 用于映射外设地址空间如UART、GPIO其访问行为是严格受控的通常不可缓存。dd编码详解:二进制类型行为说明0b00Device-nGnRnE最强限制不允许聚合Gathering、不允许重排序Re-ordering、不提前写应答Early Write Acknowledge。这是最安全的设备内存配置适用于UART等敏感外设。0b01Device-nGnRE允许提前写应答但不允许聚合和重排序。0b10Device-GRE允许聚合、重排序和提前写应答性能更高但需设备支持。2. 普通内存 (Normal Memory)编码格式:0booooiiii(8位)属性说明: 用于映射RAM等常规内存。CPU可对其进行缓存、预取和乱序执行以提升性能。编码详解:oooo(Outer)和iiii(Inner): 分别控制外部和内部共享域如多核集群内/间的缓存策略。RW编码: 表内RW字段共同决定策略:二进制 (oooo或iiii)策略0b0000Non-cacheable(不可缓存)0b0001Write-Through(写透)0b0010Write-Back, Write-Allocate(回写写分配)0b0011Write-Back, no Write-Allocate(回写非写分配)Linux 内核的配置参考Linux 内核中预定义了几种常用的内存类型和对应的MAIR_EL1编码可以直接参考使用。属性名描述MAIR_EL1 编码值 (8位)MT_DEVICE_nGnRnE强限制设备内存用于 UART 等0b00000000(0x00)MT_DEVICE_nGnRE允许提前应答的设备内存0b00000100(0x04)MT_DEVICE_GRE允许聚合和重排序的设备内存0b00001000(0x08)MT_NORMAL_NC普通内存不可缓存0b01000100(0x44)MT_NORMAL普通内存回写、写分配0b11111111(0xFF)MT_NORMAL_WT普通内存写透0b10101010(0xAA)使用示例假设需要配置一个支持回写的普通内存索引0和一个严格的设备内存索引1代码片段如下// 定义宏 #define NORMAL_MEM_ATTR 0xFF // 用于索引 0 #define DEVICE_MEM_ATTR 0x00 // 用于索引 1 // 组装 MAIR_EL1 的值 unsigned long mair_val (unsigned long)DEVICE_MEM_ATTR 8 | NORMAL_MEM_ATTR; // 写入寄存器 __asm__ volatile(msr mair_el1, %0 : : r (mair_val)); __asm__ volatile(isb); // 确保配置生效在页表项中设置AttrIndx字段bit[4:2]为0b000即选择普通内存为0b001则选择设备内存。配置的关键步骤计算并写入: 根据需求计算出64位值通过MSR MAIR_EL1, Xn写入。刷新 TLB: 修改后必须刷新TLB确保旧属性被清除使新配置生效。使用TLBI *和DSB/ISB指令。使能 MMU: 确保 MMU 已使能 (SCTLR_EL1.M 1)。与页表协同: 页表项中的AttrIndx必须与MAIR_EL1中的索引配置相匹配