首先我们以最为常用的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中配置的内存块来决定的。