由linux那些事之中断与异常(AMD64架构)_2》分析可知,在kernel启动过程中首先安装的early中断dt_setup_early_handler中,主要是对page fault中断支持,这是早期第一个page fault中断处理称为early page fault.

early page fault处理的内核空间

early page fault主要是为后续用到的虚拟地址空间建立映射方式。

需要特别指出的是,此段空间映射采用虚拟地址 与物理地址一一对应映射的方式,主要是方便进行管理,并且此时buddy还没有启动不能通过buddy分配物理内存,由内核空间划分可知,内核中存在一段虚拟地址和物理地址一一映射空间, 4级page table 位于0xfff888000000000~ffffc87fffffffff

5级 page table位于 0xff11000000000000~0xff90ffffffffffff:

early page table entry划分

根据 五级转换分布使用如下:

  • early_top_pgt 用于专门管理pgd表
  • 其余p4d、pud、pmd统一使用 early_dynamic_pgts进行管理以节约物理内存
  • 采用huge page

early_top_pgt

early_top_pgt 定义如下:

extern pgd_t early_top_pgt[PTRS_PER_PGD];

entry 占用8个字节,early_top_pgt 实际占用内存大小为512*8=4096 一个page 大小。

由于在内核还为启动因此early_top_pgt 不能通过buddy分配物理内存,只能通过汇编初始化并申请空间(arch\x86\kernel\head_64.S:

SYM_DATA_START_PTI_ALIGNED(early_top_pgt).fill   512,8,0.fill    PTI_USER_PGD_FILL,8,0
SYM_DATA_END(early_top_pgt)

通过.file 指令,重复执行512次,每次将8个字节空间填充为0。

early_dynamic_pgts

early_dynamic_pgts定义如下:

#define EARLY_DYNAMIC_PAGE_TABLES    64extern pmd_t early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];

共计64*512=32,768 个entry ,占用64个page 物理页。(并没有为一一映射空间申请全部entry,个人认为主要是用于节约物理内存,内核需要并不需要太多物理内存)。

early_dynamic_pgts 初始化同样是使用汇编:

SYM_DATA_START_PAGE_ALIGNED(early_dynamic_pgts).fill 512*EARLY_DYNAMIC_PAGE_TABLES,8,0
SYM_DATA_END(early_dynamic_pgts)

early_make_pgtable()

early_make_pgtable()函数为:

int __init early_make_pgtable(unsigned long address)
{unsigned long physaddr = address - __PAGE_OFFSET;pmdval_t pmd;pmd = (physaddr & PMD_MASK) + early_pmd_flags;return __early_make_pgtable(address, pmd);
}
  • unsigned long physaddr = address - __PAGE_OFFSET;  计算虚拟地址对应的物理地址,一一映射,虚拟地址减去__PAGE_OFFSET偏移,4级别page table __PAGE_OFFSET为0xfff888000000000
  • 计算之后的物理地址 结合early_pmd_flags (主要是权限),组成PTE entry ,调用__early_make_pgtable 设置到page table中

__early_make_pgtable

__early_make_pgtable walk page table, 并设置PTE entry到page table中:


/* Create a new PMD entry */
int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
{unsigned long physaddr = address - __PAGE_OFFSET;pgdval_t pgd, *pgd_p;p4dval_t p4d, *p4d_p;pudval_t pud, *pud_p;pmdval_t *pmd_p;/* Invalid address or early pgt is done ?  */if (physaddr >= MAXMEM || read_cr3_pa() != __pa_nodebug(early_top_pgt))return -1;again:pgd_p = &early_top_pgt[pgd_index(address)].pgd;pgd = *pgd_p;/** The use of __START_KERNEL_map rather than __PAGE_OFFSET here is* critical -- __PAGE_OFFSET would point us back into the dynamic* range and we might end up looping forever...*/if (!pgtable_l5_enabled())p4d_p = pgd_p;else if (pgd)p4d_p = (p4dval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);else {if (next_early_pgt >= EARLY_DYNAMIC_PAGE_TABLES) {reset_early_page_tables();goto again;}p4d_p = (p4dval_t *)early_dynamic_pgts[next_early_pgt++];memset(p4d_p, 0, sizeof(*p4d_p) * PTRS_PER_P4D);*pgd_p = (pgdval_t)p4d_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE;}p4d_p += p4d_index(address);p4d = *p4d_p;if (p4d)pud_p = (pudval_t *)((p4d & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);else {if (next_early_pgt >= EARLY_DYNAMIC_PAGE_TABLES) {reset_early_page_tables();goto again;}pud_p = (pudval_t *)early_dynamic_pgts[next_early_pgt++];memset(pud_p, 0, sizeof(*pud_p) * PTRS_PER_PUD);*p4d_p = (p4dval_t)pud_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE;}pud_p += pud_index(address);pud = *pud_p;if (pud)pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);else {if (next_early_pgt >= EARLY_DYNAMIC_PAGE_TABLES) {reset_early_page_tables();goto again;}pmd_p = (pmdval_t *)early_dynamic_pgts[next_early_pgt++];memset(pmd_p, 0, sizeof(*pmd_p) * PTRS_PER_PMD);*pud_p = (pudval_t)pmd_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE;}pmd_p[pmd_index(address)] = pmd;return 0;
}
  • pgd_p = &early_top_pgt[pgd_index(address)].pgd; 根据虚拟地址 查找到对应pgd 表
  • 如果pgtable_l5_enabled 5级映射没有使能,则p4d表不存在,直接与pdg相等
  • 如果设置5级 page table,则查找p4d entry是否存在,如果不存在则从early_dynamic_pgts 获取到一个entry,并设置到pdg 表中
  • pud表 过程同上
  • 后续一直遍历到pmd表中 并将entry 设置到pmd中(没有PTE表采用huge page进一步节约early_top_pgt 物理内存。

linux那些事之early pape fault相关推荐

  1. linux那些事之page fault(AMD64架构)(user space)(2)

    do_user_addr_fault 用户空间地址处理是page fault主要处理流程,x86 64位系统主要是do_user_addr_fault()函数 该处理部分是x86架构特有部分 即与架构 ...

  2. linux那些事之LRU(3)

    继续承接<linux那些事之LRU(2)>,shrink_active_list()函数中需要将调用isolate_lru_pages函数将active LRU中从链表尾部隔离出nr_to ...

  3. linux那些事之pin memory相关API

    内核中为pin memory 用户空间申请物理内存除了get_user_pages() API函数之外,还有其他相关一系列函数,主要位于mm\gup.c 主要都是针对get_user_pages进行的 ...

  4. linux那些事之TLB(Translation-Lookaside Buffer)无效操作

    TLB 为了加速虚拟地址转换物理地址过程,CPU内部一般都集成TLB硬件单元,通过缓存存取虚拟地址与物理地址映射关系,避免再通过MMU 通过多级查表引入多次内存开销,直接将映射关系存储到硬件单元中,本 ...

  5. linux那些事之follow_page

    follow_page()函数是内核中用于根据虚拟地址查找对应的物理页函数,函数定义如下: struct page *follow_page(struct vm_area_struct *vma, u ...

  6. 网吧软件正版化,别拿Linux说事

    <!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --> 5月15日,媒体盛传微软开始对东莞市网吧行业"下手" ...

  7. Linux内核运行时错误:general protection fault

    最近帮师兄做内核实验,错误不断,由于是修改的内核代码,所以经常遇到错误排查起来都比较麻烦,刚解决了一个问题下一个问题就又出现了. 直接上新问题的描述:general protection fault ...

  8. linux内核那些事之early boot memory-memblock

    Why need early boot memory? early boot memory即位于系统上电到内核内存管理模型构建之前这段内存管理阶段,严格说它只是系统启动过程中一个中间阶段的内存管理,当 ...

  9. linux那些事之page fault(AMD64架构)(1)

    应用程序或者内核都是运行在虚拟内存空间之中,kernel 启动完成之后如果一个虚拟地址要访问物理内存需要通过CPU MMU硬件进行地址转换,整个虚拟地址访问物理内存逻辑过程如下: kernel 启动完 ...

最新文章

  1. NAT技术解决了IPv4地址短缺的问题,假设内网的地址数是m,而外网地址数n,若mn,则这种技术叫做(66),若mn,且n=1,则这种技术这叫做(67)。【答案】A C
  2. 讲真,上班路上 1 小时算很幸福了!
  3. python实现实例_用python语言实现斗地主基础版-案例
  4. [Qt教程] 第23篇 数据库(三)利用QSqlQuery类执行SQL语句
  5. Spark配置参数详解
  6. c语言宏高级用法,C语言宏高级用法 [总结]
  7. sapmto生产模式配置及操作详解_硬岩制砂线怎么设计?300t/h的生产流程与设备配置详解...
  8. bartender的安全策略不允许指定的用户执行此操作_Linux sudo 被曝提权漏洞,任意用户均能以 root 身份运行命令...
  9. java python c++比喻图_Java/Python/PHP/C++图文详解它们之间的尿性
  10. from scipy import special, optimize, from ._nnls import nnls ImportError: DLL load failed: 找不到指定的模块。
  11. opengl代码实例_一步步学OpenGL(22) -《OpenGL使用Assimp库导入3d模型》
  12. Intouch2020安装与授权
  13. 诺基亚PC套件界面设计
  14. 【Python系列】python文件或文本加密(4种方法)
  15. HTML网页制作——制作一个属于自己的网页
  16. 上传漏洞靶场:upload-labs 8-13关
  17. Android Studio中关于消除“Permission is only granted to system apps”错误的方法
  18. Attach函数的讲解
  19. 计算机分享硬盘,共享磁盘是什么怎么设置
  20. 中科院自动化所 模式识别国家重点实验室(NLPR)

热门文章

  1. 公众号第三方平台开发 - 教程五 代公众号发起网页授权源码
  2. 微服务架构案例(05):SpringCloud 基础组件应用设计
  3. Shell编程入门(第二版)(下)
  4. centos清楚缓存
  5. Android程序打开和关闭输入法
  6. android中自定义RadioButton
  7. React 源码剖析系列 - 解密 setState
  8. 组播穿越MPLS ***+SSM
  9. 【转】桌面快捷方式不见了的解决办法
  10. java获取linux下面所有线程,获取Linux中Java线程的线程ID