ARM64内存属性及MAIR配置

内存属性分为2类:

Normal型:sram或者dram那样的内存空间,一般都是过cache的(当然也可不过cache,如外设访问的地址空间,标记为NC)

device型:设备寄存器那样的io空间,都不会过cache。Device属性的内存空间还有下面三种子属性,都有打开和关闭的定义。

G(gather:对多个memory的访问可以合并) nG与之相反

R(Reordering:对内存访问指令进行重排) nR与之相反

E(Early Write Acknowledgement hint:写操作的ack可提早应答) nE与之相反

MAIR寄存器定义如下:

Linux预先定义了6种内存属性,分别存在MAIR寄存器的attr0~attr5。内存页表属性部分可以选择这个寄存器的某个index,范围(0~5)作为自己的属性。

  /*
   * 上面内容我们说到了, 页表entry表明内存是普通内存, 就是结合这里的初始化来指明的,
   * PMD_ATTRINDX(MT_NORMAL)是4, 这其实是一个index, 指向MAIR寄存器的[4*8+7:4*8],
   * MAIR寄存器一共有8组, KERNEL用了6组, 每组有8bit, 每个bit都有相应的含义.
   * 具体参考手册, 这里就不细说了, 点到为止
   */

   /*
    * Memory region attributes for LPAE:
    *
    *   n = AttrIndx[2:0]
    *                  n   MAIR
    *   DEVICE_nGnRnE  000 00000000
    *   DEVICE_nGnRE   001 00000100
    *   DEVICE_GRE     010 00001100
    *   NORMAL_NC      011 01000100
    *   NORMAL         100 11111111
    *   NORMAL_WT      101 10111011
    */

ldr x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \

MAIR(0x04, MT_DEVICE_nGnRE) | \

MAIR(0x0c, MT_DEVICE_GRE) | \

MAIR(0x44, MT_NORMAL_NC) | \

MAIR(0xff, MT_NORMAL) | \

MAIR(0xbb, MT_NORMAL_WT)

msr mair_el1, x5 写入预定义的5种内存属性值

如上所述,Linux在cpu初始化时建立了6种页表属性索引

ARM64 cpu可以通过页表中设置的页表属性配置,决定其内存或寄存器访问行为(DEVICE_nGnRE/nGnRE/GRE、NORMAL_NC/WT/NORMAL)。


 

#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))


#define PROT_DEVICE_nGnRnE  (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRIDX(MT_DEVICE_nGnRnE))

#define PROT_DEVICE_nGnRE  (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRIDX(MT_DEVICE_nGnRE))

#define PROT_NORMAL_NC  (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRIDX(MT_NORMAL_NC))

#define PROT_NORMAL_WT  (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRIDX(MT_NORMAL_WT))

#define PROT_NORMAL  (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRIDX(MT_NORMAL))


#define PTE_ATTRINDX(t)   (_AT(pteval_t, (t)) << 2)

PTE_ATTRINDX在页表中的位置 bit[4:2]

关于使用页表的场景:

1、内核代码中使用alloc_pages从伙伴系统内存中申请

2、设备驱动代码使用device-tree预留内存地址建立页表映射访问(内存或寄存器,使用ioremap较多)

    ioremap() / ioremap_wc()

    pci_iomap() ==> pci_iomap_range() ==> ioremap()

    pci_iomap_wc() ==> pci_iomap_wc_range() ==> ioremap_wc()

3、设备驱动一致性内存,dma_alloc_coherent如何使用内存?attrindex使用哪个?
 

  arch/arm64/mm/dma-mapping.c  swiotlb_dma_ops

   __dma_alloc(dev, size, dma_handle, flags, attrs)

   prot = __get_dma_pgprot(attr, PAGE_KERNEL, false); PAGE_KERNEL = __pgprot(PROT_NORMAL)    coherent=false,prot最终修改为 PTE_ATTRINDX(MT_NORMAL_NC)

  ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs);

  coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP, prot, NULL)

       dma_common_pages_remap(pages, size, VM_USERMAP, prot, NULL); 建立NORMAL页表

PoC与PoU的区别和使用范围?

内存Inner和Outer域如何界定?

多核cpu或多cluster cpu如果跑一个系统则是inner的

一般cpu与DMA,cpu与GPU都是outer的

  • 13
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值