ARM64
根据Linux内核配置文件可以配置页大小和虚拟地址位宽,ARM64支持4K/16K/64K的Page Size,支持39/48位的VA虚拟地址位宽。
# CONFIG_ARM64_4K_PAGES is not set
# CONFIG_ARM64_16K_PAGES is not set
CONFIG_ARM64_64K_PAGES=y
# CONFIG_ARM64_VA_BITS_42 is not set
CONFIG_ARM64_VA_BITS_48=y
CONFIG_ARM64_VA_BITS=48
我们这里明显用的是4k/48bit的配置
如果va=39,则user 和 kernel 分别是512GB
AArch64 Linux memory layout with 4KB pages + 3 levels:
Start End Size Use
-----------------------------------------------------------------------
0000000000000000 0000007fffffffff 512GB user
ffffff8000000000 ffffffffffffffff 512GB kernel
如果va=48,则user和kernel 分别是256TB
AArch64 Linux memory layout with 4KB pages + 4 levels:
Start End Size Use
-----------------------------------------------------------------------
0000000000000000 0000ffffffffffff 256TB user
ffff000000000000 ffffffffffffffff 256TB kernel
下面是kernel实际跑起来的memory 配置,可以看到kernel是从0xffff 0000 0000 0000 到0xffff842ffc000000 只用了132TB
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] modules : 0xffff000000000000 - 0xffff000008000000 ( 128 MB)
[ 0.000000] vmalloc : 0xffff000008000000 - 0xffff7dffbfff0000 (129022 GB)
[ 0.000000] .text : 0xffff000008080000 - 0xffff000008b20000 ( 10880 KB)
[ 0.000000] .rodata : 0xffff000008b20000 - 0xffff000008f80000 ( 4480 KB)
[ 0.000000] .init : 0xffff000008f80000 - 0xffff0000090d0000 ( 1344 KB)
[ 0.000000] .data : 0xffff0000090d0000 - 0xffff0000092a5a00 ( 1879 KB)
[ 0.000000] .bss : 0xffff0000092a5a00 - 0xffff00000992d9f0 ( 6688 KB)
[ 0.000000] fixed : 0xffff7dfffe7fd000 - 0xffff7dfffec00000 ( 4108 KB)
[ 0.000000] PCI I/O : 0xffff7dfffee00000 - 0xffff7dffffe00000 ( 16 MB)
[ 0.000000] vmemmap : 0xffff7e0000000000 - 0xffff800000000000 ( 2048 GB maximum)
[ 0.000000] 0xffff7e0000000000 - 0xffff7e10bff00000 ( 68607 MB actual)
[ 0.000000] memory : 0xffff800000000000 - 0xffff842ffc000000 (4390848 MB)
如果是64K page,则user 和 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
首先我们以最为常用的4KB page + 3 levels配置为例去介绍:
AArch64 Linux memory layout with 4KB pages + 3 levels:
Start End Size Use
-----------------------------------------------------------------------
0000000000000000 0000007fffffffff 512GB user
ffffff8000000000 ffffffffffffffff 512GB kernel
我们知道arm64架构最大支持48bit寻址,那么它的最大寻址空间是256TB,但是如果我们使用这种配置,虚拟内存划分为以上所示的两个区域,最大寻址空间是1TB,其中512GB属于用户空间,剩余512GB属于内核空间。下面我们着重介绍内核空间地址分布:
Memory: 4293896K/4776612K available (16828K kernel code, 2654K rwdata, 7436K rodata, 7104K init, 11801K bss, 195996K reserved, 286720K cma-reserved)
Virtual kernel memory layout:
modules : 0xffffff8000000000 - 0xffffff8008000000 ( 128 MB)
vmalloc : 0xffffff8008000000 - 0xffffffbebfff0000 ( 250 GB)
.text : 0xffffff9688080000 - 0xffffff96890f0000 ( 16832 KB)
.rodata : 0xffffff9689100000 - 0xffffff9689850000 ( 7488 KB)
.init : 0xffffff9689850000 - 0xffffff9689f40000 ( 7104 KB)
.data : 0xffffff9689f40000 - 0xffffff968a1d7a00 ( 2655 KB)
.bss : 0xffffff968a1d7a00 - 0xffffff968ad5e000 ( 11802 KB)
fixed : 0xffffffbefe7fd000 - 0xffffffbefec00000 ( 4108 KB)
PCI I/O : 0xffffffbefee00000 - 0xffffffbeffe00000 ( 16 MB)
vmemmap : 0xffffffbf00000000 - 0xffffffc000000000 ( 4 GB maximum)
0xffffffbf62000000 - 0xffffffbf67000000 ( 80 MB actual)
memory : 0xffffffd880000000 - 0xffffffd9c0000000 ( 5120 MB)
这个内存布局和arm 32的区别如下:
不存在highmem区域,在arm 32内存布局中,会有lowmem选项标识了低端内存直接映射区(DMA/NORMAL),而在arm 64架构中,只有一个memory用来映射可用内存(DMA/NORMAL/MOVABLE)
在arm 32架构中存在pkmap和fixmap两块区域,而arm 64架构中只有一个fixed区域,其实对应的就是fixmap区域,而不再有pkmap区域。
虽然内核可访问地址区域为512G,但是这里memory根据实际物理内存大小做了限制,所以memroy显示了实际能够访问的内存区。
memory区域的起始/结束地址如下:
pr_notice(" memory : 0x%16lx - 0x%16lx (%6ld MB)\n",
MLM(__phys_to_virt(memblock_start_of_DRAM()),
(unsigned long)high_memory));
而high_memory的赋值如下所示:
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
实际上这里的区域最终来源是memblock_start_of_DRAM()和memblock_end_of_DRAM()函数,进一步跟进可以看到具体获取的方式,实际是通过dts中配置的内存块来决定的。
原文:https://www.cnblogs.com/justin-y-lin/p/10568335.html