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, 连续 |
预分配优势: 零延迟分配,避免运行时内存碎片;适合对延迟敏感的显示路径(如启动动画、安全视频播放)。
预分配劣势: 内存浪费,若实际使用场景不需要大尺寸帧缓冲,预留区域将无法被其他子系统回收。
预分配劣势: 内存浪费,若实际使用场景不需要大尺寸帧缓冲,预留区域将无法被其他子系统回收。
3.2 动态分配策略(Runtime Allocation)
动态分配发生在内核驱动加载后,由 ION 内存管理器 或 DMA-BUF 框架 按需分配。SA8155 的 GPU(Adreno 640)通过 kgsl 驱动向 ION 申请显存,用于纹理、渲染目标、顶点缓冲等。
3.2.1 动态分配流程
- 应用请求: 用户态(SurfaceFlinger / 应用)通过
gralloc分配图形缓冲区。 - ION 分配:
gralloc调用 ION 接口,从系统内存或预留 CMA 区域分配物理连续或非连续内存。 - DMA-BUF 导出: 分配的内存以 DMA-BUF 形式导出,可跨驱动(GPU / DPU / VPU)共享。
- GPU 映射: kgsl 驱动将 DMA-BUF 映射到 GPU 的 IOMMU 页表,建立 GPU 虚拟地址到物理地址的映射。
- DPU 获取: 显示处理单元(DPU)通过 SMMU 映射同一 DMA-BUF,用于合成输出。
常见异常: 动态分配失败通常伴随
ION allocation failed 或 Out of memory 内核日志。此时应检查 CMA 区域是否耗尽、IOMMU 页表是否溢出。
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 映射。