18

修志龙_ZenonXiu · 2022年10月22日 · 上海市浦东新区

如何设置MMU访问页表的属性

众所周知,MMU的页表是由软件建立在外部内存中的。实际上有两条硬件路径需要访问这个页表:

  1. MMU硬件进行page table walk时,它会读取查找这个页表。
  2. 软件修改这个页表的页表项(Page table entry)时,需要load/store指令通过load-store unit (LSU)访问。

MMU page table walk

MMU page table walk这条路径上对全部页表项访问的属性(Cacheability, Shareability)是通过寄存器TCR_ELx.IRGNy, TCR_ELx.ORGNy, TCR_ELx.SHy (x=1, 2 or 3, and y= 0 or 1)来设置的。
TCR_ELx.SHy可以设置MMU page table walk这条路径上对页表访问的Shareability属性。TCR_ELx.IRGNy, TCR_ELx.ORGNy可以分别设置访问的Inner 和Outer Cacheability属性为:

*  Normal memory, Non-cacheable.
*  Normal memory, Write-Back Read-Allocate Write-Allocate Cacheable.
*  Normal memory, Write-Through Read-Allocate No Write-Allocate Cacheable.
*  Normal memory, Write-Back Read-Allocate No Write-Allocate Cacheable.

当设置为Non-cacheable时,MMU page table walk时不查找cache, 直接在外部内存中查找页表。

MMU table-Page-3.jpg

当设置为Cacheable时, MMU page table walk unit可以将外部内存中的页表项缓存在cache中,page table walk时先查找cache,检查需要的页表项是否在cache中,如果不在则继续去外部内存中页表中查找。

MMU table-Page-4.jpg

软件修改页表

当MMU enable时,软件对页表本身的访问也是使用虚拟地址,因而MMU page table中某些页表项是用来描述页表本身所在的 page的访问属性,软件使用load/store指令对页表项的访问使用这个属性。

1.png

假设,要修改下图中标为绿色的页表项,这个页表项所在的page的属性由图中标为橙色的页表项描述。

  1. load/store指令需要利用上一章节‘MMU page table walk’的过程,通过MMU获得访问的地址(对标为绿色的页表项的访问)对应的属性(在标为橙色的页表项中描述)
  2. 获取到物理地址和访问属性后,LSU接下来可以访问页表项(标为绿色)
    a. 如果要修改的页表项访问属性为Normal Non Cacheable/Device type
    那么这个load/store访问的页表项不在cache中缓存,不查找cache
    MMU table-Page-5.jpg
    b. 如果要修改的页表项访问属性为Normal Cacheable
    那么这个load/store访问的页表项可以在cache中缓存
    MMU table-Page-6.jpg

如何配置MMU page table walk的访问属性

如果需要在MMU enable的情况下,运行时修改页表项。如上所述,因为MMU page table walk的访问属性和load/store访问页表本身的访问属性是分别设置的,不匹配的设置可能会导致一致性问题。
例如,如果MMU page table walk的访问属性设置为 Normal Cacheable,而load/store访问页表本身的访问属性设置为Normal Non Cacheable,

  1. MMU page table walk查找页表时可以cache这些页表项。
  2. 接下来软件通过load/store修改页表项时,不会在cache中查找,而直接修改在外部内存中的页表,不会更新cache。
  3. 下一次MMU page table walk时,MMU table walk依然只看到cache中stale的页表项,而不使用步骤2更新的页表项。

MMU table-Page-8.jpg

因此,在需要动态修改页表的情况下,软件最好将MMU page table walk的访问属性和load/store访问页表本身的访问属性设置为一样的,都是Normal Cacheable或都是Normal Non Cacheable。Shareability属性也应该设置为一样。

以Linux kernel为例

Linux kernel会动态修改页表。
如以下代码所示,
https://elixir.bootlin.com/li...
https://elixir.bootlin.com/li...
https://elixir.bootlin.com/li...

mov_q    tcr, TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \
            TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \
            TCR_TBI0 | TCR_A1 | TCR_KASAN_SW_FLAGS
/* PTWs cacheable, inner/outer WBWA */
#define TCR_CACHE_FLAGS    TCR_IRGN_WBWA | TCR_ORGN_WBWA

#define TCR_SMP_FLAGS    TCR_SHARED
#define TCR_SHARED        (TCR_SH0_INNER | TCR_SH1_INNER) 

MMU page table walk的访问属性设置为 Inner Shareable Normal Inner/Outer Write-Back Write-Allocate

而Linux kernel的页表是从一般的page中分配的,load/store对页表本身的访问属性也是Inner Shareable Normal Inner/Outer Write-Back Write-Allocate
https://elixir.bootlin.com/li...

#define PROT_NORMAL        (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL)) 

#define _PROT_DEFAULT        (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) 

#define _PAGE_DEFAULT        (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))

因此Linux Kernel中,MMU page table walk的访问属性和load/store访问页表本身的访问属性设置都是Inner Shareable Normal Inner/Outer Write-Back Write-Allocate,因为这个属性是可以利用硬件一致性,在kernel中使用set_pte函数修改页表项时,不需要附加对这个页表项的cache maintenance操作。

推荐阅读
关注数
8644
内容数
58
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息