页表转换
arm64在硬件体系结构上支持4级的每页大小为4K的页表转换,也支持3级的页大小64KB的页表转换。
在linux arm64中,如果页的大小为4KB,使用3级页表转换或者4级页表转换,用户空间和内核空间都支持有39bit(512GB)或者48bit(256TB)大小的虚拟地址空间。
如果页的大小为64KB,就只有2级页表转换,支持42bit(4TB)大小的虚拟地址,用户空间和内核空间也大小一样。
地址分布
虚拟地址都用64位无符号数表示。
用户虚拟地址从高位的63到低位的48都是0,内核虚拟地址则相反,63~48都是1. TTBR x(Translation table base register)的选择是通过虚拟地址的第63 bit位来确定的。swapper_pg_dir只包含内核地址映射,而用户
pgd 只包含用户地址映射,swapper_pg_dir 指向的地址只会写入到 TTBR1,绝不会写入到TTBR0。
AArch64 Linux memory layout with 4KB pages + 3 levels: Start End Size Use ----------------------------------------------------------------------- 0000000000000000 0000007fffffffff 512GB user ffffff8000000000 ffffffffffffffff 512GB kernel
AArch64 Linux memory layout with 4KB pages + 4 levels: Start End Size Use ----------------------------------------------------------------------- 0000000000000000 0000ffffffffffff 256TB user ffff000000000000 ffffffffffffffff 256TB kernel
AArch64 Linux memory layout with 64KB pages + 2 levels: Start End Size Use ----------------------------------------------------------------------- 0000000000000000 000003ffffffffff 4TB user fffffc0000000000 ffffffffffffffff 4TB kernel
AArch64 Linux memory layout with 64KB pages + 3 levels: Start End Size Use ----------------------------------------------------------------------- 0000000000000000 0000ffffffffffff 256TB user ffff000000000000 ffffffffffffffff 256TB kernel
想看内核虚拟地址布局的详细情况,可以通过观察内核boot日志。
Translation table lookup with 4KB pages: +--------+--------+--------+--------+--------+--------+--------+--------+ |63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| +--------+--------+--------+--------+--------+--------+--------+--------+ | | | | | | | | | | | v | | | | | [11:0] in-page offset | | | | +-> [20:12] L3 index | | | +-----------> [29:21] L2 index | | +---------------------> [38:30] L1 index | +-------------------------------> [47:39] L0 index +-------------------------------------------------> [63] TTBR0/1
Translation table lookup with 64KB pages: +--------+--------+--------+--------+--------+--------+--------+--------+ |63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| +--------+--------+--------+--------+--------+--------+--------+--------+ | | | | | | | | | v | | | | [15:0] in-page offset | | | +----------> [28:16] L3 index | | +--------------------------> [41:29] L2 index | +-------------------------------> [47:42] L1 index +-------------------------------------------------> [63] TTBR0/1
[ 0.000000] [0: swapper: 0] Virtual kernel memory layout:
57 [ 0.000000] [0: swapper: 0] vmalloc : 0xffffff8000000000 - 0xffffffbdbfff0000 ( 246 GB)
58 [ 0.000000] [0: swapper: 0] vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000 ( 8 GB maximum)
60 [ 0.000000] [0: swapper: 0] 0xffffffbdc0000000 - 0xffffffbde4000000 ( 576 MB actual)
61 [ 0.000000] [0: swapper: 0] fixed : 0xffffffbffa7fd000 - 0xffffffbffac00000 ( 4108 KB)
62 [ 0.000000] [0: swapper: 0] PCI I/O : 0xffffffbffae00000 - 0xffffffbffbe00000 ( 16 MB)
63 [ 0.000000] [0: swapper: 0] modules : 0xffffffbffc000000 - 0xffffffc000000000 ( 64 MB)
64 [ 0.000000] [0: swapper: 0] memory : 0xffffffc000000000 - 0xffffffc900000000 ( 36864 MB)
65 [ 0.000000] [0: swapper: 0] .init : 0xffffffc0011e1000 - 0xffffffc0012a9000 ( 800 KB)