当前位置:首页>Linux>AArch64 Linux 内存布局

AArch64 Linux 内存布局

  • 2026-09-10 17:16:53
AArch64 Linux 内存布局

作者: Catalin Marinas catalin.marinas@arm.com

本文档描述了 AArch64 Linux 内核使用的虚拟内存布局。该架构允许在使用 4KB 页面大小时最多支持 4 级转换表,而在使用 64KB 页面大小时最多支持 3 级转换表。

AArch64 Linux 在使用 4KB 页面配置时采用 3 级或 4 级转换表,分别为用户空间和内核提供 39 位(512GB)或 48 位(256TB)虚拟地址空间。当使用 64KB 页面时,仅使用 2 级转换表,提供 42 位(4TB)虚拟地址空间,但内存布局是相同的。

ARMv8.2 添加了对大虚拟地址空间的可选支持。此功能仅在运行 64KB 页面大小时可用,并扩展了第一级转换表中的描述符数量。

TTBRx 的选择由虚拟地址的第 55 位决定。swapper_pg_dir 仅包含内核(全局)映射,而用户页全局目录(pgd)仅包含用户(非全局)映射。swapper_pg_dir 的地址被写入 TTBR1,永远不会写入 TTBR0。

当在不使用虚拟化主机扩展(Virtualization Host Extensions)的情况下使用 KVM 时,管理程序(hypervisor)在 EL2 级别以线性映射的固定(且可能随机)偏移量映射内核页面。更多详细信息,请参阅kern_hyp_va 宏和kvm_update_va_mask 函数。像 GICv2 这样的 MMIO 设备会被映射在 HYP idmap 页面旁边,当为特定 CPU 启用ARM64_SPECTRE_V3A 时,向量表也会映射在此处。

当在使用虚拟化主机扩展的情况下使用 KVM 时,由于主机内核直接在 EL2 级别运行,因此不会创建额外的映射。

内核中的 52 位 VA 支持

如果存在 ARMv8.2-LVA 可选特性,并且我们运行在 64KB 页面大小下;那么就有可能为用户空间和内核地址都使用 52 位地址空间。然而,任何支持 52 位的内核二进制文件也必须能够在早期启动时,如果硬件特性不存在,回退到 48 位。

这种回退机制要求内核的.text 段位于较高的地址区域,以便它们对于 48/52 位 VA 保持不变。由于 KASAN 影子内存只是整个内核 VA 空间的一部分,KASAN 影子内存的末端也必须位于内核 VA 空间的高半部分,同时适应 48 位和 52 位。(从 48 位切换到 52 位时,KASAN 影子内存的末端是固定不变的,取决于~0UL,而其起始地址将向低地址方向“增长”)。

为了优化phys_to_virt 和virt_to_phys,PAGE_OFFSET 被保持为常数0xFFF0000000000000(对应 52 位),这消除了额外变量读取的需要。物理-虚拟偏移量和 vmemmap 偏移量在早期启动时计算,以实现此逻辑。

由于单个二进制文件需要同时支持 48 位和 52 位 VA 空间,VMEMMAP 的大小必须足够容纳 52 位 VA,并且也必须足够大以容纳固定的PAGE_OFFSET。

内核中的大多数代码不需要考虑VA_BITS,对于那些确实需要知道 VA 大小的代码,变量定义如下:

  • VA_BITS:常量,表示最大 VA 空间大小
  • VA_BITS_MIN:常量,表示最小 VA 空间大小
  • vabits_actual:变量,表示实际 VA 空间大小

最大和最小尺寸对于确保缓冲区足够大或者地址在“最坏”情况下足够接近非常有用。

52 位用户空间 VA

为了保持与依赖 ARMv8.0 VA 空间最大 48 位限制的软件的兼容性,内核默认将从 48 位地址范围返回虚拟地址给用户空间。

软件可以通过指定一个大于 48 位的 mmap 提示参数来“选择加入”接收来自 52 位空间的 VA。

例如:

maybe_high_address = mmap(~0UL, size, prot, flags,...);

也可以通过启用以下内核配置选项来构建一个返回 52 位空间地址的调试内核:

CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y

请注意,此选项仅用于调试应用程序,不应在生产环境中使用。

Src

https://www.kernel.org/doc/html/latest/arch/arm64/memory.html

最新文章

随机文章