LWN:在 direct map 之外管理 page!

作者: Jonathan Corbet
2026年5月13日 


LSFMM+BPF 

当 Brendan Jackman 提议 为 2026 年 Linux 存储、文件系统、内存管理和 BPF 峰会 (Linux Storage, Filesystem, Memory Management, and BPF Summit) 举办一场会议时,他的主题是“为内核提供一个页表库 (pagetable library)”。然而,在实际的内存管理轨道 (memory-management-track) 会议期间,他表示这个想法已经“泡汤了 (fizzled)”,他将改为讨论相关的主题。最终的结果是一场关于如何高效管理那些不存在于内核直接映射 (direct map) 中的页面的会议。 

直接映射将系统的整个物理地址空间 (physical address space) 都置于内核的虚拟地址空间 (virtual address space) 之内(至少在 64 位系统上是这样)。这使得内核无需先建立任何映射即可访问系统中的任何内存位置。直接映射既快速又方便,但它也使得内核容易以非预期的方式访问内存,这可能是由于 Bug、推测执行漏洞或某种形式的系统受损造成的。因此,将包含敏感数据的内存从直接映射中移除,可以带来显著的安全收益。 

Jackman 首先提到,他研究地址空间隔离 (address-space isolation) 已经有一段时间了,这涉及大量的直接映射移除工作。进展虽然缓慢,但他收到的反馈一直是积极的。目前,他正困于一些技术细节,同时也由于他的补丁集规模庞大到令人望而生畏,缺乏评审也阻碍了他的进度。因此,他正尝试将问题分解为更小、更容易评审的部分。 

其中一个部分是允许分配未映射(即不在直接映射中)的内存。他说, Firecracker 虚拟化管理器的开发者一直在尝试各种方法,将客户机内存从宿主机的直接映射中移除,但结果并不理想。他曾 提议 对内存分配器进行一系列更改,以提供一个新的分配标志 (allocation flag)  __GFP_UNMAPPED ,用于请求不存在于直接映射中的内存。实现该标志需要添加一些新的基础设施,以使这种分配比当前内核更高效。这些更改非常显著,且可能存在争议;他(笑着)提醒大家,如果开发者不进行评审,David Hildenbrand 就会合并这些更改。 

具体来说,该系列补丁改变了现有的“迁移类型” (migration type) 概念,目前该概念用于区分可移动和不可移动的分配。迁移类型将被“空闲类型” (freetype) 取代,后者包含有关内存块的其他属性——包括该内存块当前是否在直接映射中。这将允许从直接映射中批量移除内存块,以便快速满足  __GFP_UNMAPPED  分配请求。 

然而,从直接映射中移除内存的问题在于,内核将无法再访问该内存(毕竟这正是移除的目的),但有时内核恰恰需要这样做。在分配时清零页面、实现类似于  read()  的系统调用、处理写时复制 (copy-on-write, COW) 故障,以及填充  guest_memfd 内存,都是内核有正当理由需要访问内存的例子。Jackman 对这个问题的回答是内核中的一种构造,他称之为“mermap”;它允许将页面短暂地映射到内核地址空间中,以便执行操作。 

Mermap 映射是 CPU 本地的 (CPU-local);只有请求映射的 CPU 才能使用它。这很像  kmap_local_page() ,但该函数创建的映射对所有 CPU 都是可见的,而 mermap 则不然。另一个区别是,mermap 能够一次映射多个页面。此外,至关重要的一点是,它允许映射失败。 

使用  __GFP_UNMAPPED  还存在其他一些风险。为了提高性能,mermap 在移除临时映射后不会执行 TLB 刷新 (TLB flush);这可能会留下过期的 TLB 条目 (stale TLB entries)。可以想象,这些条目可能被用于在内存取消映射后访问它;不过,在地址再次被映射之前,它们“肯定”会被刷新,因此不存在获取错误内存内容的风险。他正在考虑要求分配器的使用者在释放页面之前执行 TLB 刷新;否则,这些页面可能会在过期 TLB 条目依然存在的情况下被其他地方重用。总的来说,他认为这并不是最好的 API,并对如何改进它很感兴趣。 

Liam Howlett 建议将 mermap 挂钩到 lockdep 检查器 (lockdep checker) 中(该检查器通常用于检测锁定 Bug),作为检测在没有相应 TLB 刷新的情况下释放临时映射页面的代码的一种手段。Matthew Wilcox 想知道是否可以使用  作用域资源管理原语 (scoped resource-management primitives) 来确保在编译时页面释放时会发生 TLB 刷新。这种方法的问题在于页面分配和释放发生在不同的作用域中,因此该问题并不符合这一模型。David Hildenbrand 询问,如果在页面本身追踪“释放时需要 TLB 刷新”的状态是否有帮助;Jackman 说这会有帮助,但这需要一个页面标志 (page flag),而这些标志资源一直非常紧缺。 

Jackman 向参会者提出的最后一个问题是,使用 GFP 标志是否合适。目前存在一种趋势,即总体上减少对 GFP 标志的依赖,因此增加一个新的标志可能并不受欢迎。在这种情况下,真正需要的只是将“未映射”位引入页面分配器的方法。Hildenbrand 建议添加一个新的分配上下文 (allocation context),但 Jackman 表示,对未映射内存的需求取决于其中存储的数据属性,而不是内核当前运行的上下文。 

至此,会议时间耗尽。Jackman 已经发布了 他自己对会议的总结 ,并提供了指向  他幻灯片 的链接。 

关注了就能看到更多这么棒的文章哦~   全文完
 LWN 文章遵循 CC BY-SA 4.0 许可协议。 

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值