3、显存分配机制:SA8155 上显存(Video Memory)的分配策略

在 SA8155 显示子系统中,显存(Video Memory)的分配策略直接决定了 GPU 渲染效率、显示帧率稳定性以及多窗口合成的成功率。SA8155 采用 预分配(Pre-allocation) 与 动态分配(Dynamic Allocation) 相结合的混合策略,以平衡启动速度与内存利用率。

调试要点: 显存分配异常通常表现为“黑屏”、“花屏”或“合成失败”。排查时需首先确认当前分配模式是预分配还是动态分配,再检查对应的内存区域是否被正确映射。

3.1 预分配策略(Boot-time Reservation)

预分配是指在系统启动阶段(UEFI / SBL / ABL),通过固件配置为显示子系统预留固定大小的连续物理内存区域。这部分内存通常用于帧缓冲(Framebuffer)和关键合成管线。

预分配区域 典型大小 用途 映射属性
Primary FB 8 ~ 16 MB 主屏帧缓冲(Boot splash / 桌面) WB (Write-back), 连续
Secure Display 4 ~ 8 MB DRM 保护内容(如 HDCP) 不可缓存, 连续
DPU VBIF 2 ~ 4 MB 显示处理单元内部 VBIF 预留 IO-coherent
MDP 管线 16 ~ 32 MB 多层合成(Overlay / Layer Mixer) WB, 连续
预分配优势: 零延迟分配,避免运行时内存碎片;适合对延迟敏感的显示路径(如启动动画、安全视频播放)。
预分配劣势: 内存浪费,若实际使用场景不需要大尺寸帧缓冲,预留区域将无法被其他子系统回收。
SA8155 预分配显存布局 SA8155 预分配显存布局(Boot-time) Primary FB 8~16 MB Boot Splash Secure 4~8 MB HDCP DPU VBIF 2~4 MB IO-coherent MDP 管线 16~32 MB Overlay / Layer Mixer 物理地址空间(低地址 → 高地址)

3.2 动态分配策略(Runtime Allocation)

动态分配发生在内核驱动加载后,由 ION 内存管理器 或 DMA-BUF 框架 按需分配。SA8155 的 GPU(Adreno 640)通过 kgsl 驱动向 ION 申请显存,用于纹理、渲染目标、顶点缓冲等。

3.2.1 动态分配流程

  1. 应用请求: 用户态(SurfaceFlinger / 应用)通过 gralloc 分配图形缓冲区。
  2. ION 分配: gralloc 调用 ION 接口,从系统内存或预留 CMA 区域分配物理连续或非连续内存。
  3. DMA-BUF 导出: 分配的内存以 DMA-BUF 形式导出,可跨驱动(GPU / DPU / VPU)共享。
  4. GPU 映射: kgsl 驱动将 DMA-BUF 映射到 GPU 的 IOMMU 页表,建立 GPU 虚拟地址到物理地址的映射。
  5. DPU 获取: 显示处理单元(DPU)通过 SMMU 映射同一 DMA-BUF,用于合成输出。
常见异常: 动态分配失败通常伴随 ION allocation failed 或 Out of memory 内核日志。此时应检查 CMA 区域是否耗尽、IOMMU 页表是否溢出。
SA8155 动态显存分配流程 SA8155 动态显存分配流程(ION + DMA-BUF) 应用 / SurfaceFlinger gralloc (HAL) ION 内存管理器 GPU (kgsl) 映射 DPU (SMMU) 映射 关键:DMA-BUF 作为共享句柄,GPU 和 DPU 各自通过 IOMMU/SMMU 建立独立映射

3.3 预分配 vs 动态分配对比

对比维度 预分配 动态分配
分配时机 Boot-time(UEFI / SBL) Runtime(内核启动后)
内存连续性 物理连续 物理连续或非连续(通过 IOMMU 虚拟化)
分配延迟 零延迟(已预留) 微秒级(ION 分配 + 页表更新)
内存利用率 低(可能浪费) 高(按需分配)
适用场景 Boot splash、安全视频、关键合成管线 普通 UI 渲染、游戏纹理、相机预览
调试手段 查看 dmesg | grep msm_display 查看 /d/ion/heaps 或 kgsl_proc

3.4 显存分配异常排查清单

  • 检查预分配区域是否被覆盖: 使用 cat /proc/iomem | grep msm_display 确认预留区域边界。
  • 检查 ION 堆使用情况: cat /d/ion/heaps 查看各堆(system / cma / carveout)的已分配和剩余大小。
  • 检查 GPU 内存映射: cat /d/kgsl/proc/*/mem 查看每个进程的 GPU 内存分配。
  • 检查 SMMU 页表错误: dmesg | grep arm-smmu 查找 Unhandled context fault 或 TLB miss。
  • 检查 CMA 区域是否耗尽: cat /d/cma/usage 查看连续内存使用率。
实战案例: 某项目中,SurfaceFlinger 分配 4K 显示缓冲区时返回 NO_MEMORY。排查发现 CMA 区域被相机驱动耗尽,导致无法分配连续物理内存。解决方案:增大 CMA 预留大小,或将相机改为使用非连续内存 + IOMMU 映射。
显存分配异常排查流程 显存分配异常排查流程 显存分配失败 检查 ION 堆 检查 CMA 区域 检查 SMMU 错误 定位根因:内存耗尽 / 页表错误 / 权限不足