summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-26 02:46:41 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-26 02:46:41 -0400
commitae2bd4def95997ff7198b1bad21a73a267eea604 (patch)
treebece0cea9a0d1d3ab3f2149f5441e377ddd71bc8
parent7ac4d61c5a06fda4c9d4a398fb49f400b2b76f15 (diff)
downloadopen-iov-ae2bd4def95997ff7198b1bad21a73a267eea604.tar.gz
open-iov-ae2bd4def95997ff7198b1bad21a73a267eea604.zip
kernel: add a channel-table dump param; tools: fix memprobe --max parsing
-rw-r--r--kernel/gsp_sema_service.c69
-rw-r--r--kernel/gsp_sema_service.h1
-rw-r--r--kernel/main.c17
-rw-r--r--tools/guest-diag/memprobe.py2
4 files changed, 88 insertions, 1 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index ffc8ae2..1f1222e 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -3122,6 +3122,74 @@ int gsp_sema_service_probe(u64 gpu_va, u32 count)
}
/*
+ * Diagnostic dump of the service's channel table: GPFIFO/USERD state, the
+ * pending-entry expectation and the two NvNotification slots the client polls
+ * (status + info32). Runs in the service thread (guest-DMA reads need a
+ * kthread context); the sysfs writer waits for completion.
+ */
+static struct completion chan_dump_done;
+static bool chan_dump_pending;
+
+static void svc_handle_chan_dump(struct nv_vgpu_device *vgpu)
+{
+ struct svc_channel local[SVC_MAX_CHANNELS];
+ unsigned long flags;
+ int i, n = 0;
+
+ if (!chan_dump_pending)
+ return;
+
+ spin_lock_irqsave(&svc.chan_lock, flags);
+ for (i = 0; i < SVC_MAX_CHANNELS; i++)
+ if (svc.chan[i].valid)
+ local[n++] = svc.chan[i];
+ spin_unlock_irqrestore(&svc.chan_lock, flags);
+
+ pr_info("sema-chan-dump: %d channel(s)\n", n);
+ for (i = 0; i < n; i++) {
+ struct svc_channel *ch = &local[i];
+ u32 st0 = 0, st1 = 0, info0 = 0, info1 = 0;
+
+ if (ch->notifier_pa) {
+ svc_read_ap(vgpu, ch->notifier_pa + 14,
+ ch->notifier_as, &st0, 2);
+ svc_read_ap(vgpu, ch->notifier_pa + 8,
+ ch->notifier_as, &info0, 4);
+ svc_read_ap(vgpu, ch->notifier_pa + 16 + 14,
+ ch->notifier_as, &st1, 2);
+ svc_read_ap(vgpu, ch->notifier_pa + 16 + 8,
+ ch->notifier_as, &info1, 4);
+ }
+ pr_info("sema-chan-dump: h=0x%x eng=%u gpfifo=0x%llx ent=%u userd=0x%llx as=%u ok=%d get=%u sub=%llu exp=%u notif=0x%llx as=%u slot0{info=0x%x st=0x%x} slot1{info=0x%x st=0x%x} notified=%llu\n",
+ ch->h_object, ch->engine_type, ch->gpfifo_va,
+ ch->gpfifo_entries, ch->userd_pa, ch->userd_as,
+ ch->userd_ok, ch->last_get, ch->submissions,
+ ch->expected_sem_payload, ch->notifier_pa,
+ ch->notifier_as, info0, st0, info1, st1,
+ ch->notified);
+ }
+
+ chan_dump_pending = false;
+ complete(&chan_dump_done);
+}
+
+int gsp_sema_service_dump_channels(void)
+{
+ if (!svc.task)
+ return -ENODEV;
+
+ init_completion(&chan_dump_done);
+ chan_dump_pending = true;
+
+ if (!wait_for_completion_timeout(&chan_dump_done, 3 * HZ)) {
+ chan_dump_pending = false;
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+
+/*
* Debug injection: teach the service one {GPU VA -> guest PA} translation.
* Some client mappings (user VA == GPU VA, sysmem backed) are not
* discoverable from the structures the service scans; this lets a session
@@ -3205,6 +3273,7 @@ static int svc_thread(void *arg)
svc_handle_probe(vgpu);
svc_handle_map_add();
+ svc_handle_chan_dump(vgpu);
if (!svc.direct_base ||
time_after(jiffies, svc.last_build + 10 * HZ))
diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h
index 6b8dc6a..d5e41a6 100644
--- a/kernel/gsp_sema_service.h
+++ b/kernel/gsp_sema_service.h
@@ -57,6 +57,7 @@ void gsp_sema_service_vaspace_del(u32 h_vaspace);
int gsp_sema_service_start(void);
void gsp_sema_service_stop(void);
int gsp_sema_service_probe(u64 gpu_va, u32 count);
+int gsp_sema_service_dump_channels(void);
int gsp_sema_service_add_map(u64 gpu_va, u64 pa, u64 len, u32 ap);
void gsp_sema_service_doorbell(u32 token);
diff --git a/kernel/main.c b/kernel/main.c
index 63657f3..f23be27 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -2248,6 +2248,23 @@ module_param_cb(sema_probe, &nv_vgpu_sema_probe_ops, NULL, 0200);
MODULE_PARM_DESC(sema_probe, "Dump sema-service map + slot values for a GPU VA");
/*
+ * Debug: dump the semaphore service's channel table (GPFIFO/USERD state and
+ * the two NvNotification slots each channel exposes):
+ * echo 1 > .../parameters/chan_dump
+ */
+static int nv_vgpu_chan_dump_set(const char *val, const struct kernel_param *kp)
+{
+ return gsp_sema_service_dump_channels();
+}
+
+static const struct kernel_param_ops nv_vgpu_chan_dump_ops = {
+ .set = nv_vgpu_chan_dump_set,
+};
+
+module_param_cb(chan_dump, &nv_vgpu_chan_dump_ops, NULL, 0200);
+MODULE_PARM_DESC(chan_dump, "Dump the sema service channel table (any value)");
+
+/*
* Debug: inject a verified {GPU VA -> guest PA} translation into the
* semaphore service (used when the client's mapping cannot be discovered
* from guest structures):
diff --git a/tools/guest-diag/memprobe.py b/tools/guest-diag/memprobe.py
index 4fe000b..26ed0af 100644
--- a/tools/guest-diag/memprobe.py
+++ b/tools/guest-diag/memprobe.py
@@ -156,7 +156,7 @@ def main():
limit = 8
for i, a in enumerate(sys.argv[3:]):
if a == "--min": lo = int(sys.argv[4 + i], 16)
- if a == "--max": hi = int(sys.argv[5 + i], 16)
+ if a == "--max": hi = int(sys.argv[4 + i], 16)
if a == "--limit": limit = int(sys.argv[4 + i])
res = find_trackers(pid, fd, lo, hi, limit)
for p, sub, last, cur, sem, mem in res: