概述
Documentation/arm/memory.txt中的描述:
开始位置 | 结束位置 | 使用 |
---|---|---|
0xffff8000 | 0xffffffff | 用于 copy_user_page / clear_user_page。在SA11xx和Xscale平台,用于建立一个迷你缓存映射 |
0xffff4000 | 0xffffffff | armv6及以后的CPU cache混淆 |
0xffff1000 | 0xffff7fff | 保留地址空间,各平台不能使用 |
0xffff0000 | 0xffff0fff | cpu中断向量页。如果CPU支持向量重定位(控制寄存器V bit),CPU中断向量表映射到该地址范围 |
0xfffe0000 | 0xfffeffff | Xscale缓存冲刷区。在 proc-xscale.S文件中使用这个地址范围冲刷整个数据缓存(Xscale没有TCM). |
0xfffe8000 | 0xfffeffff | 各平台的DTCM映射区 |
0xfffe0000 | 0xfffe7fff | 各平台的ITCM映射区 |
0xffc00000 | 0xffefffff | 固定映射区,调用fix_to_virt()函数分配该区域 |
0xfee00000 | 0xfeffffff | PCI I/O映射空间。是vmalloc空间的静态映射 |
VMALLOC_START | VMALLOC_END-1 | vmalloc() / ioremap() 空间。 vmalloc/ioremap返回的动态定位的内存区域,机器也可以通过iotable_init()函数指定静态映射。 VMALLOC_START基于 high_memory的变化值。VMALLOC_END等于 0xff000000。 |
PAGE_OFFSET | high_memory-1 | 内核直接映射内存区。所有平台典型的1:1映射关系 |
PKMAP_BASE | PAGE_OFFSET-1 | 内核持久映射区。映射高端内存页到内核空间的方法之一 |
MODULES_VADDR | MODULES_END-1 | 内核模块映射空间。内核模块通过insmod安装并动态映射到此区域 |
0x00001000 | TASK_SIZE-1 | 用户进程映射区。每个进程通过mmap()函数映射到这个区域 |
0x00000000& | 0x00000fff | CPU向量页/空指针陷阱。不支持中断向量重映射的CPUs在此区间进行映射。内核和用户空间释放空指针也在此空间捕捉 |
以imx6dl为例看一下具体的虚拟地址空间如何分配的,源码参考自飞思卡尔基于linux-3.0.35版本发布的imx6内核代码),先上具体的映射布局直观感受一下:
图 imx6dl虚拟内存空间布局
具体地址及定义出处:
中断向量映射区:
0xffff0000 ~ 0xffff1000 ( 4 kB)
vector的起始地址在内核默认配置arch/arm/configs/qmx6_deconfig中定义CONFIG_VECTORS_BASE 为0xffff0000,该映射区占用一个页的大小。
固定映射区:
0xfff00000 ~0xfffe0000 ( 896 kB)
fixmap起始地址FIXADDR_START,结尾地址FIXADDR_TOP均定义在arch/arm/include/asm/fixmap.h,分别固定为0xfff00000和0xfffe0000
DMA映射区:
0xf4600000 - 0xffe00000 ( 184 MB)
起始位置CONSISTENT_BASE, 结束位置CONSISTENT_END均定义在 arch/arm/include/asm/memory.h,其中
CONSISTENT_BASE = CONSISTENT_END – CONSISTENT_DMA_ZISE
CONSISTENT_END固定为0xffe00000
CONSISTENT_DMA_ZISE的定义在arch/arm/plat-mxc/include/mach/memory.h中,cpu为MX6的开发板,大小为184*SZ_1M
vmalloc映射区与DMA映射区的pages gap
该区域被I/O映射所占用,调用ioremap()会映射到这个区域中,具体定义在arch/arm/plat-mxc/include/mach/mx6.h中,外设基地址PERIPABASE_VIRT定义为0xf2000000,为I/O映射的起始地址
vmalloc映射区:
0xc0800000 - 0xf2000000 ( 792 MB)
VMALLOC_START 定义在arch/arm/ include/asm/pgtable.h中,VMALLOC_START具体定义为
#define VMALLOC_START
(((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
high_memory由物理内存的结束地址转化而来,然后换算成虚拟地址,最后得到0xc0000000,也就是直接映射区(lowmem)的末尾。
VMALLOC_OFFSET为直接映射区到vmalloc的偏移量,大小8M,此page gap用于守护内存访问越界错误。VMALLOC_END定义在arch/arm/plat-mxc/include/mach/vmalloc.h中,固定为0xf2000000
直接内存映射区:
lowmem : 0x80000000 - 0xc0000000 (1024 MB)
起始地址PAGE_OFFSET,结束地址为high_memory,PAGE_OFFSET定义在.config中为0x8000000,high_memory的值在bootmem_init时候计算出来,在vmalloc中计算VMALLOC_START时也应用了该值。
内核镜像映射地址空间在lowmem 范围内,起始地址定义在vmlinx.lds.S中,为PAGE_OFFSET+TEST_OFFSET,TEST_OFFSET定义在arch/arm/Makefile中,值为0x00008000, 所以内核镜像所在的起始地址为0x80008000,其中又包括.init/.text/.data/.bss段等,就不详细说了。而0x80000000~0x80008000的空间用于存放内核页表,。
模块映射区 :
modules : 0x7f000000 - 0x80000000 ( 16 MB)
起始地址MODULES_VADDR = PAGE_OFFSET – 16*1024*1024
结束地址MODULES_END = PAGE_OFFSET
定义在arch/arm/include/asm/memory.h中
用户进程映射区
0x00000000 ~0x7f000000
TASK_SIZE = CONFIG_PAGE_OFFSET – 0x01000000
定义在arch/arm/include/asm/memory.h,CONFIG_PAGE_OFFSET在lowmem中已经说明为0x80000000,所减去的16M空间被modules所占用,所以TASK_SIZE实际为0x7f000000,而0x00000000为起始的第一页为CPU向量页/空指针陷阱。
参考资料:
Documentation/arm/memory.txt
Understanding The Linux Virtual Memory Manager (url https://www.kernel.org/doc/gorman/pdf/understand.pdf)
最后
以上就是孝顺金毛为你收集整理的arm linux虚拟内存布局的全部内容,希望文章能够帮你解决arm linux虚拟内存布局所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复