Fix-Mapped Addresses
一、前言
某天,wowo同学突然来了一句:如果要在start_kernel中点LED,ioremap在什么时间点才能调用呢?我想他应该是想通过点LED灯来调试start_kernel之后的初始化的代码(例如DTB解析部分的代码)。那天,我们两个花了二十分钟的时间,讨论相关的问题,我觉得很有意思,因此决定写fix mapped address这样的一份文档。
在汇编代码中,由于没有打开MMU,想怎么访问外设都很简单,直接使用物理地址即可,然而,进入start kernel之后(打开了MMU),想要访问硬件都是那么的不方便,至少需要通过ioremap获取了虚拟地址之后才可以访问。但是,实际上,在内核的启动的初始阶段,内存管理子系统还没有ready,ioremap还不能调用(在mm_init之后可以正常使用)。
实际上,这个需求是和early ioremap模块相关,此外,还有一些其他的需求,内核合并了这些需求并提出了fix mapped address的概念。本文就是描述关于fix mapped address的方方面面,BTW,本文的代码来自4.4.6内核,体系结构相关的代码依然选择的是ARM64。
二、什么是fixmap?
Fix map中的fix指的是固定的意思,那么固定什么东西呢?其实就是虚拟地址是固定的,也就是说,有些虚拟地址在编译(compile-time)的时候就固定下来了,而这些虚拟地址对应的物理地址不是固定的,是在kernel启动过程中被确定的。为了方便大家理解fixmap,我们提供一个具体的例子:DTB image的处理。
实际上DTB的处理一开始并没有使用fixmap,而是放在了kernel image附近。更具体的要求是必须放在kernel image起始地址的512M内,8字节对齐,dtb image不能越过2M section size的边界。之所以这么要求,主要是想借用kernel image页表的“东风”,反正建立kernel image所需要的PGD/PUD/PMD页表都已经静态分配了,对dtb image的要求可以不需要建立新的页表,只是在原有的页表中增加一个entry而已,不过这样的设计存在下面的问题:
(1)对dtb image的位置有限制,不是很灵活(谁不想自由自在呢?bootload copy dtb img的时候当然想了无牵挂啊)。
(2)对dtb image的位置检查在head.S中,需要汇编实现(谁想写汇编啊,用c实现多买易懂啊,可维护性,可移植性多么好啊)。
现在,既然内核有了early fixmap的支持,那么上面的限制都可以放宽了。整个dtb image的处理过程如下:
(1)bootloader copy dtb image到memory的某个位置上。具体的位置随便,当然还是要满足8字节对齐,dtb image不能越过2M section size的边界的要求,毕竟我们也想一条section mapping就搞定dtb image。
(2)bootload通过寄存器x0传递dtb image的物理地址,dtb image的虚拟地址在编译kernel image的时候就确定了。
(3)汇编初始化阶段不对dtb image做任何处理
(4)在start kernel之后的初始化代码中(具体在setup_arch--->setup_machine_fdt中),创建dtb image的相关Translation tables,之后就可以自由的访问dtb image了。
三、为何有fixmap这个概念?
动态分配虚拟地址以及建立地址映射是一个复杂的过程,在内核完全启动之后,内存管理可以提供各种丰富的API让内核的其他模块可以完成虚拟地址分配和建立地址映射的功能,但是,在内核的启动过程中,有些模块需要使用虚拟内存并mapping到指定的物理地址上,而且,这些模块也没有办法等待完整的内存管理模块初始化之后再进行地址映射。因此,linux kernel固定分配了一些fixmap的虚拟地址,这些地址有固定的用途,使用该地址的模块在初始化的时候,讲这些固定分配的地址mapping到指定的物理地址上去。
最直观的需求来自初始化代码的调试,想一想当我们来到start_kernel的时候我们面临的处境:
(1)我们不能访问全部的内存,只能访问kernel image附近的memory。
(2)我们不能访问任何的硬件,所有的io memory还没有mapping
想要通过串口控制台输出错误信息?sorry,现在离console驱动的初始化还早着呢。想点个LED灯看看内核运行情况?sorry,ioremp函数需要kmalloc分配内存,但是伙伴系统还没有初始化呢。怎么办?一个最简洁的方法就是简化虚拟内存的分配和管理(ioremp中使用的管理虚拟内存地址的方法太重了),而最简单的方法就是fix virtual address。
四、fixmap的具体位置在那里?
fixmap的地址区域位于FIXADDR_START和FIXADDR_TOP之间,具体可以参考下图:

上图中,红色框的block就是fixmap address的具体位置。
五、fixmap具体应用在哪些场景?
fixmap的地址区域有被进一步细分,如下:
enum fixed_addresses {
FIX_HOLE,
FIX_FDT_END,
FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1,FIX_EARLYCON_MEM_BASE,
FIX_TEXT_POKE0,
__end_of_permanent_fixed_addresses,FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
__end_of_fixed_addresses
};
由定义可知,fixmap地址区域又分成了两个部分,一部分叫做permanent fixed address,是用于具体的某个内核模块的,使用关系是永久性的。另外一个叫做temporary fixed address,各个内核模块都可以使用,用完之后就释放,模块和虚拟地址之间是动态的关系。
permanent fixed address主要涉及的模块包括:
(1)dtb解析模块。
(2)early console模块。标准的串口控制台驱动的初始化在整个kernel初始化过程中是很靠后的事情了,如果能够在kernel启动阶段的初期就有一个console,能够输出各种debug信息是多买美妙的事情啊,early console就能满足你的这个愿望,这个模块是使用early param来初始化该模块的功能的,因此可以很早就投入使用,从而协助工程师了解内核的启动过程。
(3)动态打补丁的模块。正文段一般都被映射成read only的,该模块可以使用fix mapped address来映射RW的正文段,从动态修改程序正文段,从而完成动态打补丁的功能。
temporary fixed address主要用于early ioremap模块。linux kernel在fix map区域的虚拟地址空间中开了FIX_BTMAPS_SLOTS个的slot(每个slot的size是NR_FIX_BTMAPS),内核中的模块都能够通过early_ioremap、early_iounmap的接口来申请或者释放对某个slot 虚拟地址的使用。
Fix-Mapped Addresses的更多相关文章
- 保留ip: Reserved IP addresses
Reserved IP addresses From Wikipedia, the free encyclopedia In the Internet addressing architect ...
- 《Peering Inside the PE: A Tour of the Win32 Portable Executable File Format》阅读笔记二
Common Sections The .text section is where all general-purpose code emitted by the compiler or assem ...
- PE Header and Export Table for Delphi
Malware Analysis Tutorial 8: PE Header and Export Table 2. Background Information of PE HeaderAny bi ...
- 【转】Django Model field reference学习总结
Django Model field reference学习总结(一) 本文档包含所有字段选项(field options)的内部细节和Django已经提供的field types. Field 选项 ...
- 《Unix网络编程》卷一(简介TCP/IP、基础套接字编程)
通常说函数返回某个错误值,实际上是函数返回值为-1,而全局变量errno被置为指定的常值(即称函数返回这个错误值). exit终止进程,Unix在一个进程终止时总是关闭该进程所有打开的描述符. TCP ...
- Network Object NAT配置介绍
1.Dynamic NAT(动态NAT,动态一对一) 实例一: 传统配置方法: nat (Inside) 1 10.1.1.0 255.255.255.0 global (Outside) 1 202 ...
- Django Model field reference
===================== Model field reference ===================== .. module:: django.db.models.field ...
- devm_xxx机制【转】
前言 devm是内核提供的基础机制,用于方便驱动开发者所分配资源的自动回收.参考内核文档devres.txt.总的来说,就是驱动开发者只需要调用这类接口分配期望的资源,不用关心释放问题.这些资源的释放 ...
- POSIX-Data Structure
struct sigevent The <signal.h> header shall define the sigeventstructure, which shall include ...
随机推荐
- 你需要知道的、有用的 Python 功能和特点
在使用Python多年以后,我偶然发现了一些我们过去不知道的功能和特性.一些可以说是非常有用,但却没有充分利用.考虑到这一点,我编辑了一些的你应该了解的Pyghon功能特色. 带任意数量参数的函数 你 ...
- ListView 控件与 内容
1)由控件获取内容:ListViewItem item = Utilities.GetVisualParent<ListViewItem>(chx); if (item == null) ...
- (转)Unity3D新手引导开发手记
转自:http://www.cnblogs.com/ybgame/p/3844315.html 最近开始接手新手引导的开发,记录下这块相关的心得 首先客户端是Unity,在接手前,前面的同学已经初步完 ...
- 数据需求统计常用awk命令
原文:http://www.5iops.com/html/2013/script_0418/267.html 1.将时间转换为时间戳 select unix_timestamp('2009-10-26 ...
- OpenFace库(Tadas Baltrusaitis)中基于Haar Cascade Classifiers进行人脸检測的測试代码
Tadas Baltrusaitis的OpenFace是一个开源的面部行为分析工具.它的源代码能够从 https://github.com/TadasBaltrusaitis/OpenFace 下载. ...
- windows 用户变量和系统变量的差别
点击"我的电脑→属性→高级系统设置"标签的"环境变量"button,出现"环境变量"对话框,假设当前是以Administrator登录系统的 ...
- Android MVP 构架封装
上一篇我们简单实现了一个MVP的构架,下面我们来做一个简单的封装使其使用更简单方便 源码地址RxMVP分支Tag03 最终实现目录结构如下 BasePresenter 如果每一个Activity都需要 ...
- xpath语法速查
xpath的具体学习可以通过w3c查看(链接:http://www.w3school.com.cn/xpath/index.asp) 这里只是将平时用到的几个表格贴出来,以后查询: 这里的xpath我 ...
- 经典,HTML5游戏,超级玛丽
在线演示 在线演示 本地下载 这是一款使用HTML5开发的超级玛丽,有没有点儿时的记忆?长按向上键,可以跳的更高哦.如果你也喜欢可以当成休闲游戏,如果你是开发者,不防下载下来看看是如何生成的.
- listView下拉刷新加载数据
这个下拉效果在网上最早的例子恐怕就是Johan Nilsson的实现,http://johannilsson.com/2011/03/13/android-pull-to-refresh-update ...