arm linux虚拟内存布局【转】

转自:https://blog.csdn.net/sxw1002/article/details/52841762

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
1
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))
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
1
  定义在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)
————————————————
版权声明:本文为CSDN博主「sxw1002」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sxw1002/article/details/52841762

posted @ 2022-08-24 16:39  Sky&Zhang  阅读(324)  评论(0编辑  收藏  举报