在arm linux 内核启动后,会出现Virtual kernel memory layout
Memory: 509624K/524288K available (6144K kernel code, 390K rwdata, 1372K rodata, 1024K init, 164K bss, 14664K reserved, 0K cma-reserved)
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
vmalloc : 0xa0800000 - 0xff800000 (1520 MB)
lowmem : 0x80000000 - 0xa0000000 ( 512 MB)
modules : 0x7f000000 - 0x80000000 ( 16 MB)
.text : 0x(ptrval) - 0x(ptrval) (7136 kB)
.init : 0x(ptrval) - 0x(ptrval) (1024 kB)
.data : 0x(ptrval) - 0x(ptrval) ( 391 kB)
.bss : 0x(ptrval) - 0x(ptrval) ( 165 kB)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
这是linux 的虚拟内核内存布局
- vector 如果CPU支持向量重定向(控制寄存器的V位),则CPU中断向量被映射到这里。
- fixmap 固定映射区,用来分配大页内存
- vmalloc虚拟内存申请的地址范围,实际大小
VMALLOC_END=0xf0000000 must be aligned to a 2MB boundary.
VMALLOC_END必须在2MB的边界上对齐。 - lowmem 直接物理内存映射区,它映射平台的RAM,通常所有的平台都使用1:1的映射关系。这里是245MB。大小=总物理内存大小减去其他分区总和。0x80000000也就是PAGE_OFFSET内核镜像起始虚拟地址。
- modules 内核模块空间,内核模块通过insmod命令加载,会动态的映射到这里
- .text 内核映像text函数的代码段
- .init 内核映像(系统启动过程中以__init宏标识的函数占用的空间被vmlinux.lds标识为__init_begin__init_end启动init进程前被释放掉)init函数的init段,内核映像(同上) text函数的代码段
- .data 内核映像 data函数的代码段
- .bss 内核映像 bss函数的数据段
在内核进行page初始化以及mmu配置之前,首先需要知道整个memory map。
PAGE_OFFSET
Start address of Kernel space
0xC000_0000lowmem
Kernel direct-mapped RAM region (1:1 mapping)
Maximum 896MHIGH_MEMORY
End address of lowmem
PAGE_OFFSET + MEMORY_SIZEpkmap
用来把HIGHMEM page 永久映射到 kernel space
2MB (这个大小每个平台不一样)
kmap() / kunmap()Page gap
To against out-of-bounds errors
8MBvmalloc
vmalloc() / ioremap() spaceDMA
DMA memory mapping regionFixmap
kmap()可能会进入睡眠,所以不能用在中断上下文等地方.
所以Fixmap就是用于在中断上下文中把 highmem映射到内核空间的.
Mapping HIGHMEM pages atomically
kmap_atomic() :Fixmap在使用这个函数,所以可以在中断上下文中使用Vector
CPU vectors are mapped hereModules
Kernel modules inserted via insmod are placed here
16MB (14MB, if HIGHMEM is enabled)