summaryrefslogtreecommitdiffstats
path: root/kernel/main.c
diff options
context:
space:
mode:
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;
}