内存管理-79-MMU-1-疑问chatGPT
一、Linux系统中有哪些MMU,作用分别是什么?用于把什么地址翻译成什么地址?
注: 基于 Linux + QNX 虚拟化平台。
1. 先给结论Linux
内核本身不实现 MMU,MMU 是 SoC 硬件;Linux 只负责建立页表、处理缺页异常、刷新 TLB。按“谁发起地址访问”来划分,一颗 ARM SoC 上通常有三类软件可见的地址翻译单元:
(1) CPU MMU:每个 CPU core 内部一个,把 CPU 的虚拟地址(VA)翻译成物理地址(PA);在虚拟化环境下变成 VA → IPA → PA。
(2) IOMMU / ARM SMMU:系统级外设地址翻译单元,把设备 DMA 使用的 I/O 虚拟地址(IOVA)翻译成 PA;在虚拟化环境下变成 IOVA → IPA → PA。
(3) GPU MMU:GPU 专用的地址翻译单元,把 GPU 虚拟地址(GPU VA)翻译成 PA(或 IPA);在 Adreno 平台上通常由 KGSL 通过 SMMU context bank + GPU 页表实现。
除此之外,DSP、NPU、ISP、VPU 等加速器一般没有 Linux 独立管理的 MMU,而是挂到某个系统 SMMU 的 context bank 上;虚拟化层的 stage-2 MMU 也不是独立硬件,而是 CPU/SMMU 内部的第二级翻译。
2. 先把地址名词统一
--------------------------------------------------------------------------------------------------------------------------------------- 地址 含义 谁产生 --------------------------------------------------------------------------------------------------------------------------------------- VA 虚拟地址(Virtual Address) CPU 的 load/store、取指 IPA 中间物理地址(Intermediate Physical Address),即 guest 看到的“物理地址” Guest 的 stage-1 翻译输出 PA 真正的物理地址(Physical Address) Hypervisor stage-2 输出 IOVA I/O 虚拟地址,设备 DMA 使用的地址 驱动通过 DMA/IOMMU API 分配 GPU VA GPU 虚拟地址,GPU 命令流、纹理、缓冲使用 GPU/KGSL 分配 ---------------------------------------------------------------------------------------------------------------------------------------
关键点:Linux guest 里的 phys_addr_t / virt_to_phys() 返回的是 IPA,不是 PA。Linux 看不到真正的 PA,PA 由 QNX Hypervisor 的 stage-2 页表管理。
3. CPU MMU
3.1 位置
ARM64 每个 CPU core 内部都有 MMU,负责该 core 上所有 EL0/EL1 的取指和数据访问。
3.2 翻译方向
Stage 1:VA → PA(没有虚拟化时);VA → IPA(有 stage 2 时)
Stage 2:IPA → PA,由 Hypervisor(QNX)在 EL2 配置 VTTBR_EL2
Linux 在 EL1 只控制 stage 1 页表(TTBR0_EL1 用户空间、TTBR1_EL1 内核空间),stage 2 由 EL2 的 Hypervisor 控制。
3.3 主要作用
(1) 进程地址空间隔离:每个进程一套 mm_struct + 页表;
(2) 用户态/内核态权限隔离(EL0/EL1、AP、UXN/PXN);
(3) 按需分页、缺页异常、COW、mmap;
(4) 内存属性控制(Normal/Device、Cacheable、Shareability);
(5) ASID 标记 TLB,上下文切换减少 TLB flush。
3.4 Linux 对应代码
页表管理:arch/arm64/mm/mmu.c、mm/memory.c(缺页)、mm/mmap.c
TLB:arch/arm64/include/asm/tlbflush.h
在 8295 上,Linux guest 的 stage 1 输出 IPA,QNX Hypervisor 的 stage 2 再翻译成 PA。
4. IOMMU / ARM SMMU
4.1 位置
SMMU 是 SoC 内独立的系统级 IP,通常有多个实例。Qualcomm 平台常见的有:
(1) apps_smmu:显示、Camera、Video、PCIe、USB 等大多数外设;
(2) kgsl_smmu:GPU 专用;
(3) 部分平台还有 adsp_smmu、cdsp_smmu 等。
具体节点名因平台而异,Linux 通过设备树的 iommus 属性把设备绑定到某个 SMMU。
4.2 翻译方向
Stage 1:IOVA → PA(非虚拟化);IOVA → IPA(虚拟化)
Stage 2:IPA → PA
SMMU 的查表过程大致是:设备 DMA 请求 → Stream ID(标识设备) → Stream Table Entry (STE) → Context Descriptor (CD) → TTBR0 页表 → 输出 PA / IPA
不同 Stream ID、不同 context bank 相互隔离,所以一块 SMMU 可以同时服务很多设备。
4.3 主要作用
(1) DMA 隔离与安全:设备只能访问驱动为它映射的地址,不能随意读写物理内存;
(2) Scatter-gather:把分散的物理页映射成一段连续 IOVA,交给设备使用;
(3) 地址范围适配:让只有 32 位 DMA 能力的设备访问 4GB 以上内存;
(4) dma-buf 共享:Camera/Display/GPU/Video 之间共享缓冲时,各自映射到自己的 IOVA;
(5) 设备直通/虚拟化:stage 1 由 guest 管理,stage 2 由 hypervisor 管理;
(6) 故障上报:非法 DMA 触发 SMMU fault,而不是静默踩内存。
4.4 Linux 对应代码
框架:drivers/iommu/
ARM SMMUv2:drivers/iommu/arm/arm-smmu/arm-smmu.c
ARM SMMUv3:drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
驱动接口:iommu_map() / iommu_unmap()、dma_map_single() / dma_map_sg()
一个实用判断:dma_addr_t 在使能 IOMMU 时是 IOVA,未使能时才是总线/物理地址;驱动不能假设 dma_addr_t == phys_addr_t。
5. GPU MMU
5.1 位置
GPU 侧的地址翻译单元。在 Adreno 平台上,它通常不是一颗完全独立的芯片,而是:
GPU 内部/旁边的地址翻译硬件;
加上 KGSL 为每个进程维护的 GPU 页表;
在新平台上,这些页表通常挂到专用的 SMMU context bank(如 kgsl_smmu);
历史平台(如更早的 a3xx/a4xx)则使用独立的 GPUMU。
5.2 翻译方向
GPU VA → PA(非虚拟化);
GPU VA → IPA → PA(GPU 直通给 GVM 时,stage 2 由 Hypervisor 叠加)。
5.3 主要作用
(1) 给每个进程独立的 GPU 虚拟地址空间,实现 GPU 侧进程隔离;
(2) 把 GPU 缓冲、纹理、命令流(ringbuffer)、页表自身映射到 GPU VA;
(3) 导入 dma-buf 时,把同一批物理页映射到 GPU VA,避免拷贝;
(4) GPU 页错误隔离和 fault 上报(KGSL 捕获后终止/重启 GPU context);
(5) 部分平台支持 SVA(Shared Virtual Addressing),让 GPU 直接使用 CPU 页表。
5.4 Linux 对应代码
vendor/qcom/opensource/graphics-kernel/kgsl_mmu.c
kgsl_iommu.c(SMMU 路径)、kgsl_gpummu.c(历史 GPUMU 路径)
GPU 映射/缺页:kgsl_mmap()、kgsl_paged_vmfault() 等。
注意:GPU VA 和 CPU VA 是两个独立地址空间。同一个物理页可以同时出现在某进程的 CPU VA 和 GPU VA 中,但两个 VA 数值通常不同。
6. 其它加速器与虚拟化 stage-2
6.1 DSP/NPU/ISP/VPU
大多数情况下没有 Linux 直接管理的独立 MMU;它们作为 SMMU 的 client,使用某个 context bank,由 Linux IOMMU 驱动或固件配置;例如 FastRPC 把 dma-buf 映射给 ADSP/CDSP,底层仍走 SMMU;Hexagon 等处理器内部可能还有自己的地址转换机制,但通常由 DSP 固件管理,Linux 不直接操作。
6.2 Stage-2 MMU
不是独立硬件,而是 CPU MMU / SMMU 的第二级翻译;CPU 侧根页表是 VTTBR_EL2,SMMU 侧是 STE/CD 中的 stage-2 配置;在 8295 上由 QNX Hypervisor 管理,Linux 只看到 IPA;linux-la.config 里配置的内存预留地址是 IPA 范围,不是 PA;Hypervisor 用 stage 2 把它们映射到实际 PA。
实测:
linux-la.config 里配置的内存预留地址(IPA),比如 __GVM_SYSRAM1_START__/__GVM_SYSRAM1_SIZE__ 就是 Linux 内核中能看到的物理地址,已通过 cat 下面两个文件进行了确认。
# cat /sys/kernel/debug/memblock/reserved
# cat /sys/kernel/debug/memblock/memory
7. 一张总表
--------------------------------------------------------------------------------------------------------------------------------------- 翻译单元 输入地址 输出地址 页表/上下文 主要作用 --------------------------------------------------------------------------------------------------------------------------------------- CPU MMU stage 1 VA PA 或 IPA TTBR0_EL1/TTBR1_EL1 进程/内核地址空间、权限、缺页 CPU MMU stage 2 IPA PA VTTBR_EL2 Hypervisor 虚拟机内存隔离 SMMU stage 1 IOVA PA 或 IPA Stream Table + CD + TTBR0 外设 DMA 隔离、scatter-gather SMMU stage 2 IPA PA STE/CD stage-2 设备直通、VM 隔离 GPU MMU GPU VA PA 或 IPA GPU 页表 / SMMU context bank GPU 进程隔离、缓冲映射、GPU fault ---------------------------------------------------------------------------------------------------------------------------------------
8. 8295 + QNX 虚拟化下的完整链路
Linux 进程/内核: VA ──[CPU stage1, TTBR0/1]──► IPA ──[QNX stage2, VTTBR_EL2]──► PA Linux 外设 DMA : IOVA ──[SMMU stage1]──► IPA ──[SMMU stage2 / Hypervisor]──► PA GPU: : GPU VA ──[KGSL GPU页表 / kgsl_smmu CB]──► IPA ──[stage2]──► PA
对应关系:
Linux 里 cat /proc/meminfo 看到的 MemTotal 是 IPA 总量;
Linux 驱动 dma_map_sg() 得到的 dma_addr_t 是 IOVA;
GPU 驱动拿到的 GPU VA 由 KGSL 分配,和 CPU VA 无关;
真正的 PA 只有 QNX Hypervisor 知道,Linux 无法直接访问。
9. 容易混淆的几个点
(1) MMU 不只是“地址翻译”:它还做权限检查、内存属性控制、缺页支持;IOMMU 还做 DMA 隔离。
(2) TLB 不是 MMU:TLB 只是页表项的缓存,MMU 才是翻译单元。
(3) IOMMU 的方向是 IOVA → PA,不是 PA → IOVA;IOVA 是驱动/设备使用的地址。
(4) GPU VA ≠ CPU VA:两者是独立地址空间,通过页表映射到同一 PA 才能共享数据。
(5) stage 2 不是独立 MMU:它是 CPU/SMMU 内部的第二级翻译,根页表由 Hypervisor 管理。
(6) mmu_notifier、mmu_gather 不是硬件 MMU:
a. mmu_notifier 是 Linux 在 CPU 页表变化时通知 GPU/KVM/RDMA 等 secondary MMU 失效映射的机制;
b. mmu_gather 是批量 TLB flush 的优化机制;
c. KVM MMU 是管理 guest stage-2 页表的软件模块。
10. 一句话总结
ARM Linux 上主要是 CPU MMU(VA→PA/IPA)、IOMMU/SMMU(IOVA→PA/IPA)、GPU MMU(GPU VA→PA/IPA) 三类;在 8295 的 QNX+Linux 虚拟化架构里,它们的第一级输出都是 IPA,再由 Hypervisor 的 stage 2 统一翻译成真正的 PA。
posted on 2026-10-24 21:40 Hello-World3 阅读(12) 评论(0) 收藏 举报
浙公网安备 33010602011771号