我是靠谱客的博主 孝顺金毛,最近开发中收集的这篇文章主要介绍arm linux虚拟内存布局,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Documentation/arm/memory.txt中的描述:

开始位置结束位置使用
0xffff80000xffffffff用于 copy_user_page / clear_user_page。在SA11xx和Xscale平台,用于建立一个迷你缓存映射
0xffff40000xffffffffarmv6及以后的CPU cache混淆
0xffff10000xffff7fff保留地址空间,各平台不能使用
0xffff00000xffff0fffcpu中断向量页。如果CPU支持向量重定位(控制寄存器V bit),CPU中断向量表映射到该地址范围
0xfffe00000xfffeffffXscale缓存冲刷区。在 proc-xscale.S文件中使用这个地址范围冲刷整个数据缓存(Xscale没有TCM).
0xfffe80000xfffeffff各平台的DTCM映射区
0xfffe00000xfffe7fff各平台的ITCM映射区
0xffc000000xffefffff固定映射区,调用fix_to_virt()函数分配该区域
0xfee000000xfeffffffPCI I/O映射空间。是vmalloc空间的静态映射
VMALLOC_STARTVMALLOC_END-1vmalloc() / ioremap() 空间。 vmalloc/ioremap返回的动态定位的内存区域,机器也可以通过iotable_init()函数指定静态映射。 VMALLOC_START基于 high_memory的变化值。VMALLOC_END等于 0xff000000。
PAGE_OFFSEThigh_memory-1内核直接映射内存区。所有平台典型的1:1映射关系
PKMAP_BASEPAGE_OFFSET-1内核持久映射区。映射高端内存页到内核空间的方法之一
MODULES_VADDRMODULES_END-1内核模块映射空间。内核模块通过insmod安装并动态映射到此区域
0x00001000TASK_SIZE-1用户进程映射区。每个进程通过mmap()函数映射到这个区域
0x00000000&0x00000fffCPU向量页/空指针陷阱。不支持中断向量重映射的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虚拟内存布局所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部