diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/main.c | 33 |
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; } |
