2. GPU内存管理基础:物理内存与虚拟内存概念、GPU地址空间(GPA)与CPU地址空间(CPA)的区别、内存映射(MMIO)基础

2.1 物理内存与虚拟内存:GPU视角下的核心概念

在SA8155这样的异构SoC中,GPU和CPU共享同一片物理DRAM(LPDDR5),但两者对内存的访问方式和地址理解截然不同。理解物理内存与虚拟内存的差异,是掌握GPU内存管理的起点。

关键认知: GPU看到的“物理地址”与CPU看到的“物理地址”在硬件层面是同一块DRAM颗粒,但经过IOMMU/SMMU映射后,GPU和CPU各自拥有独立的虚拟地址空间。

2.1.1 物理内存(Physical Memory)

  • 定义: SoC外部DRAM芯片的硬件存储单元,由内存控制器统一管理。
  • 特点: 地址连续、容量固定、资源稀缺。
  • GPU视角: GPU通过AXI总线直接访问物理地址(PA),但现代GPU几乎不直接操作PA,而是通过IOMMU进行地址转换。

2.1.2 虚拟内存(Virtual Memory)

  • 定义: 由MMU(CPU侧)或IOMMU(GPU侧)提供的地址转换层,使每个进程/上下文拥有独立的地址空间。
  • GPU优势:
    • 碎片消除:GPU驱动可以分配不连续的物理页框,通过页表映射为连续的虚拟地址。
    • 隔离保护:不同GPU上下文(Context)的虚拟地址空间互不干扰。
    • 按需分配:虚拟地址范围远大于物理内存,允许延迟分配物理页。
实战提示: SA8155的GPU驱动(kgsl)在分配显存时,优先分配虚拟地址(GVA),物理页框在GPU实际访问时通过缺页中断按需填充。这种机制称为“惰性分配”(Lazy Allocation),能显著降低显存浪费。

2.2 GPU地址空间(GPA)与CPU地址空间(CPA)的区别

这是嵌入式GPU开发中最容易混淆的概念。SA8155的Adreno GPU拥有独立的地址空间,与CPU的地址空间在硬件上通过IOMMU/SMMU隔离。

对比维度 CPU地址空间(CPA) GPU地址空间(GPA)
管理单元 CPU MMU(ARMv8.2) GPU IOMMU(SMMU v3)
地址宽度 48位(虚拟地址)/ 40位(物理地址) 48位(GPU虚拟地址GVA)
页表格式 4级页表(L0-L3),4KB/64KB页 2级页表(TTBR0/TTBR1),4KB/64KB/2MB页
访问发起者 CPU核心(Cortex-A76/A55) GPU着色器核心(Shaders)
缓存一致性 硬件ACE/CHI协议保证 需软件显式flush或使用IO-coherent
典型映射范围 0x0000_0000_0000 ~ 0xFFFF_FFFF_FFFF 0x0000_0000_0000 ~ 0x0000_FFFF_FFFF(用户区)
0xFFFF_0000_0000 ~ 0xFFFF_FFFF_FFFF(内核区)
常见陷阱: 在SA8155上,CPU物理地址(CPA)和GPU物理地址(GPA)在硬件上指向同一DRAM地址,但经过IOMMU映射后,GPU看到的“物理地址”实际上是经过SMMU转换后的中间物理地址(IPA)。驱动开发时,切勿将CPU的物理地址直接写入GPU页表,必须通过IOMMU API进行映射。

2.3 内存映射(MMIO)基础

MMIO(Memory-Mapped I/O)是GPU驱动与硬件交互的核心手段。SA8155的Adreno GPU将控制寄存器、状态寄存器、FIFO队列等暴露为一段连续的物理地址区域,CPU通过读写这些地址来操控GPU。

2.3.1 MMIO区域布局

在SA8155的硬件手册中,GPU的MMIO基地址通常位于系统总线的高地址区域(例如0x1C00_0000 ~ 0x1C0F_FFFF)。驱动通过ioremap将其映射到内核虚拟地址空间。

/* SA8155 Adreno GPU MMIO 基地址与偏移示例 */
#define GPU_MMIO_BASE         0x1C000000
#define GPU_MMIO_SIZE         0x00100000   /* 1MB */

/* 关键寄存器偏移 */
#define REG_GPU_STATUS        0x0004       /* GPU运行状态 */
#define REG_GPU_CTRL          0x0008       /* GPU软复位/时钟门控 */
#define REG_GPU_FAULT_ADDR    0x0010       /* 页错误地址 */
#define REG_GPU_FAULT_STATUS  0x0014       /* 页错误状态码 */
#define REG_GPU_IOMMU_BASE    0x0100       /* IOMMU页表基地址 */

2.3.2 MMIO访问流程

  1. 物理地址获取: 从设备树(DTS)或ACPI表中读取GPU MMIO的物理基地址。
  2. 内核映射: 使用devm_ioremap_resource()将物理地址映射到内核虚拟地址空间。
  3. 寄存器读写: 通过readl()/writel()访问映射后的虚拟地址。
  4. 内存屏障: 在关键操作前后插入mb()/wmb()保证顺序。
/* 内核驱动中MMIO映射与访问示例 */
static int gpu_probe(struct platform_device *pdev)
{
    struct resource *res;
    void __iomem *mmio_base;

    /* 1. 获取MMIO资源 */
    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!res)
        return -ENXIO;

    /* 2. 映射到内核虚拟地址空间 */
    mmio_base = devm_ioremap_resource(&pdev->dev, res);
    if (IS_ERR(mmio_base))
        return PTR_ERR(mmio_base);

    /* 3. 读取GPU状态寄存器 */
    u32 status = readl(mmio_base + REG_GPU_STATUS);
    dev_info(&pdev->dev, "GPU status: 0x%08x\n", status);

    /* 4. 写入控制寄存器启动GPU */
    writel(0x1, mmio_base + REG_GPU_CTRL);
    wmb();  /* 确保写入完成 */

    return 0;
}
性能要点: MMIO访问比普通内存访问慢2~3个数量级。在SA8155的GPU驱动中,高频路径(如提交命令队列)应尽量减少MMIO读写次数,优先使用内存中的Ring Buffer与Doorbell机制。

2.4 地址空间关系总览

下面的SVG图展示了SA8155中CPU地址空间、GPU地址空间以及IOMMU映射之间的完整关系。

SA8155 CPU与GPU地址空间映射关系 SA8155 CPU与GPU地址空间映射关系 CPU地址空间(CPA) CPU虚拟地址(VA) 48位,进程隔离 CPU物理地址(PA) 40位,DRAM实际位置 CPU MMU(ARM MMU-500) GPU地址空间(GPA) GPU虚拟地址(GVA) 48位,上下文隔离 中间物理地址(IPA) 经SMMU转换后地址 GPU SMMU(IOMMU v3) 共享物理DRAM(LPDDR5) CPU PA 与 GPU IPA 最终指向同一物理颗粒 直接访问 SMMU转换后访问 MMIO寄存器区域(0x1C00_0000 ~ 0x1C0F_FFFF) CPU通过ioremap映射后,使用readl/writel访问GPU控制寄存器 ioremap GPU内部总线 CPU地址空间 GPU地址空间 共享DRAM MMIO区域

2.5 本章小结

  • 物理 vs 虚拟: GPU驱动通过虚拟地址(GVA)管理显存,物理页框由IOMMU按需映射,实现碎片消除和隔离保护。
  • CPA vs GPA: CPU和GPU拥有独立的地址空间,通过SMMU/IOMMU进行地址转换。驱动开发时必须使用IOMMU API,不能直接传递CPU物理地址。
  • MMIO基础: GPU控制寄存器通过MMIO暴露,驱动使用ioremap + readl/writel访问,注意内存屏障和性能开销。