pud

内存管理(三):内核上电启动阶段的页表映射

孤者浪人 提交于 2020-05-06 23:14:27
Linux版本:4.14.74 目录 1 启动阶段所需页表 2 创建过程 2.1启动阶段的页表大小 2.2创建描述符函数 2.3 创建中间页表 2.4 section mapping 2.5 映射的整体流程 1 启动阶段所需页表 在kernel启动阶段,会创建两次地址映射 Identity mapping Kernel image mapping 在BootLoader以及uboot中,mmu功能是关闭的,操作的都是物理地址。为了提高性能,加快初始化速度,我们必须某个阶段(越早越好)打开MMU和cache,打开MMU之后操作的就是虚拟地址,为了从物理地址(Physical Address,简称PA)转换到虚拟地址(Virtual Address,简称VA)的平滑过渡,ARM推荐创建VA和PA相等的一段映射(例如:虚拟地址addr通过页表查询映射的物理地址也是addr)。这段映射在linux中称为identity mapping。 而为了执行kernel image,自然需要映射kernel image。 turn on MMU相关的代码被放入到一个特别的section,名字是.idmap.text,实际上对应上图中物理地址空间的IDMAP_TEXT这个block。这个区域的代码被mapping了两次,做为kernel image的一部分,它被映射到了__idmap_text

内存管理(四):DTB的映射

ⅰ亾dé卋堺 提交于 2020-05-06 10:09:27
Linux版本:4.14.74 目录 1 建立系统映射的过程 2 FIXMAP概念 3 FIXMAP的初步映射 4 DTB的映射 1 建立系统映射的过程 经过前面几章的内容,我们开启了MMU,为kernel image创建了映射,通过调用start_kernel setup_arch建立页表映射,读取kernel建立页表映射的代码和流程如下图所示,下面分章节对这三个部分进行说明 1. void __init setup_arch(char **cmdline_p) 2. { 3. pr_info("Boot CPU: AArch64 Processor [%08x]\n", read_cpuid_id()); 4. 5. ..... 6. 7. early_fixmap_init(); 8. early_ioremap_init(); 9. 10. setup_machine_fdt(__fdt_pointer); 11. .... 12. arm64_memblock_init(); 13. 14. paging_init(); 15. 16. .... 17. } 本文主要描述映射DTB的过程 2 FIXMAP概念 虽然可以通过kernel image mapping和identity mapping来窥探物理地址空间,但终究是管中窥豹,不了解全局

Linux内存初始化(二)identity mapping和kernel image mapping

 ̄綄美尐妖づ 提交于 2020-05-05 13:48:50
一、前言 本文没有什么框架性的东西,就是按照__create_page_tables代码的执行路径走读一遍,记录在初始化阶段,内核是如何创建内核运行需要的页表过程。想要了解一些概述性的、框架性的东西可以参考 内存初始化 文档。 本文的代码来自ARM64,内核版本是4.4.6,此外,阅读本文最好熟悉ARMv8中翻译表描述符的格式。 二、create_table_entry 这个宏定义主要是用来创建一个中间level的translation table中的描述符。如果用linux的术语,就是创建PGD、PUD或者PMD的描述符。如果用ARM64术语,就是创建L0、L1或者L2的描述符。具体创建哪一个level的Translation table descriptor是由tbl参数指定的,tbl指向了该translation table的内存。virt参数给出了要创建地址映射的那个虚拟地址,shift参数以及ptrs参数是和具体在哪一个entry中写入描述符有关。我们知道,在定位页表描述的时候,我们需要截取虚拟地址中的一部分做为offset(index)来定位描述符,实际上,虚拟地址右移shift,然后截取ptrs大小的bit field就可以得到entry index了。tmp1和tmp2是临时变量。create_table_entry的代码如下: .macro create

内存管理(二):页表映射过程

ε祈祈猫儿з 提交于 2020-05-01 14:29:34
Linux源码版本:4.14.75 我们知道在Linux中,操作的都是虚拟地址(有MMU的情况下),那么Linux是如何从虚拟地址找到物理地址的呢? 通过 内存管理(一):虚拟地址空间布局 我们知道,arm64支持64位地址宽度,但64bit并不是都用到了,linux最大支持的虚拟地址宽度为48bit,我们以39bit地址宽度为例 1、[63:39]指示页表的基地址寄存器,如果全为1,表示这个地址是内核空间地址,页表基地址寄存器是TTBR1_EL1;如果全为0,表示这个地址是用户空间地址,页表基地址寄存器是TTBR0_EL1 2、TTBR寄存器保存了第0级页表寄存器,0级页表寄存器有512个页表项,每个页表项8个字节,大小是4K,正好一页大小。通过虚拟地址的[38:30]作为索引查找相应的表项,表项中存储有下一级页表的基地址,0级页表每个页表项可以映射1G大小。 3、1级页表同样512个页表项,大小4K。通过虚拟地址的[29:21]作为索引查找相应的表项,表项中存储有下一级页表的基地址,1级页表每个页表项可以映射2M大小 4、2级页表512个页表项,大小4K。2级页表每个页表项映射一页4K大小,通过虚拟地址的[20:12]作为索引查找相应的表项,表项中存储了最终物理地址的[38:12],与虚拟地址的[11:0]组合之后就找到了最终的物理地址。 ARM64最大支持4级页表: PGD

虚拟地址布局

孤人 提交于 2020-05-01 14:19:46
Linux版本:4.14.74 #1 Linux虚拟内存布局# 在ARM64中,地址线由32bit变为64bit,但是64bit并不是全用到了,最大支持48位物理寻址,最大可寻找256T的物理地址空间,对于目前的应用来讲完全足够了。 虚拟地址的最大宽度可配置,最大为48bit,还可以有36bit,39bit,42bit,47bit 1. [arch/arm64/Kconfig] 2. 3. config ARM64_VA_BITS 4. int 5. default 36 if ARM64_VA_BITS_36 6. default 39 if ARM64_VA_BITS_39 7. default 42 if ARM64_VA_BITS_42 8. default 47 if ARM64_VA_BITS_47 9. default 48 if ARM64_VA_BITS_48 10. 11. [arch/arm64/ configs/xj2_debug_defconfig] 12. CONFIG_ARM64_VA_BITS_39=y 以39bit为例,。用户空间和内核空间大小均为512G。 用户空间范围:0x0000-0000-0000-0000----0x0000-007f-ffff-ffff 内核空间范围:0xffff-ff800-0000-0000—0xffff-ffff

Linux内存初始化(一)

烂漫一生 提交于 2020-04-06 01:49:08
一、前言 一直以来,我都非常着迷于两种电影拍摄手法:一种是慢镜头,将每一个细节全方位的展现给观众。另外一种就是快镜头,多半是反应一个时代的变迁,从非常长的时间段中,截取几个典型的snapshot,合成在十几秒的镜头中,可以让观众很快的了解一个事物的发展脉络。对应到技术层面,慢镜头有点类似情景分析,把每一行代码都详细的进行解析,了解技术的细节。快镜头类似数据流分析,勾勒一个过程中,数据结构的演化。本文采用了快镜头的方法,对内存初始化部分进行描述,不纠缠于具体函数的代码实现,只是希望能给大家一个概略性的印象(有兴趣的同学可以自行研究代码)。BTW,在本文中我们都是基于ARM64来描述体系结构相关的内容。 二、启动之前 在详细描述linux kernel对内存的初始化过程之前,我们必须首先了解kernel在执行第一条语句之前所面临的处境。这时候的内存状况可以参考下图: bootloader有自己的方法来了解系统中memory的布局,然后,它会将绿色的kernel image和蓝色dtb image copy到了指定的内存位置上。kernel image最好是位于main memory起始地址偏移TEXT_OFFSET的位置,当然,TEXT_OFFSET需要和kernel协商好。kernel image是否一定位于起始的main memory(memory address最低)呢?也不一定