summaryrefslogtreecommitdiffstats
path: root/kernel/main.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-23 12:02:31 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-23 12:02:31 -0400
commitae18e08d02500579f084616874d8f2ae57f8281b (patch)
tree1ad71b457cc36290ac3d993280063424203509af /kernel/main.c
parent5c47eacbe01f9353f2c21d96e1a3eb15a63fd991 (diff)
downloadopen-iov-ae18e08d02500579f084616874d8f2ae57f8281b.tar.gz
open-iov-ae18e08d02500579f084616874d8f2ae57f8281b.zip
kernel: apply BAR0/BAR1 region writes to the emulated shadows
The mdev's region write handler returned success without touching the BAR0 shadow or the trap table, so register writes that arrive through the VFIO region path (QEMU-trapped accesses) never took effect. A fresh guest then polled a register that never changed and spun forever in cuInit (QEMU log: vfio_region_write(mdev:region0+0x88704) failed: Resource temporarily unavailable). Route those writes to the BAR0 shadow/trap handler and mirror BAR1 writes into the emulated vidmem backing.
Diffstat (limited to 'kernel/main.c')
-rw-r--r--kernel/main.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/kernel/main.c b/kernel/main.c
index 0a1ebc2..45c34ab 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -755,6 +755,39 @@ static ssize_t nv_vgpu_vfio_dev_write(struct vfio_device *vdev, const char __use
return ret;
}
+ /* BAR0 region (register space). Most guest accesses hit the mmap'd
+ * shadow directly, but region writes also arrive here (e.g. when QEMU
+ * handles a trapped access). They must be applied to the shadow and to
+ * the trap table - dropping them makes the guest driver poll a
+ * register that never changes and spin forever. */
+ if (pos >= 0 && (u64)pos < vgpu->bars[0].size && count <= 8) {
+ u8 tmp[8];
+ ssize_t ret;
+
+ if (!vgpu->bar_emul_ctx)
+ return -ENODEV;
+ if (copy_from_user(tmp, buf, count))
+ return -EFAULT;
+
+ ret = nv_vgpu_bar_emul_write(vgpu, 0, (u64)pos, tmp, count);
+ if (ret)
+ return ret;
+ *ppos += count;
+ return count;
+ }
+
+ /* BAR1 region (VRAM): same for the emulated vidmem backing. */
+ if (pos >= (1ULL << 40) &&
+ (u64)pos < (1ULL << 40) + vgpu->bars[1].size &&
+ vgpu->bars[1].vaddr && count <= 8) {
+ u64 bar1_off = (u64)pos - (1ULL << 40);
+
+ if (copy_from_user(vgpu->bars[1].vaddr + bar1_off, buf, count))
+ return -EFAULT;
+ *ppos += count;
+ return count;
+ }
+
return 0;
}