RFC-0245:VMO 预提取

RFC-0245:VMO 预提取
状态已接受
区域
  • 内核
说明

用于预提取 VMO 中数据以准备读取访问的操作。

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2024-03-19
审核日期(年-月-日)2024-04-09

摘要

拥有 ZX_VMO_OP_COMMIT 的只读类似项,用于填充 VMO 以进行即时读取访问。

设计初衷

现有的 COMMIT 操作 ZX_VMO_OP_COMMITZX_VMAR_OP_COMMIT 是面向用户的性能工具。借助这些标记,用户可以指明要使用 VMO 或 VMAR 的范围,并允许内核更高效地批量分配所有页面,从而避免日后需要处理许多故障。

由于 COMMIT 旨在模拟写入,因此目前存在两个缺点。首先,它需要对 VMAR 和/或 VMO 拥有写入权限,如果是某些可执行数据,则可能没有此权限。其次,它会主动执行写时复制并分配页面,如果该范围日后只会被读取,则这两项操作都是不必要的,并且会浪费内存。

目前,Starnix 受到了第一个缺点的影响,该缺点源自其使用由只读分页器支持的 VMO。PREFETCH 操作可以解决这两个缺点,同时保留 COMMIT 的预期优势。

利益相关方

教员

cpu@google.com

Reviewers:

adamperry@google.com、dworsham@google.com

咨询了

rashaeqbal@google.com

社交

此功能是 Starnix 团队和虚拟内存团队之间讨论的结果。

要求

应将 PREFETCH 操作添加到 VMO(作为 ZX_VMO_OP_PREFETCH)和 VMAR(作为 ZX_VMAR_OP_PREFETCH)。这些操作应仅需要对其各自的句柄拥有读取权限,并且应执行必要的工作,以便日后执行的读取操作的工作量降到最低。因此,预提取可能:

  • 请求用户分页器中范围内的所有缺失页面
  • 解压缩该范围内的所有页面
  • 对于 VMAR,为范围内的所有页面创建硬件页表

设计和实现

内核虚拟机内部已经拥有支持此功能的大多数工具,实现方式主要是布置新的 API 标志。因此,这可以通过一个或两个小型 CL(如果 VMO 和 VMAR 实现分开)来实现,包括任何相关测试和文档等。

性能

这项更改不应影响任何现有功能的性能,我们将通过现有基准进行验证。

安全注意事项

预提取在逻辑上等同于用户在整个范围内执行手动读取。除了需要 READ 权限(而非 WRITE 权限)之外,其余要求和限制与 COMMIT 完全相同,因此这里没有新的安全注意事项。

测试

我们将在核心测试套件中添加测试,以验证系统是否支持 PREFETCH 操作并正确触发用户分页器请求。

由于这些系统在性能方面有意向于对用户保持高度透明,因此很难从用户空间测试其他方面,例如 PREFETCH 触发的解压缩。由于基于性能的单元测试本身就不可靠(尤其是由于模拟器执行),因此我们将尽可能使用内核单元测试来测试这些行为。

替代方案

更改 COMMIT 以模拟读取

可以更改现有 COMMIT 操作的语义,以模拟读取,而不是引入 PREFETCH 操作。虽然这对于 Starnix 用例来说已经足够了,但其他现有用户确实希望进行写入模拟并提前分配页面,以避免日后写入时出现故障和分配问题。

继续使用 ALWAYS_NEED

Starnix 目前通过使用 ALWAYS_NEED 操作来解决缺少 PREFETCH 操作的问题。ALWAYS_NEED 执行的初始操作与 PREFETCH 需要执行的初始操作相同,即提取所有缺失的页面并解压缩等。与 PREFETCH 不同,它还会额外声明,应尽可能不回收此内存。这会增加系统内存压力,并可能会增加发生 OOM 或用户体验下降的可能性。

其他 zx_vmar_map 选项

除了支持 VMAR 操作之外,还可以通过 ZX_VM_MAP_RANGE_PREFETCH 等其他选项在映射创建时支持 PREFETCH。这项优化可避免在创建映射后需要发出预取操作。

目前尚不清楚是否有必要避免额外的系统调用,此 RFC 不想排除在 zx_vmar_map 中提供额外支持的可能性,但需要单独的动机,这超出了本文档的范围,可在需要时在后续提案中进行。