一、前言

某天,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的更多相关文章

  1. 保留ip: Reserved IP addresses

    Reserved IP addresses From Wikipedia, the free encyclopedia     In the Internet addressing architect ...

  2. 《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 ...

  3. PE Header and Export Table for Delphi

    Malware Analysis Tutorial 8: PE Header and Export Table 2. Background Information of PE HeaderAny bi ...

  4. 【转】Django Model field reference学习总结

    Django Model field reference学习总结(一) 本文档包含所有字段选项(field options)的内部细节和Django已经提供的field types. Field 选项 ...

  5. 《Unix网络编程》卷一(简介TCP/IP、基础套接字编程)

    通常说函数返回某个错误值,实际上是函数返回值为-1,而全局变量errno被置为指定的常值(即称函数返回这个错误值). exit终止进程,Unix在一个进程终止时总是关闭该进程所有打开的描述符. TCP ...

  6. Network Object NAT配置介绍

    1.Dynamic NAT(动态NAT,动态一对一) 实例一: 传统配置方法: nat (Inside) 1 10.1.1.0 255.255.255.0 global (Outside) 1 202 ...

  7. Django Model field reference

    ===================== Model field reference ===================== .. module:: django.db.models.field ...

  8. devm_xxx机制【转】

    前言 devm是内核提供的基础机制,用于方便驱动开发者所分配资源的自动回收.参考内核文档devres.txt.总的来说,就是驱动开发者只需要调用这类接口分配期望的资源,不用关心释放问题.这些资源的释放 ...

  9. POSIX-Data Structure

    struct sigevent The <signal.h> header shall define the sigeventstructure, which shall include ...

随机推荐

  1. Android中远程Service浅析

    上一篇文章中简单的写了一下关于Android中Service的两种启动方式,不过都是本地的服务,今天就简单的写下关于Android中远程Service的使用,学习之前先了解两个概念,AIDL( And ...

  2. 遇到问题描述:Android Please ensure that adb is correctly located at问题解决

    遇到问题描述: 运行android程序控制台输出 [2013-11-04 16:18:26 - ] The connection to adb is down, and a severe error ...

  3. CPC广告反作弊

    原文:http://blog.csdn.net/xwm1000/article/details/45460957 CPC广告上线也2年了,从上线以来就一直存在着作弊和反作弊的斗争,刚开始的时候流量少, ...

  4. [Angular] Use ngx-build-plus to compile Angular Elements

    We can treat Angular Element as each standlone lib and compile each Angular element spreatly. Tool w ...

  5. [Python] 错误“IndentationError: unindent does not match any outer indentation level”是什么意思?

    文本没有对齐,建议打开文本编辑器的Tab显示(我用的Editplus是视图->空白->制表符),看缩进是否合理,调整一致就好了.

  6. “/”应用程序中的server错误

    前几天敲ASP.NET有关验证控件的样例的时候,出现了这个问题: 可是对于这个问题我们应该都不陌生,之前敲牛腩的时候也出现过,当时的解决方法是: 在web.config中找         <a ...

  7. hiberante 二级缓存设置

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  8. 火狐浏览器Firefox不支持alt怎么

    因为HTML代码的解析不同,需要把标签文字"alt"换成"title",就可以在FireFox中正常显示了. 如下所示,IE对于alt和title均可以支持 但 ...

  9. Javascript高级程序设计-对象

    学习Javascript,最难的地方是什么? Object(对象)最难,初学者不容易掌握. Javascript是一种基于对象(object-based)的语言,它的语法中没有class(类). C# ...

  10. nm 命令 程序符号信息查看

    http://www.cnblogs.com/wangkangluo1/archive/2012/07/02/2572438.html 用途 显示关于对象文件.可执行文件以及对象文件库里的符号信息. ...