目录
- 普通内存 (normal memory)
- 设备内存(device memory)
- arm64 mair_el1 系统寄存器及linux 对其配置
- 页表中的内存属性
- 总结
普通内存 (normal memory)
弱一致性(weakly ordered)。
存在分支预测,数据预取,高速缓存行预取,乱序加载等优化。
设备内存(device memory)
访问时有特定的时序限制。访问性能比普通内存差。
arm64 mair_el1 系统寄存器及linux 对其配置
linux中的几种memory 属性定义如下:
/*
* Memory types available.
*/
#define MT_DEVICE_nGnRnE 0
#define MT_DEVICE_nGnRE 1
#define MT_DEVICE_GRE 2
#define MT_NORMAL_NC 3
#define MT_NORMAL 4
#define MT_NORMAL_WT 5
其中 G/nG/R/nR/E/nE 的含义如下:
G:Gathering,内存聚合
R:Re-ordering,指令重排
E:Early Write Ackowledgement,提前写应答
_NC: Non-Cacheable,关闭高速缓存
_WT: write through 直写策略
在内核启动时,会对mair_el1 进行配置
从arm官网可以看到MAIR 这一列数值的含义
其中,开头的0b 是二进制的含义,后边dd, x, iiii这些具体是0还是1 及对应的含义要看如下几个表格
页表中的内存属性
ioremap 是将设备地址映射成虚拟地址的接口,从如下定义可以看到其使用了上述提到的内存属性 PROT_DEVICE_nGnRE 等
#define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
#define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
#define ioremap_wt(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
// 其中
typedef u64 pteval_t;
typedef struct { pteval_t pgprot; } pgprot_t;
#define pgprot_val(x) ((x).pgprot)
#define __pgprot(x) ((pgprot_t) { (x) } )
如下属性会直接或到64位pte 中。
/*arch/arm64/include/asm/pgtable-prot.h*/
#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE))
#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT))
#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
/*arch/arm64/include/asm/pgtable-hwdef.h*/
#define PTE_ATTRINDX(t) (_AT(pteval_t, (t)) << 2)
页表属性占了pte 中的bit[4:2]。因此mmu 在查询当前页表的内存属性时,会使用pte 的bit[4:2] 拿到AttrIndex,然后找到系统寄存器 MAIR 中下标为AttrIndex 的内存属性。
总结
1、在linux arm64 中,共有MT_DEVICE_nGnRnE 等共6种内存属性
2、arm64 系统寄存器MAIR 可以配置共8种内存属性,每个内存属性占用8bit。linux 仅配置了6种。
3、页表描述符中,bit[4:2] 为AttrIndx。当前页的内存属性,就是MAIR 寄存器中下标为AttrIndx 的属性。
参考
《Arm® Architecture Reference Manual for A-profile architecture》(DDI0487K_a_a-profile_architecture_reference_manual.pdf)