VMware SVGA 同步与资源¶
提交和唤醒¶
drivers/video/svga/ 实现 VMware FIFO/GB 协议;
drivers/video/drm/vmwgfx/ 负责 Linux vmwgfx ioctl 的验证、翻译与资源所有权。
公开 ioctl 编号和布局继续使用 include/uapi/drm/,不新增私有加速协议。
FIFO 命令、内联 PPN 数组与 fence 完整写入后,以内存屏障发布 NEXT_CMD。 支持 BUSY 寄存器的 host 在 BUSY 为真时承诺睡眠前检查新命令,因此只在 空闲到忙碌时写 BUSY 和 SYNC;不支持该寄存器的旧 FIFO 保留 SYNC 唤醒。 查询已经完成的 fence 不重新唤醒 host。BUSY 仅表示处理活动,不能作为 命令完成或释放 DMA 页的依据。
借用 BO 后备页时,GMR2 每个映射包含至多 256 个 PPN,每次调用发布至多 四个包,不逐包等待 host。最新 fence 按 FIFO 顺序覆盖所有已发布映射; 完成映射及最终 fence 之前,MOB ID 不可用于提交。FIFO 压力导致重试时 保留已发布的完整前缀。拆除仍须等待最终 unmap/destroy fence,之后才能 释放 owner 引用和物理页。
损伤与呈现¶
Surface-backed KMS PRESENT 只编码一个固定协议包和尾随 fence,经
svga3d_present_try 原子发布;不为简单呈现分配通用 render-batch 的
shader/query/state 元数据。当前通用 sidecar 为 53008 字节,需要 13 个
物理页;这些分配和清零不再出现在每次 KMS PRESENT 的路径中。
该接口在同一个 SVGA 锁临界区检查设备、完整 surface handle、源/目标矩形 范围和 FIFO 容量。发布成功才更新 surface 的 last-use fence;FIFO 忙时 不发布部分命令,也不假定绘制完成。呈现 job 继续持有 framebuffer 和 surface 引用,直到真实 fence 完成或有明确 quiescence 证据,不能因关闭文件、释放 master 或切换 VT 就提前释放 DMA 后备页。
正常 DIRTYFB 仍立即尝试提交,只有背压才保留脏区域并合并重试,不按定时器 延迟成功提交。Linux UAPI 的 256 个 clip 上限不变。Xorg modesetting 在超出 上限时可能退回逐个 clip 提交,因此简单呈现的分配开销会被放大;离屏绘制 不经过这条扫描输出路径,不能用离屏速度代替桌面呈现速度。
软件扫描输出后备路径按行以精确的 32 位像素上传到四字节对齐的显存,
使用 REP MOVSL,避免把针对普通 RAM 的 REP MOVSB 用于 uncached
设备窗口。非原生格式仍先执行原有颜色转换;非四字节像素保留逐字节路径。
上传不读取显存,不访问行尾填充或单次上传矩形外的像素,不使用用户 SIMD 状态。
软件 DIRTYFB 先校验全部 clip;多块损伤的面积之和小于包围矩形时分别上传,
避免光标和远处窗口的一点变化触发整片屏幕复制。重叠面积使逐块复制更大时
仍上传包围矩形,复制量不超过旧路径。设备 surface 的异步呈现仍沿用原有合并。
损伤保留、FIFO 背压、fence 和 VT 所有权规则不变。
该路径降低 CPU 上传成本,不代表 QEMU 提供了 VMware 3D 加速能力。
像素缓存属性¶
启动 BSP 在稀疏直映射完成、用户页表与 AP 启动之前,为支持 PAT 且启用 MTRR 的 CPU 保留 PAT 槽四作为 WC;其他固件项保持原样。只有可预取 PCI BAR1 与实际 SVGA 像素窗口吻合、完整 UC 永久保留且没有租约/其他缓存 别名、没有普通 RAM 或 FIFO 交叠时,才一次性转换为 WC/NX。失败保留 UC。 首次尝试或创建用户页表后关闭重设入口,不在运行中的映射下更改缓存类型。
直映射和保留的低地址别名一起更新,缓存与 TLB 在转换前后清理;AP 在 上线前验证并安装相同 PAT 布局,无法满足的 AP 保持离线。fbdev/DEVICE 映射沿用同一物理页的缓存选择器,模式切换和 SVGA 3D 初始化保留该策略。 像素写入在提交损伤之前执行内存屏障,即使 FIFO 满而延后发布也先排空 WC 写入。FIFO 继续采用其原有的独立验证策略,控制寄存器不使用 WC。
nopat 启动参数保留原来的 UC 像素路径。这里的内部映射 API 不向用户
提供任意缓存属性修改权限;物理范围的缓存别名约束参考
Linux PAT 文档。
EXECBUF 背压¶
在途工作受 32 个任务和 8 MiB 的全局预算约束。预算暂满时,先在释放 exec_lock 后执行一次有界回收,再原子重试预留;仍未腾出空间则返回 EBUSY。 不会扩大限额、循环持锁等待 host,也不会跳过尚未完成的 fence 来释放内存。 单次申请本身超过限额或真实 heap 分配失败仍返回 ENOMEM,并回滚预留计数。
Mesa 的 vmwgfx winsys 对 EXECBUF EBUSY 会短暂休眠后重试,其他错误可能使 Xorg/glamor 终止。把暂时的队列拥塞当作 ENOMEM 会在 GPU 落后于提交时导致 桌面退出,即使实际预算占用远低于物理内存容量。该行为参考 Mesa 上游的 EBUSY 重试修复; 不修改 ioctl 编号或结构,也不把真实分配失败伪装成成功。
分配与锁¶
内部 svga_ops.alloc 返回独占、页对齐且已经清零的物理页;失败返回零。
生产实现使用 mm_alloc_pages。GB 后备页和 shader staging 不重复清零。
页表中尚未写入的项和 shader 尾部填充仍由分配器的零页保证覆盖。
物理页分配器在 mm_lock 内认领完整页段、初始化引用并更新空闲计数,随后 解锁再清零,返回前不会向调用方发布物理地址。其他 CPU 不能分配已经认领 但仍在清零的页面。调用方已有的锁和 IRQ 状态保持原样;这不意味着所有 SVGA 资源分配都可抢占,也不能据此声称所有整机停顿已经消除。
SYNCCPU 兼容语义¶
Linux v6.12 的 drm_vmw_synccpu_allow_cs grab 等待先前 GPU 使用完成,
但不建立阻止后续命令提交的 CPU writer reservation。对应 release 对有效
handle 成功返回,不递减其他非 ALLOW_CS grab 的计数;无效 handle 和非法
flag 仍返回 EINVAL。非 ALLOW_CS grab 保留原来的 writer 排斥与关闭清理。
行为参考 Linux v6.12 vmwgfx BO 接口; 此处按上游接口语义实现,不复制 Linux vmwgfx 实现代码。 协议头的原有许可证与归属说明保留;本次实现没有导入其他内核的 DRM 源码。
验证边界¶
宿主 fixture 需要覆盖旧 FIFO 唤醒、BUSY 状态、已完成 fence、未完成映射、 背压和拆除时的 owner 生命周期,并使用 ASan/UBSan 检查生产实现。 真实 VMware 验证还需检查 Xorg 日志确实启用 SVGA3D/glamor、正确像素、 重复会话、资源反复创建/销毁和并发负载。QEMU 的 VMware 型号设备不能替代 真实 VMware 3D 验证。未复现某次 panic 不等于已经证明其原因或修复。
资源预算¶
GB 对象使用本驱动的有界页预算,初值来自设备报告的内存寄存器:支持
CAP2.GB_MEMSIZE_2 时使用 GBOBJECT_MEM_SIZE_KB,否则使用
SUGGESTED_GBOBJECT_MEM_SIZE_KB。这与 Linux vmwgfx 对相同硬件接口的
选择一致。这是来宾分配策略;Linux vmwgfx 将对应容量视为可扩大的软上限,
不能据此声称硬件必然拒绝超出该值的对象。旧 GMR 的后备预算不截断 GB 内存;单个 MOB 仍受
MOB_MAX_SIZE、32 位线协议长度和 PPN32 两级页表容量约束。
字节数向上取整为页数时使用 64 位中间值,避免 UINT32_MAX 回绕。
GMR2 的注册页数独立受 GMRS_MAX_PAGES 限制。自有与借用的 GMR 共享此
注册预算;已经发布但尚在映射或退休的对象,在最终解除之前仍计费。
GB 预算包含自有物理页、借用 MOB 的完整后备页、页表和尚未提交的 shader
预留。批处理 shader 与普通 MOB 分配使用相同的预算检查。借用后备页
直到最终拆除 fence 完成才解除计费,但这些页始终由调用方 owner 释放。
自有物理页和页表还受分配器实际可用内存约束;分配失败
仍返回 ENOMEM,不会通过关闭加速或吞掉错误隐藏失败。
表面 ID 存储支持协议规定的 32768 项,并接受设备更低的
MAX_SURFACE_IDS 上限;零号保留。对象表按协商后的容量分配,并进一步
受单个 MOB 可容纳的表项数限制;context、surface、shader 和外部 MOB 的
编号范围保持互不重叠。surface 快照使用在发布和最终释放时更新的计数,
仍包含正在创建或退休的句柄,避免每次提交都持锁扫描全部 32768 项。
资源句柄、代际验证、fence 退休与
模块 owner 生命周期规则保持不变。非 GB 设备继续使用既有的后备内存策略。
对应上游接口见 Linux v6.12 vmwgfx 初始化 和 SVGA 寄存器定义。 预算策略对照见 Linux v6.12 vmwgfx 内存管理器。