summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-27 16:36:48 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-27 16:36:48 -0400
commit28c8c8e9635a072abe52b08b30b6d9607cfb0768 (patch)
tree10633942f1498a0fcf378632e6d68536fd82b1b8
parentf6e8a70fd4288d6fa11aa67a4d2a0e9a50f534dd (diff)
downloadopen-iov-28c8c8e9635a072abe52b08b30b6d9607cfb0768.tar.gz
open-iov-28c8c8e9635a072abe52b08b30b6d9607cfb0768.zip
vgsp: notify keepalive on registered notifier slots + 8GB demo guest
r864 ground truth while wedged: both the RC-watchdog channel (0x31415900) and the X/GL channel (0x1000013) sit with their class2d notification ARMED (u16 status 0xFFFF at notifier_pa + 0x3E = slot-3 struct status) and nothing ever clears them (X notified=0 after 459 submissions), so the guest krcWatchdog fires 'GPU is probably locked' every ~8.2 s and the whole X/GL stack wedges (glxgears poll() never returns; late XOOM death). Under the mirrored flow the watchdog ring reads go unreadable (rc=-2), so the decode-time ack and the notify2d_va path both miss. svc_notify2d_keepalive(): every pass, every GR channel with a registered notifier PA, read slots 0..3; for each slot armed exactly 0xFFFF write the zeroed 16-byte NvNotification and post the channel event - the same effects as svc_notify_complete without any ring read. Also bump the demo harness guest RAM to 8GB (launch_qemu_rootport.sh) to survive the observed emulation-path allocation growth during accelerated runs.
-rw-r--r--kernel/gsp_sema_service.c74
-rwxr-xr-xtools/guest-diag/launch_qemu_rootport.sh2
2 files changed, 75 insertions, 1 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 15cc93f..af4534b 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -10897,6 +10897,72 @@ static void svc_notify2d_write(struct nv_vgpu_device *vgpu,
}
}
+/*
+ * SESSION 148 perf (r862/r864): the RC watchdog's class2d notify cycle
+ * keep-alive that needs no push decode and no captured VA. Under the
+ * mirrored frame flow the watchdog ring reads go unreadable (rc=-2) for
+ * stretches, SET_NOTIFY never re-captures, notify2d_va stays 0, and the
+ * put != get gate of the r832 path misses - the guest's krcWatchdog then
+ * declares "GPU is probably locked" (Notify Timeout Seconds: 7) every
+ * ~8.2 s and the whole X/GL stack wedges (glxgears poll() never returns,
+ * late XOOM death as buffers pile up).
+ *
+ * Ground truth (r864, live RAM scan while wedged): BOTH the watchdog
+ * channel (0x31415900) and the X/GL channel (0x1000013) sit with their
+ * class2d notification ARMED - u16 status 0xFFFF at notifier_pa + 0x3E,
+ * i.e. the 16-byte NvNotification struct at slot 3 (notifier_pa + 0x30,
+ * status at +14 within the struct) - and NOTHING ever clears them
+ * (X channel notified=0 after 459 submissions). Slots 0..3 cover the
+ * error notifier (0), the work-submit token (1) and the class2d notify
+ * slot (3); the armed test is EXACTLY 0xFFFF so the fault-notifier
+ * payload slots (nonzero engine/exception codes) are never touched.
+ *
+ * Every pass, for every GR channel with a registered notifier (driver
+ * truth, always known): read slots 0..3; for each slot whose status is
+ * armed, write the zeroed 16-byte NvNotification (the GPU's completion
+ * write) and post the channel event - the same two effects
+ * svc_notify_complete() produces, but reached without any ring read.
+ * Idempotent: only an armed slot is written.
+ */
+#define SVC_NOTIFY_SCAN_SLOTS 4
+
+static void svc_notify2d_keepalive(struct nv_vgpu_device *vgpu,
+ struct svc_channel *ch)
+{
+ u8 slots[16 * SVC_NOTIFY_SCAN_SLOTS];
+ u8 zero[16] = { 0 };
+ int slot;
+
+ if (!ch->notifier_pa)
+ return;
+ if (svc_read_ap(vgpu, ch->notifier_pa, ch->notifier_as,
+ slots, sizeof(slots)))
+ return;
+ for (slot = 0; slot < SVC_NOTIFY_SCAN_SLOTS; slot++) {
+ u16 st;
+
+ memcpy(&st, slots + slot * 16 + 14, 2);
+ if (st != 0xffff)
+ continue; /* not armed - nothing to ack */
+ if (svc_write_ap(vgpu, ch->notifier_pa + slot * 16,
+ ch->notifier_as, zero, sizeof(zero)))
+ continue;
+ svc_notify2d_done++;
+ /*
+ * The GPU consumed the submission: post the channel event so
+ * the client's CPU-side RM signals the OS event the
+ * submitting thread waits on (a real GPU would raise an
+ * interrupt here). Mirrors svc_notify_complete().
+ */
+ gsp_rm_post_channel_event(vgpu, ch->h_object);
+ if (gsp_sema_dbg && svc_notify2d_log < 16) {
+ svc_notify2d_log++;
+ pr_info("sema-notify2d: h=0x%x notifier_pa=0x%llx slot=%d armed -> zeroed (registration-based ack)\n",
+ ch->h_object, ch->notifier_pa, slot);
+ }
+ }
+}
+
static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
u32 len, u64 page_pa, bool allow_ops,
struct svc_channel *ch, u32 entry_idx,
@@ -27154,6 +27220,14 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
*/
if (!ch->engine_type && ch->notify2d_va && put != get)
svc_notify2d_write(vgpu, ch);
+ /*
+ * SESSION 148 (r864): registration-based keep-alive that
+ * needs no decode - ack the driver-registered notifier when
+ * it is armed. Catches the stretches where the watchdog ring
+ * reads go unreadable and notify2d_va was never captured.
+ */
+ if (!ch->engine_type)
+ svc_notify2d_keepalive(vgpu, ch);
/*
* ISSUE-0002 diag: put snapshots for CE channels, bounded per
diff --git a/tools/guest-diag/launch_qemu_rootport.sh b/tools/guest-diag/launch_qemu_rootport.sh
index 444bdfc..d38321b 100755
--- a/tools/guest-diag/launch_qemu_rootport.sh
+++ b/tools/guest-diag/launch_qemu_rootport.sh
@@ -1,4 +1,4 @@
#!/bin/bash
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2026 Open-IOV contributors
-exec /bin/qemu-system-x86_64 -D /home/rmcore/.local/libvf.io/logs/qemu/e726ba0b-204f-4ec9-91da-983ed7f41d06-session.txt -no-hpet -mem-prealloc -qmp unix:/tmp/qemu-qmp.sock,server,nowait -chardev socket,path=/tmp/qemu-guest-agent.sock,server=on,wait=off,id=qga0 -device virtio-serial-pci -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 -serial file:/tmp/vgpu-guest-serial.log -gdb tcp::1234 -display none -device ivshmem-plain,id=shmem0,memdev=ivshmem_kvmfr -object memory-backend-file,id=ivshmem_kvmfr,mem-path=/dev/shm/kvmfr-e726ba0b-204f-4ec9-91da-983ed7f41d06,size=128M,share=yes -device ivshmem-plain,id=shmem1,memdev=ivshmem_kvmsr -object memory-backend-file,id=ivshmem_kvmsr,mem-path=/dev/shm/kvmsr-e726ba0b-204f-4ec9-91da-983ed7f41d06,size=2M,share=yes -object memory-backend-file,id=pc.ram,size=4096M,mem-path=/dev/shm/vgpu-guest-ram,share=yes,prealloc=on -uuid e726ba0b-204f-4ec9-91da-983ed7f41d06 -machine pc-q35-4.2,accel=kvm,usb=off,vmport=off,dump-guest-core=off,memory-backend=pc.ram -cpu host,ss=on,vmx=on,pcid=on,hypervisor=on,arat=on,tsc-adjust=on,umip=on,md-clear=on,stibp=on,arch-capabilities=on,ssbd=on,xsaveopt=on,pdpe1gb=on,ibpb=on,amd-stibp=on,amd-ssbd=on,skip-l1dfl-vmentry=on,pschange-mc-no=on,hv-vapic,hv_time,hv-spinlocks=0x1fff,hv-vendor-id=null,kvm=on,topoext=on -rtc clock=host,base=localtime -m 4096 -smp cores=4,threads=1,sockets=1 -hda /home/rmcore/.local/libvf.io/kernel/linux.qcow2 --enable-kvm -device pcie-root-port,id=rp0,chassis=1,slot=30,bus=pcie.0 -device vfio-pci,id=hostdev0,bus=rp0,sysfsdev=/sys/bus/mdev/devices/<MDEV-UUID>,display=off -device rtl8139,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -device vhost-vsock-pci,guest-cid=50718 -qmp unix:/tmp/sockets/e726ba0b-204f-4ec9-91da-983ed7f41d06/main.sock,server,nowait -qmp unix:/tmp/sockets/e726ba0b-204f-4ec9-91da-983ed7f41d06/master.sock,server,nowait
+exec /bin/qemu-system-x86_64 -D /home/rmcore/.local/libvf.io/logs/qemu/e726ba0b-204f-4ec9-91da-983ed7f41d06-session.txt -no-hpet -mem-prealloc -qmp unix:/tmp/qemu-qmp.sock,server,nowait -chardev socket,path=/tmp/qemu-guest-agent.sock,server=on,wait=off,id=qga0 -device virtio-serial-pci -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 -serial file:/tmp/vgpu-guest-serial.log -gdb tcp::1234 -display none -device ivshmem-plain,id=shmem0,memdev=ivshmem_kvmfr -object memory-backend-file,id=ivshmem_kvmfr,mem-path=/dev/shm/kvmfr-e726ba0b-204f-4ec9-91da-983ed7f41d06,size=128M,share=yes -device ivshmem-plain,id=shmem1,memdev=ivshmem_kvmsr -object memory-backend-file,id=ivshmem_kvmsr,mem-path=/dev/shm/kvmsr-e726ba0b-204f-4ec9-91da-983ed7f41d06,size=2M,share=yes -object memory-backend-file,id=pc.ram,size=8192M,mem-path=/dev/shm/vgpu-guest-ram,share=yes,prealloc=on -uuid e726ba0b-204f-4ec9-91da-983ed7f41d06 -machine pc-q35-4.2,accel=kvm,usb=off,vmport=off,dump-guest-core=off,memory-backend=pc.ram -cpu host,ss=on,vmx=on,pcid=on,hypervisor=on,arat=on,tsc-adjust=on,umip=on,md-clear=on,stibp=on,arch-capabilities=on,ssbd=on,xsaveopt=on,pdpe1gb=on,ibpb=on,amd-stibp=on,amd-ssbd=on,skip-l1dfl-vmentry=on,pschange-mc-no=on,hv-vapic,hv_time,hv-spinlocks=0x1fff,hv-vendor-id=null,kvm=on,topoext=on -rtc clock=host,base=localtime -m 8192 -smp cores=4,threads=1,sockets=1 -hda /home/rmcore/.local/libvf.io/kernel/linux.qcow2 --enable-kvm -device pcie-root-port,id=rp0,chassis=1,slot=30,bus=pcie.0 -device vfio-pci,id=hostdev0,bus=rp0,sysfsdev=/sys/bus/mdev/devices/<MDEV-UUID>,display=off -device rtl8139,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -device vhost-vsock-pci,guest-cid=50718 -qmp unix:/tmp/sockets/e726ba0b-204f-4ec9-91da-983ed7f41d06/main.sock,server,nowait -qmp unix:/tmp/sockets/e726ba0b-204f-4ec9-91da-983ed7f41d06/master.sock,server,nowait