0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ARM64 Linux内核页表的块映射

Linux阅码场 来源:Linuxer 作者:Linuxer 2021-01-04 13:37 次阅读

内核文档Documentation/arm64/memory.rst描述了ARM64 Linux内核空间的内存映射情况,应该是此方面最权威文档。

以典型的4K页和48位虚拟地址为例,整个内核空间的虚拟地址分布如下:

173d710c-4e4d-11eb-8b86-12bb97331649.png

从ffff000000000000到ffff7fffffffffff是一段针对物理地址的线性映射区,最大支持128TB的物理地址空间,这一段地址非常类似ARM32的low memory映射区。

我们看看这种情况下的页表,我们既可以用最终的【20:12】对应的PTE映射项,以4K为单位,进行虚拟地址到物理地址的映射;又可以以【29:21】对应的PMD映射项,以2M为单位,进行虚拟地址到物理地址的映射。

1764476e-4e4d-11eb-8b86-12bb97331649.png

对于用户空间的虚拟地址而言,当我们进行的是PMD映射的时候,我们得到的是Huge Page,ARM64的2MB的huge page,在虚拟和物理上都连续,它在实践工程中的好处是,可以减小TLB miss,因为,如果进行了2MB的映射,整个2MB不再需要PTE,映射关系大为减小。

178dd1ce-4e4d-11eb-8b86-12bb97331649.png

对于内核空间而言,从ffff000000000000到ffff7fffffffffff的这段虚拟地址,如果与物理地址进行的是一种PMD映射的话,显然也可以达到同样的效果。但是,这不意味着它们就是Huge Page。众所周知,内核开机把物理地址往虚拟地址进行线性映射,并不意味着这片内存被内核拿走了,它只是进行了一种映射,以便日后调用kmalloc(),get_free_pages()等API申请的内存是直接已经有虚实映射的。所以,即便内核进行的就是PMD映射,在内存的分割上,还是可以以4K为单位的:

17c8ca68-4e4d-11eb-8b86-12bb97331649.png

所以,即便我们在内核空间进行PMD映射,里面的每个蓝色圆圈(一个4K页),还是可以被单独分配的,这种分配可以是kmalloc、vmalloc,用户态的malloc等。内核态进行的PMD映射,不意味着相关的2MB成为了huge page,它纯粹只是为了服务于当内核以线性映射的虚拟地址访问该物理地址的时候(我们认为内核大多数时候是用这个线性映射的虚拟地址的),减小TLB miss。

当然,更牛逼的情况下,内核应该也可以直接用【38:30】位的PUD来进行映射,这样映射关系是1GB的,则整个1GB后面占TLB的时候,只需要占一个入口。

1835a250-4e4d-11eb-8b86-12bb97331649.png

当然,如果用户态的虚实映射是这样的,用户实际得到了一个1GB的巨页。但是对于内核的线性映射区域而言,即便我们进行了1GB的PUD映射,这1G内部就可以进一步切割为4KB页或者2MB的巨页。记住:内核态的线性映射区的映射只是个映射关系,不是个分配关系。比如下面的1GB的内核线性映射的1GB区域,仍然可以被4K分配走,或者被用户以huge page以2MB为单位分配走:

185868b2-4e4d-11eb-8b86-12bb97331649.png

我们需要一个真实的调试手段来验证我们的想法,这个调试手段就是PTDUMP(Page Table Dump),相关的代码在ARM64内核的:

arch/arm64/mm/ptdump.c和ptdump_debugfs.c

我们把它们全部选中,这样我们可以得到一个debugfs接口

/sys/kernel/debug/kernel_page_tables

来获知内核态页表的情况。

我用qemu启动了一个4GB内存的ARM64虚拟机,可以看到前1GB的虚拟地址空间大多数是PMD和PTE映射,后面的3GB,全是PUD映射:

188ac456-4e4d-11eb-8b86-12bb97331649.png

我的内核启动参数加了rodata=0:

$ cat/proc/cmdlineroot=/dev/vda2 rw console=ttyAMA0 ip=dhcp rodata=0

原因是内核在几种情况下,是不会做这种PMD和PUD映射的,相关代码见于:

18d0ee68-4e4d-11eb-8b86-12bb97331649.png

191e8b00-4e4d-11eb-8b86-12bb97331649.png

rodata_full在默认情况下总是成立的,它对应着内核的一个Config选项CONFIG_RODATA_FULL_DEFAULT_ENABLED, "Apply r/o permissions of VM areas also to their linear aliases",这个选项提高了内核的安全性,但是减小了内核的性能。

197a2640-4e4d-11eb-8b86-12bb97331649.png

我在内核启动参数加的rodata=0实际上是让rodata_full为false。如果我把这个kernel启动选项去掉,我得到的内核页表是完全不一样,线性映射区也全部是PTE映射:

199d2ee2-4e4d-11eb-8b86-12bb97331649.png

最后,值得一提的是,不仅线性映射区可以使用PMD映射,vmemmap映射区也是在4K页面情况下,默认用PMD映射的:

1a0676fe-4e4d-11eb-8b86-12bb97331649.png

字节跳动的宋牧春童鞋发了一个patchset,企图在用户分得巨页的情况下,删除巨页内部的4KB的小page占用的page struct的内存消耗,这个patchset在圣诞节前目前发到了V11:

https://lore.kernel.org/linux-mm/20201222142440.28930-1-songmuchun@bytedance.com/

1a6a8f18-4e4d-11eb-8b86-12bb97331649.png

在这个patchset中,它就需要拆分vmemmap的PMD映射为PTE映射:

1b367c4a-4e4d-11eb-8b86-12bb97331649.png

这个patchset的原理建立在,当内核以4KB分页的时候,每个page需要64字节的page struct。但是,当用户把它分配为巨页的时候,时候,我们不再需要一个个4KB单独用page struct描述,对于这种compound page的情况,我们应该可以把后面的page struct的内存直接释放掉,因为情况完全是雷同的,这样可以剩下不少内存。

责任编辑:xj

原文标题:宋宝华: ARM64 Linux内核页表的块映射

文章出处:【微信公众号:Linuxer】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ARM
    ARM
    +关注

    关注

    134

    文章

    9094

    浏览量

    367538
  • 内核
    +关注

    关注

    3

    文章

    1372

    浏览量

    40289
  • Linux
    +关注

    关注

    87

    文章

    11304

    浏览量

    209474
  • 板块
    +关注

    关注

    0

    文章

    3

    浏览量

    7578

原文标题:宋宝华: ARM64 Linux内核页表的块映射

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    linux驱动程序如何加载进内核

    Linux系统中,驱动程序是内核与硬件设备之间的桥梁。它们允许内核与硬件设备进行通信,从而实现对硬件设备的控制和管理。 驱动程序的编写 驱动程序的编写是Linux驱动开发的基础。在编
    的头像 发表于 08-30 15:02 467次阅读

    Linux内核测试技术

    Linux 内核Linux操作系统的核心部分,负责管理硬件资源和提供系统调用接口。随着 Linux 内核的不断发展和更新,其复杂性和代码规
    的头像 发表于 08-13 13:42 493次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>测试技术

    Linux内核映射的基础知识

    大家在看内核代码时会经常看的以上术语,但在ARM的芯片手册中并没有用到这些术语,而是使用L1,L2,L3这种术语。
    的头像 发表于 08-07 15:53 907次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>中<b class='flag-5'>页</b><b class='flag-5'>表</b><b class='flag-5'>映射</b>的基础知识

    3568F-Linux系统使用手册

    userspace主频 模式使能的主频,请修改Linux内核源码"arch/arm64/boot/dts/rockchip/"目录下的内核设 备树文件
    发表于 07-25 15:45

    Pine64 发布 Oz64 单板计算机:Arm、RISC-V任你切换

    Pine64公司最新推出Oz64单板计算机(SBC),其最大的亮点采用SopghoSG2000双架构芯片,可切换支持Arm和RISC-V。IT之家附上SopghoSG2000双架构芯片相关信息如下
    的头像 发表于 06-30 08:37 299次阅读
    Pine<b class='flag-5'>64</b> 发布 Oz<b class='flag-5'>64</b> 单板计算机:<b class='flag-5'>Arm</b>、RISC-V任你切换

    【米尔-瑞米派兼容树莓派扩展模块-试用体验】 实时系统移植

    /myir-renesas-linux$ make ARCH=arm64 mys_g2lx_defconfig hjx@myir-server:/renesas/04_Sources/myir-renesas-linux
    发表于 06-19 16:57

    Linux 6.10集成RISC-V更新,支持Rust编程语言

    本次补丁升级中,Linux内核进一步扩展了对应于RISC-V架构的Rust编程语言支持。在此之前,Rust已可应用在x86_64、龙芯LoongArch以及ARM64等多种架构之上。
    的头像 发表于 05-23 17:16 960次阅读

    【鸿蒙】OpenHarmony运行docker详细步骤

    check-config.sh 2.在编译命令 ./build.sh --product-name rk3568 --ccache --target-cpu arm64 编译 arm64 位系统情况下 进入
    的头像 发表于 03-02 15:10 2633次阅读
    【鸿蒙】OpenHarmony运行docker详细步骤

    向后移植了cypress-fmac-v5.15.58-2023_0801到arm64内核 5.10.104,insmod brcmfmac崩溃怎么解决?

    向后移植了 cypress-fmac-v5.15.58-2023_0801 到 arm64 内核 5.10.104。 在加载内核模块 brcmfmac.ko 时,按照自述文件中的说明进行操作, 我
    发表于 03-01 09:00

    Linux内核内存管理之内核非连续物理内存分配

    的主要优点是避免了外部碎片,而缺点是需要修改内核。显然,非连续内存区域的大小必须是4096的倍数。Linux使用非连续物理内存区的场景有几种:(1)为swap区分配数据结构;(2)
    的头像 发表于 02-23 09:44 972次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>内存管理之<b class='flag-5'>内核</b>非连续物理内存分配

    arm开发板如何安装linux系统

    工具和软件: 一台运行Linux系统的电脑 一个支持ARM架构的开发板 一个USB转串口模块 一根Micro USB线缆 一个SD卡读卡器 一个空的SD卡 一个USB键盘和鼠标(可选) 一个HDMI显示器(可选) 下载Linux
    的头像 发表于 01-24 14:19 3564次阅读

    Linux内核中信号详解

      1 信号的角色 1.1 x86/64架构信号定义 1.2 ARM架构信号定义 1.3 RISC-V架构信号定义 1.4 信号的系统调用 1.5 信号工作原理 2 信号的响应行为 3 POSIX
    的头像 发表于 01-13 09:40 1387次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>中信号详解

    rk3399移植Linux内核

    Linux内核移植到RK3399上。 首先,我们需要了解RK3399的硬件架构和特性。RK3399采用的是ARM架构,具有双核Cortex-A72和四核Cortex-A53处理器,支持
    的头像 发表于 01-08 09:56 1149次阅读

    Linux内核内存管理架构解析

    内存管理子系统可能是linux内核中最为复杂的一个子系统,其支持的功能需求众多,如页面映射、页面分配、页面回收、页面交换、冷热页面、紧急页面、页面碎片管理、页面缓存、页面统计等,而且对性能也有很高
    的头像 发表于 01-04 09:24 665次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>内存管理架构解析

    TQT507开发板如何修改和保存内核配置

    ,如果不存在,则使用默认配置单。编译前请使用原厂的配置单配置内核。 进入/Embedsky/TQT507/CoreA/longan/kernel/linux-4.9/arch/arm64
    的头像 发表于 12-28 14:13 451次阅读
    TQT507开发板如何修改和保存<b class='flag-5'>内核</b>配置