diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-23 12:02:31 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-23 12:02:31 -0400 |
| commit | ae18e08d02500579f084616874d8f2ae57f8281b (patch) | |
| tree | 1ad71b457cc36290ac3d993280063424203509af /kernel | |
| parent | 5c47eacbe01f9353f2c21d96e1a3eb15a63fd991 (diff) | |
| download | open-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')
| -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; } |
