summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_display_engine.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-08 07:05:03 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-08 07:05:03 -0500
commit4942e2afb6a9470e5c8f3c60515656551bd1e2f2 (patch)
treebc253beafeb7920c7fd28945fc1047478f09ae32 /kernel/gsp_display_engine.c
parentcfa2bf216065c87a185e83a8bf38a6c5dd5788c8 (diff)
downloadopen-iov-4942e2afb6a9470e5c8f3c60515656551bd1e2f2.tar.gz
open-iov-4942e2afb6a9470e5c8f3c60515656551bd1e2f2.zip
vgsp-disp: retry the instance block through guest RAM when the shadow copy is empty
The RM's vidmem writes may use the coherent CPU mapping rather than the BAR1 aperture, in which case the display instance block lands at the announced address in guest RAM. Log the source used (src=fb|ram) and fall back to vfio_dma_rw before reporting the hash table empty.
Diffstat (limited to 'kernel/gsp_display_engine.c')
-rw-r--r--kernel/gsp_display_engine.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/kernel/gsp_display_engine.c b/kernel/gsp_display_engine.c
index 5109245..426d6a1 100644
--- a/kernel/gsp_display_engine.c
+++ b/kernel/gsp_display_engine.c
@@ -439,6 +439,7 @@ static int gsp_disp_ctxdma_pa(struct nv_vgpu_device *vgpu, u32 handle,
if (have_im) {
u64 e;
+ const char *im_src = "fb";
if (!disp.ibuf)
return -ENOMEM;
@@ -446,6 +447,52 @@ static int gsp_disp_ctxdma_pa(struct nv_vgpu_device *vgpu, u32 handle,
GSP_DISP_INST_OBJ_END))
return -ENOENT;
+ /*
+ * The RM may write vidmem through a coherent CPU mapping
+ * instead of the BAR1 aperture, in which case the block lands
+ * at the same address in guest RAM rather than in the FB
+ * shadow. If the shadow copy is empty, retry through
+ * vfio_dma_rw before giving up.
+ */
+ if (im_space == 2) {
+ u64 nz = 0;
+
+ for (e = 0; e < GSP_DISP_INST_HASH_END; e += 8) {
+ u32 a = *(u32 *)(disp.ibuf + e);
+ u32 b = *(u32 *)(disp.ibuf + e + 4);
+
+ if (a || b)
+ nz++;
+ }
+ if (!nz) {
+ u8 *tmp = kmalloc(GSP_DISP_INST_OBJ_END,
+ GFP_KERNEL);
+
+ if (tmp) {
+ if (vfio_dma_rw(&vgpu->vfio_dev, im_pa,
+ tmp,
+ GSP_DISP_INST_OBJ_END,
+ false) == 0) {
+ for (e = 0;
+ e < GSP_DISP_INST_HASH_END;
+ e += 8) {
+ u32 a = *(u32 *)(tmp + e);
+ u32 b = *(u32 *)(tmp + e + 4);
+
+ if (a || b)
+ nz++;
+ }
+ if (nz) {
+ memcpy(disp.ibuf, tmp,
+ GSP_DISP_INST_OBJ_END);
+ im_src = "ram";
+ }
+ }
+ kfree(tmp);
+ }
+ }
+ }
+
if (gsp_disp_dbg && disp.im_logs < 8) {
u32 nz = 0, shown = 0;
@@ -463,8 +510,8 @@ static int gsp_disp_ctxdma_pa(struct nv_vgpu_device *vgpu, u32 handle,
}
}
disp.im_logs++;
- pr_info("inst mem pa=0x%llx space=%u handle=0x%x hash_nz=%u\n",
- im_pa, im_space, handle, nz);
+ pr_info("inst mem pa=0x%llx space=%u src=%s handle=0x%x hash_nz=%u\n",
+ im_pa, im_space, im_src, handle, nz);
/*
* The announced block may not be where the RM's writes