当前位置:首页 > 嵌入式 > Linux阅码场
[导读]作者简介于浩进,linux内核爱好者,现就职于北京灵汐科技有限公司,任职BSP工程师,主要负责IP验证、多媒体驱动开发及一些bringup等工作。文章大纲1.背景介绍2.环境说明2.1 硬件环境2.2Kernel 版本2.3kernel 相关配置介绍3.fixmap 机制介绍3....

作者简介

于浩进,linux内核爱好者,现就职于北京灵汐科技有限公司,任职BSP工程师,主要负责IP验证、多媒体驱动开发及一些bring up等工作。


文章大纲

1.背景介绍

2.环境说明


2.1 硬件环境


2.2 Kernel 版本


2.3 kernel 相关配置介绍

3.fixmap 机制介绍


3.1 虚拟空间拓扑

3.1.1 VA=39bit 下 kernel 虚拟地址空间拓扑
3.1.2 FIXMAP 地址空间拓扑
3.1.3 FIXMAP 初始化

3.2 fixmap 在 early ioremap 应用介绍

3.2.1 early_ioremap_setup()
3.2.2 __early_ioremap()


3.3 fixmap 在 early console 应用介绍


3.4 fixmap 在 device-tree 应用介绍

3.4.1 映射过程分析

3.5 fixmap 在 paging_init 中页表切换介绍

3.5.1 paging_init 函数简单分析
3.5.2 paging_init 中的 fixmap

4.小结

5.参考文章


01

背景介绍

Fixmap机制是kernel在启动过程中(start_kernel)临时的映射机制,目的是在真正页表建立之前用于完成对io设备的访问、device-tree的解析以及paging_init中的页表切换等。本文将对该机制做一个深入的分析。


02

环境说明

2.1硬件环境

SOC芯片,CPU8cortex-A53,其DDR物理地址为0x800000000device-tree存放的物理地址为0x843000000

2.2kernel版本4.19.83版本。

2.3kernel相关配置介绍
  • 相关Config配置

  • 相关宏配置

        以下宏的值,只给出结果了:


03

虚拟空间拓扑  

3.1虚拟空间拓扑3.1.1 VA=39bitkernel虚拟地址空间拓扑

1详细展示了VA=39bitkernel虚拟地址空间拓扑,里面展示了FIXMAP区域在整个虚拟地址空间所处的位置。


3.1.2 FIXMAP地址空间拓扑

KernelFixmap区域做了进一步的划分,各区间是在enum fixed_addresses 枚举类型定义的(/arch/arm64/include/asm/fixmap.h)。


其各个区间的virtual address通过fix_to_virt(const unsigned int idx)函数获得,其定义是在/include/asm-generic/fixmap.h里面,这个函数后面会用到。


下图2详细展示了各个区间的base address

Fix_to_virt的定义如下:


3.1.3 FIXMAP初始化

Bm_ptebm_pmdBm_pte为三个全局数组,用于暂存pudpmd

pte的页表。


early_fixmap_init()函数完成了fixmap映射的基础框架,如下图3所示,bm_pte数组并没有填值,因为当前还不知道哪些物理地址需要映射,等需要映射时候再去填写bm_pteentry

 

经过分析代码,整理了fixmap各段虚拟地址与bm_pmd entry的关系,如下图4所示:

需要说明的是FIX_PGD~FIX_FDTbm_pmd是属于同一个entry,即可以用bm_ptepte映射。


FIX_FDT~FIX_HOLE不属于该entry,即不可以用bm_ptepte映射,也为后面device-tree的映射做了一个铺垫。


3.2fixmap在early ioremap应用介绍3.2.1 early_ioremap_setup()

该函数的比较简单,主要是依靠__fix_to_virt()slot_virt[i]填入虚拟地址,其布局如下图5所示。

slot[i]fix_map区域已经规划好的虚拟地址范围,任何I/O地址空间都可以向这7slot空间做映射。


其中:slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i)__fix_to_virt()在之前已经介绍过。Slot_virt每个区间size256K


3.2.2 __early_ioremap()

有三个数组需要说明:

slot_virt[slot]BTMAP区域各个区间虚拟地址;

prev_map[slot]__early_ioremap()映射后的虚拟地址;

prev_size[slot]__early_ioremap()要映射的size


映射流程如下图6所示:

Figure 6 early ioremap映射流程图


图7展示了early ioremap页表转换过程,还是比较简单的。


3.3fixmap在early console应用介绍
Early console的映射与early ioremap的映射类似,通过__fix_to_vit(FIX_EARLYCON_MEM_BASE)获取虚拟地址,物理地址为UARTSOC的实际分配的地址(该物理地址来自于command lineearlycon=XXX),然后通过向bm_pte写入页表,即可以完成映射。


8是函数调用关系。图9是页表的建立和转换过程。


3.4 fixmap在device-tree应用介绍
3.4.1 射过程分析

Device-tree的映射和early-consoleearly-ioremap的映射原理有所不同,主要区别在于FIX_FDT空间对应的虚拟地址的pmd entryFIXADDR_START对应的pmd entry是不同的。


通过分析kernel代码可知对于device-tree的映射需要建立一个2Mblock entry即可,即在bm_pmd建立一个block entry


如下图10所示,只需要找到pmdp,写入block entry的页表项即可。


那问题来了,pmdp的虚拟地址我们是知道的,对应的bm_pmdentry的物理地址也能知道,但是两者之间的页表还未建立。


因此在用pmdp指针向bm_pmd写入block entry之前,必须要先建立pmdp的页表,这个页表建立过程就与early console的页表建立过程相同了。见下图11所示。

设备树页表的建立会调用到init_pmd()建立block entry,也就是下图122对应的代码,圈1的代码就是对应上图11pmdp建立页表的过程。


在写入block entry之后,pmdp也就无用了,圈3代码把刚才的pmdp的页表清除了,即把bm_pte对应的表项清除了。

最后再简单展示一下fixmap为设备树建立页表的函数调用关系,如下图13所示。

3.5fixmap在paging_init中页表切换介绍3.5.1 paging_init函数简单分析

下图14paging_init的代码分析。

  •  1代码通过memblock分配器分配了一个物理页面,该页面暂存后面代码建立的页表;


  • 2代码是通过fixmp机制把这个物理页面映射为虚拟地址;


  • 3代码把kernel的镜像的一些代码段、数据做等做映射,在图1有说明;


  • 4代码把memblock.memory类型的region区域做线性映射,比如设备树的memory节点的内存,会在此做线性映射,但是会排除代码段和只读数据段,具体细节,还请看源码;


  • 5~7代码将暂存页表内容拷贝到swapper_pg_dir,同时切换ttbr寄存器,此后CPU发出的虚拟地址就可以通过这套新建的页表进行虚实转换了;


  • 8清除pgdp的映射;


  • 9代码释放刚才申请的物理页;


3.5.2 paging_init中的fixmap

上图 圈6代码是把临时页表拷贝到swapper_pg_dir,临时页表的物理页是memblock分配器获得的物理地址。


由于mmu已经开启,memcpy无法使用物理地址,所以必须要先用fixmap机制做该物理页面的映射,得到其虚拟地址,即pgd_set_fixmap(addr),其定义如下:


其是借助于fixmp的“FIX_PGD”区域做的映射,页表映射及转换过程如下图15所示。


04

小结

  • 在进入start_kernel之前,head.S的“__primary_switch”已经开启mmu了,使能mmu之后CPU发出的ldr、str指令都为虚拟地址了,因此必须要提前建立好页表,mmu才能把虚拟地址转为物理地址,以访问真正的物理内存;


  • Fixmap用于在” earlyconsole”、” device-tree的解析”、” earlyioremap”、” paging_init的页表切换”等过程建立临时页表。


  • Fixmap机制实际就是为mmu做了相关的虚拟和物理地址的映射;


  • Bm_pmd、bm_pte是两个全局数组,用于存放pmd、pte的页表项;



05

参考文献

https://www.cnblogs.com/LoyenWang/p/11483948.html

https://www.cnblogs.com/LoyenWang/p/11440957.html

https://www.cnblogs.com/pengdonglin137/p/9157639.html

armv8_arm.pdf,从ARM官网下载即可。


欢迎赐稿“Linux阅码场”,投稿请扫码微信联系“小月”,稿费300-500RMB(已经以任何形式,如公众号、博客、网站发表过的文章,请勿投稿):




扫描识别二维码关注"Linux阅码场"     

如果您觉得不错,请转发转发转发!

或者随手点个“在看”吧~

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭