linux armv8 MMU 相关知识学习QA
本文是原「蜗窝讨论区」的历史存档(2016-12-12),来自版块「Linux kernel技术问答」,共 13 帖。讨论区已停止服务,此处仅供查阅。
作为一个嵌入式工程师,平时对MMU相关配置是敬而远之的。因为linux kernel已经做得很完善。我们最经常使用的就是内存申请相关接口。但是越是难懂的东西,说明她的精髓越是掌握在少数人的手里面。为了自己更好的了解ARM V8架构。我决定跟随linuxer的步伐,啃一啃相关的代码。但是我现在是一张白纸,所以经过跟linuxer大哥讨论。我决定把我阅读文章以及文档的相关问题都一一记录下来。这样如果有新人,也对这一块感兴趣。可以查看此贴,希望能有所帮助。
hi linuxer Considering the resolution of the maximum IA range of 48 bits, with a translation granule size of 2n bytes: • The least-significant n bits of the IA address the memory page. This means OA[(n-1):0]=IA[(n-1):0]. • The remaining (48-n) bits of the IA, IA[47:n], must be resolved by the address translation. • A translation table descriptor is 8 bytes. Therefore: — A complete translation table holds 2(n-3) descriptors.(2的n-3 次方) — A single level of translation can resolve a maximum of (n-3) bits of address
n=12/14/16 2的n-3次方,这里不太懂
一个完整的转换表 是什么意思?? 是说一次完整的从IA到OA的转换吗?
我自己的系统一次完整的虚拟地址到物理地址的转换,VA_BITS=39, 4K PAGES,PGTABLE_LEVLE=39
VIRTUAL PHYSICAL
ffffffc000081000 80081000
PAGE DIRECTORY: ffffffc0012a9000========这里是TTBR0_EL1的值吗? PGD: ffffffc0012a9800 => 1da5fe003====这个PGD得到的值,怎么找到PMD的呢? PMD: ffffffc15a5fe000 => 80000711 PAGE: 80000000 (2MB)===这里这个PAGE是什么意思?为什么是2MB
PTE PHYSICAL FLAGS 80000711 80000000 (VALID|SHARED|AF)====711就是FLAGS的数值?
PAGE PHYSICAL MAPPING INDEX CNT FLAGS
ffffffbe01c01c38 80081000 0 0 1 400 reserved 最下面这个PAGE又是什么意思呢?
tigger 写道: hi linuxer Considering the resolution of the maximum IA range of 48 bits, with a translation granule size of 2n bytes: • The least-significant n bits of the IA address the memory page. This means OA[(n-1):0]=IA[(n-1):0]. • The remaining (48-n) bits of the IA, IA[47:n], must be resolved by the address translation. • A translation table descriptor is 8 bytes. Therefore: — A complete translation table holds 2(n-3) descriptors.(2的n-3 次方) — A single level of translation can resolve a maximum of (n-3) bits of address
n=12/14/16 2的n-3次方,这里不太懂
对于ARMv8,一个Translation table的size是固定的,就是一个page size,假设其大小是2^n个Byte,一个描述符的大小是8个Byte,也就是2^3,因此一个Translation table可以容纳的描述符的数目是2^(n-3)。
tigger 写道: 一个完整的转换表 是什么意思?? 是说一次完整的从IA到OA的转换吗?
能不能给出上下文?
tigger 写道: 我自己的系统一次完整的虚拟地址到物理地址的转换,VA_BITS=39, 4K PAGES,PGTABLE_LEVLE=39 VIRTUAL PHYSICAL
ffffffc000081000 80081000
PAGE DIRECTORY: ffffffc0012a9000========这里是TTBR0_EL1的值吗? PGD: ffffffc0012a9800 => 1da5fe003====这个PGD得到的值,怎么找到PMD的呢? PMD: ffffffc15a5fe000 => 80000711 PAGE: 80000000 (2MB)===这里这个PAGE是什么意思?为什么是2MB
PTE PHYSICAL FLAGS 80000711 80000000 (VALID|SHARED|AF)====711就是FLAGS的数值?
PAGE PHYSICAL MAPPING INDEX CNT FLAGS
ffffffbe01c01c38 80081000 0 0 1 400 reserved 最下面这个PAGE又是什么意思呢?
对于你的系统,映射有两种: 1、PGD(9 bits)--->PMD(9 bits)--->PTE(9 bits)--->PAGE(12 bits) 2、PGD(9 bits)--->PMD(9 bits)--->SECTION(21 bits)
第一个问题:是的,TTBR0_EL1指向了内核空间的PAGE DIRECTORY: ffffffc0012a9000
第三个问题:由于采用了第二种方式的映射,因此PMD中是block descriptor,因此以此mapping了2M size的block,在这个场景中使用PAGE不是太规范
第二个问题和地址映射相关,你给出的地址映射是:
VIRTUAL PHYSICAL
ffffffc000081000 80081000
对虚拟地址0xffffffc000081000 可以进行分解: pgd index:9 bits,100000000(二进制) pmd index:9 bits,000000000(二进制) section offset:21 bits,0x81000
因此,对于虚拟地址0xffffffc000081000 而言,PGD在TTBR0_EL1可以获取到,是ffffffc0012a9000,pgd index是256,因此在PGD中可以找到对应的描述符的位置是ffffffc0012a9000 + 256 x 3 = ffffffc0012a9800,该描述符的内容是1da5fe003,在这个描述符中bit[47:21]是output address,从而可以得到PMD的位置ffffffc15a5fe000 。
第四个问题:更准确的说是memory attribute,可以参考ARMv8的手册来解析这些bit field 第五个问题:我不知道你说的场景是什么,能不能再说明这些字符的出处?
linuxer 写道:
tigger 写道: 我自己的系统一次完整的虚拟地址到物理地址的转换,VA_BITS=39, 4K PAGES,PGTABLE_LEVLE=39 VIRTUAL PHYSICAL
ffffffc000081000 80081000
PAGE DIRECTORY: ffffffc0012a9000========这里是TTBR0_EL1的值吗? PGD: ffffffc0012a9800 => 1da5fe003====这个PGD得到的值,怎么找到PMD的呢? PMD: ffffffc15a5fe000 => 80000711 PAGE: 80000000 (2MB)===这里这个PAGE是什么意思?为什么是2MB
PTE PHYSICAL FLAGS 80000711 80000000 (VALID|SHARED|AF)====711就是FLAGS的数值?
PAGE PHYSICAL MAPPING INDEX CNT FLAGS
ffffffbe01c01c38 80081000 0 0 1 400 reserved 最下面这个PAGE又是什么意思呢?
对于你的系统,映射有两种: 1、PGD(9 bits)--->PMD(9 bits)--->PTE(9 bits)--->PAGE(12 bits) 2、PGD(9 bits)--->PMD(9 bits)--->SECTION(21 bits)
第一个问题:是的,TTBR0_EL1指向了内核空间的PAGE DIRECTORY: ffffffc0012a9000
第三个问题:由于采用了第二种方式的映射,因此PMD中是block descriptor,因此以此mapping了2M size的block,在这个场景中使用PAGE不是太规范
第二个问题和地址映射相关,你给出的地址映射是:
VIRTUAL PHYSICAL
ffffffc000081000 80081000
对虚拟地址0xffffffc000081000 可以进行分解: pgd index:9 bits,100000000(二进制) pmd index:9 bits,000000000(二进制) section offset:21 bits,0x81000
因此,对于虚拟地址0xffffffc000081000 而言,PGD在TTBR0_EL1可以获取到,是ffffffc0012a9000,pgd index是256,因此在PGD中可以找到对应的描述符的位置是ffffffc0012a9000 + 256 x 3 = ffffffc0012a9800,该描述符的内容是1da5fe003,在这个描述符中bit[47:21]是output address,从而可以得到PMD的位置ffffffc15a5fe000 。
第四个问题:更准确的说是memory attribute,可以参考ARMv8的手册来解析这些bit field 第五个问题:我不知道你说的场景是什么,能不能再说明这些字符的出处?
1:该描述符的内容是1da5fe003,在这个描述符中bit[47:21]是output address,从而可以得到PMD的位置ffffffc15a5fe000 。 这里我还是没有看懂,PMD是基于那个地址得到的现在的值??为什么最后的003,3这个数值不用了?
2:256 x 3 这里应该是笔误了,从结果来看应该是256x2^3=0x800
3:这里这个page 又是啥意思? PAGE PHYSICAL MAPPING INDEX CNT FLAGS ffffffbe01c01c38 80081000 0 0 1 400 reserved
1、PGD中描述符的格式定义就在ARMv8的手册里,你可以去看看,我这里只是贴上图片

2、呵呵,是写错了。
3、没有上下文,我也不知道这里的PAGE是什么意思。
linuxer 写道: 1、PGD中描述符的格式定义就在ARMv8的手册里,你可以去看看,我这里只是贴上图片 /forum/plugins/ezbbc/img/11/1481626326_table-descriptor.jpg
2、呵呵,是写错了。
3、没有上下文,我也不知道这里的PAGE是什么意思。
老大就是厉害啊,小弟茅塞顿开。 我的问题又来了 1:根据我的理解如果是4k page设置的话,每一个level的descriptor地址都应该是4k对齐的。所以地址应该是这样的形式,假设我一共需要16张page table L0=TTBRX L1=[0x0000,0x1000,0x2000,...0xf000] L2=[0x10000,0x11000,0x12000,...0x1f000] L3=[0x20000,0x21000,0x22000,...0x2f000] 上面这些空间必须预留下来对吗? 2:我能不能修改某些寄存器直接L0=>L3 L3里面就存放page entry 3:我不想使用block 方式,因为block size 太大了 最小都是2MB
1、这个问题比较诡异,我一时不知道说什么好
2、不能,可以TTBR--->L2--->L3,也可以TTBR--->L1--->L2--->L3,或者映射过程包括L0~L3,但是L0--->L3是不行的
3、大的mapping size也是有好处的,例如TLB的命中,减少page fault的次数等。
hi linuxer 文章 内存初始化代码分析(一):identity mapping和kernel image mapping
例子3:当虚拟地址是39个bit,4k page size,这时候page level等于3,映射关系是PGD(L1)--->PMD(L2)--->Page table(L3)--->page。由于是4k page,因此采用section mapping,映射关系是PGD(L1)--->PMD(L2)--->section。在create_pgd_entry函数中将创建PGD这一个中间level。 4k page 一定采用section mapping,这个是arm规定的吗??我没找到定义这个的地方。
tigger 写道: hi linuxer 文章 内存初始化代码分析(一):identity mapping和kernel image mapping
例子3:当虚拟地址是39个bit,4k page size,这时候page level等于3,映射关系是PGD(L1)--->PMD(L2)--->Page table(L3)--->page。由于是4k page,因此采用section mapping,映射关系是PGD(L1)--->PMD(L2)--->section。在create_pgd_entry函数中将创建PGD这一个中间level。 4k page 一定采用section mapping,这个是arm规定的吗??我没找到定义这个的地方。
这个你好像在下ARM64的启动过程之二中讲到了 ARM64_SWAPPER_USES_SECTION_MAPS这个宏定义是说明了swapper/idmap的映射是否使用section map。什么是section map呢?我们用一个实际的例子来描述。假设VA是48 bit,page size是4K,那么,在地址映射过程中,地址被分成9(level 0) + 9(level 1) + 9(level 2) + 9(level 3) + 12(page offset),对于kernel image这样的big block memory region,使用4K的page来mapping有点得不偿失,在这种情况下,可以考虑让level 2的Translation table entry指向一个2M 的memory region,而不是下一级的Translation table。所谓的section map就是指使用2M的为单位进行映射。当然,不是什么情况都是可以使用section map,对于kernel image,其起始地址是2M对齐的,因此block size是2M的情况下才OK,对于PAGE SIZE是16K,其Block descriptor指向了一个32M的内存块,PAGE SIZE是64K的时候,Block descriptor指向了一个512M的内存块,因此,只有4K page size的情况下,才可以启用section map
