前面我们说到,为kernel image设置了虚实地址转换表,并且开启了mmu。但是现在从虚拟地址空间CPU只能看到kernel image,如果此时想访问其他物理地址空间怎么办?用ioremap吗?要知道,此时内存子系统还没有初始化,ioremap无法工作。为了解决这一问题,Linux内核定义了一段固定的虚拟地址空间,所谓固定就是说在编译时就确定的,内核启动早期会将某些物理地址映射到这段固定虚拟地址空间。

谁要使用虚拟地址空间?

我们先来想一个问题,谁会使用这段固定虚拟地址空间?乍一看这个问题可不好回答,那么可以换一种问法,CPU要使用哪些物理地址空间?这个问题就比较容易了吧!哈哈,想到点什么没有?至少有两点是比较容易想到的:
DTB:目前DTB在linux内核中可谓深入人心,DTB用来描述硬件拓扑及资源信息,linux启动早期需要解析DTB文件,获取硬件拓扑及资源信息。
Console:调试过Linux内核启动的朋友应该都是知道串口控制台的重要性,基于调试的考虑,我们往往希望尽可能早的通过串口控制台打印我们需要的信息,那么就需要访问UART的控制器。
下面是linux所定义的固定虚拟地址空间的layout:

enum fixed_addresses {FIX_HOLE,/** Reserve a virtual window for the FDT that is 2 MB larger than the* maximum supported size, and put it at the top of the fixmap region.* The additional space ensures that any FDT that does not exceed* MAX_FDT_SIZE can be mapped regardless of whether it crosses any* 2 MB alignment boundaries.** Keep this at the top so it remains 2 MB aligned.*/
#define FIX_FDT_SIZE        (MAX_FDT_SIZE + SZ_2M)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,/** Temporary boot-time mappings, used by early_ioremap(),* before ioremap() is functional.*/
\#define NR_FIX_BTMAPS      (SZ_256K / PAGE_SIZE)
\#define FIX_BTMAPS_SLOTS   7
\#define TOTAL_FIX_BTMAPS   (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)FIX_BTMAP_END = __end_of_permanent_fixed_addresses,FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,/** Used for kernel page table creation, so unmapped memory may be used* for tables.*/FIX_PTE,FIX_PMD,FIX_PUD,FIX_PGD,__end_of_fixed_addresses
};

- FIX_FDT—FIX_FDT_END(4M)
用于DTB.
- FIX_EARLYCON_MEM_BASE
用于早期串口控制台。
- FIX_TEXT_POKE0
用法不明。
- FIX_BTMAP_BEGIN—FIX_BTMAP_END
用于早期ioremap。
- FIX_PTE
pte table固定虚拟地址,用于临时映射。
- FIX_PMD
pmd table固定虚拟地址,用于临时映射。
- FIX_PUD
pud table固定虚拟地址,用于临时映射。
- FIX_PGD
pgd table固定虚拟地址,用于临时映射。

下面的图能更清晰的反应固定虚拟地址空间的layout:

重要函数解释

  • pgd_offset_k(addr)
    根据传入的虚拟地址addr,计算得到pgd table中的某个entry,并返回其虚拟地址。
  • pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
    将pud table的物理基地址填充到pgd entry中。
  • fixmap_pud(unsigned long addr)
    根据传入的虚拟地址,计算得到pud table中的某个entry,并返回其虚拟地址。
  • pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
    将pmd table的物理基地址填充到pud entry中。
  • fixmap_pmd(unsigned long addr)
    根据传入的虚拟地址,计算得到pmd table中的某个entry,并返回其虚拟地址。
  • pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
    将pte table的物理地址填充到pmd entry中。
    以上六个函数为一个虚拟地址设置了三级转换,但是并没有设置第四级转换,第四级转换映射到物理地址。

代码逻辑分析

1. 固定映射初始化:early_fixmap_init

为虚拟地址FIXADDR_START(即固定虚拟地址空间的起始地址)设置前三级转换。
单看这个函数的逻辑,其实特别简单,就是根据虚拟地址找到pgd table中的某个entry,并填充pud table的物理基地址;再根据虚拟地址找到pud table中的某个entry,并填充pmd table的物理地址;在根据虚拟地址找到pmd table中的某个entry,并填充pte table的物理地址,并没有将虚拟地址映射到物理地址。
代码逻辑看似简单,实际上暗藏玄机,如果不把此间玄机窥探清除,读后面的代码会非常迷惑,下面我们就把其中玄机一点一点呈现出来。

- 玄机1:FIXADDR_START神秘之处。

回头看下固定虚拟地址layout,FIXADDR_TOP是2M对齐的,这个从FIXADDR_TOP定义可以知道,而FIXADDR_START并非2M对齐,这一点其实非常重要,后面的两个玄机都与此相关。

- 玄机2:为DTB固定虚拟地址设置了前两级转换表,即PDG,PUD转换表。

DTB是按section来作映射的,section映射需要三级转换,一条section映射覆盖2M空间,由于FIXADDR_TOP是2M对齐的,因而两个连续的pmd entry即可覆盖4M的DTB虚拟地址空间,后面只需要填充最多两个PMD entry即可。

- 玄机3:为其他固定虚拟地址设置了前三级转换表,及PGD,PUD,PMD转换表。

由于FIXADDR_START不是2M对齐的,此时设置的pmd entry覆盖所有的非DTB虚拟地址空间,后面映射到实际物理地址的时候,只需要填充该PMD entry指向的PTE table中的某个entry即可。

2. 早期ioremap初始化:early_ioremap_init

为了在内存子系统起来之前使用ioremap,linux实现了早期ioremap机制。该函数实现相关的初始化,实际上该初始化函数仅仅是将用于早期ioremap的固定虚拟地址空间FIX_BTMAP_BEGIN_FIX_BITMAP_END的虚拟地址存放到数组slot_virt中。

3. 完成DTB虚实地址映射:__fixmap_remap_fdt

前面early_fixmap_init已经为DTB固定虚拟地址设置了前两级转换表,此时再设置一个或者两个PMD entry即可。那么一个或者两个是怎么定的呢?主要是看DTB在物理地址空间是否跨2M的边界,因为DTB是按section(2M)来做映射的,如果DTB跨2M边界,则需要连续两个pmd entry。由于DTB最大2M,如果DTB物理基地址不是2M对齐的,则有可能出现DTB跨2M边界的情况。

3.1. dt_virt_base = __fix_to_virt(FIX_FDT);

计算得出分配给dtb的虚拟基地址。

3.2. create_mapping_noalloc:first

设置第一个section mapping,主要就是设置PMD entry。注意,这里noalloc的意思是,不会分配新的地址转换table,只会填充某个table的entry。该函数的具体代码我们不去一一分析了,我这里把其中比较重要的点列出来,供有兴趣的朋友分析代码是参考:

  • 该函数中设置DTB虚实地址映射只需要设置一个pmd entry,因为early_fixmap_init函数已经设置了前两级映射。
  • 固定虚拟地址空间定义了四个page,用于访问PGD,PUD,PMD,PTE四级页表,在当前上下文,这四级页表用于其自身的虚实地址映射及DTB虚实地址映射。也就是说首先要为页表做虚实地址映射,以便CPU可以使用虚拟地址访问页表,之后设置页表,实现DTB虚实地址映射。

3.3. create_mapping_noalloc:second

如果第一个section mapping无法覆盖完成的DTB,则需要设置第二个section mapping。

第二阶段主要是分析固定虚拟地址的映射,当然主要讲的是DTB,还有一些其他固定虚拟地址,我们后面遇到还会分析。

Linux内核固定虚拟地址映射相关推荐

  1. linux内核内存虚拟地址映射物理地址

    先说明下什么是虚拟地址. Linux 内核给每个进程都提供了一个独立的虚拟地址空间,并且这个地址空间是连续的.虚拟地址空间的内部又被分为内核空间和用户空间两部分.不同字长(也就是单个 CPU 指令可以 ...

  2. linux内核之虚拟文件系统

    一.虚拟文件系统概述 虚拟文件系统VFS(也成虚拟文件交换)作为内核子系统,为用户空间程序提供了文件和文件系统相关的统一接口.通过VFS,应用程序可以使用相同接口完成不同介质上不同文件系统的数据读写操 ...

  3. linux内核1G虚拟地址空间的映射规则以及什么是高端内存?

    前面我们讲了,在32位linux内核里,内核地址空间是0xc0000000~0xffffffff, 大小1G:内核地址空间是0x00000000~0xbfffffff,大小3G.当内核代码访问内存时, ...

  4. 深入linux内核架构--虚拟文件系统VFS

    [推荐阅读] Linux内核源码分析--内核启动之zImage自解压过程 你应该知道的Linux内核基础及内核编译 深入理解LINUX内核堆栈 [零声教育]vico老师教你怎么学习Linux内核 值得 ...

  5. Linux内核 mipi虚拟通道,基于NVP6324的4路模拟720P/1080P 视频输入方案

    基于NVP6324的4路模拟720P/1080P 视频输入方案 4路720P视频采集.4路AHD视频采集.4路模拟高清.Linux 4路AHD视频输入.4路模拟摄像头输入.4路1080P视频输入.i. ...

  6. linux内核地址映射,Linux内核设备驱动地址映射笔记整理

    #include #define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)//cookie表示物理地址, size表示映射 ...

  7. Linux内核 LCD 驱动程序框架

    Linux 内核 LCD 驱动程序框架 1. framebuffer 简介 1.1 什么是 framebuffer 1.2 framebuffer的作用 2. framebuffer 驱动的框架 3. ...

  8. Linux内核中断号映射过程分析(三)

    1.概述 早期的CPU中断数量较少,中断系统简单,Linux内核可以将硬件中断号直接映射为软件中断号.但随着CPU支持的中断数量越来越多,中断系统也被设计的越来越复杂,一个CPU内部可能包含多个中断控 ...

  9. Linux内核探秘读书笔记

    (Linux内核探秘(高剑林著 )读书笔记) Linux 文件系统探秘 一 文件系统基本概念 1.1 VFS     Linux内核通过虚拟文件系统(VFS)管理文件系统.     对每个具体文件系统 ...

最新文章

  1. .NET开发微信小程序-微信支付
  2. MSSQL - 通用存储过程
  3. H.264软件解码器在PXA270平台上的优化
  4. 通过八叉树进行空间分割和搜索
  5. OpenCV-累计概率霍夫变换cv::HoughLinesP
  6. 王佩丰数据透视表(六到十一讲)
  7. Windows 10 到期时间如何查看
  8. 小福利,制作词云图的第三种方法---stylecloud库,两行代码制作词云图
  9. Python实现网页自动化-浏览器查找元素(二)
  10. 回顾2021,展望2022,静Yu的万粉成长之路
  11. 计算机老是蓝屏需要重新启动3,电脑经常蓝屏,需要重启,怎么办?
  12. sqlserver查询今日和昨日数据
  13. 视频教程-wordpress建站教程之环境部署详解课程-PHP
  14. Ajax 完整教程-(三)
  15. Abbkine细胞周期染色试剂盒特色和实验建议
  16. 开源增强型zigbee协议栈
  17. 【iPhone/iPad】苹果iOS9正式版更新升级及固件刷机教程
  18. ACM新生赛部分题解
  19. 校园图书馆模拟器极其简陋版
  20. Excel操作 Microsoft.Office.Interop.Excel.dll的使用

热门文章

  1. 《北京遇上西雅图》[HD-RMVB.720p.国语中字][2013年爱情喜剧]
  2. 计算机无法选择字体,电脑系统字体无法修改字体大小怎么办?
  3. 【UML】-- 活动图练习题含答案(打印合同、请假、公司评审、签订合同、软件发布、会见客户)
  4. 汝州九峰山下自产自销的好蜂蜜
  5. Sgu 101 欧拉通路
  6. WR720N硬改16M flash
  7. 鸿蒙系统和安卓哪个更流畅,鸿蒙系统比安卓系统更流畅吗?
  8. Adguard Mac版(广告拦截软件)
  9. Houdini 导出粒子替代物至Maya渲染
  10. 恶意软件NOKKI和朝鲜“Group123”APT组织关联的最新证据