summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/scan.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-25 01:48:37 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-25 01:48:37 -0400
commit6fdbe6219f540f23070949648d09c9fd86029d79 (patch)
treefc0cf9dc1a40d389c95917ddb542056745c6cf74 /tools/guest-diag/scan.c
parent93431bdd896d9e6d9a25bebef0fb1af308dd64cd (diff)
downloadopen-iov-6fdbe6219f540f23070949648d09c9fd86029d79.tar.gz
open-iov-6fdbe6219f540f23070949648d09c9fd86029d79.zip
gsp_sema_service: add content rescue for unmapped push-buffer pool VAs
- Add expected_sem_payload tracking to svc_channel for CE channels - Implement svc_rescue_push_page() to scan guest RAM for push with expected semaphore release when VA translation fails - Add svc_init_expected_payload() to initialize expected payload from pool - Add rate-limited logging of distinct stalled VAs (svc_log_stalled_va) - Advance expected_sem_payload on successful push decode - Pushes SEMA_MAP_MAX to 65536, SVC_PIN_SLOTS to 32768 for scale
Diffstat (limited to 'tools/guest-diag/scan.c')
-rw-r--r--tools/guest-diag/scan.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/tools/guest-diag/scan.c b/tools/guest-diag/scan.c
new file mode 100644
index 0000000..d229dc8
--- /dev/null
+++ b/tools/guest-diag/scan.c
@@ -0,0 +1,105 @@
+/* scan.c - find the libcuda tracker objects in a process without ptrace.
+ Tracker layout (object p): p+0x9418 submitted, p+0x9420 completed,
+ p+0x9428 mirror, p+0x9430 sem object; sem object +0x10 -> sem VA (a
+ /dev/nvidia* mapping) whose u32 is small.
+
+ usage: scan PID (prints candidate p and its fields) */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#define MAXR 4096
+static struct { uint64_t lo, hi; } wr[MAXR], nv[MAXR];
+static int nwr, nnv;
+
+static int in_nv(uint64_t a)
+{
+ for (int i = 0; i < nnv; i++)
+ if (a >= nv[i].lo && a < nv[i].hi) return 1;
+ return 0;
+}
+
+static int in_wr(uint64_t a)
+{
+ for (int i = 0; i < nwr; i++)
+ if (a >= wr[i].lo && a < wr[i].hi) return 1;
+ return 0;
+}
+
+static void load_maps(int pid)
+{
+ char path[64], line[1024];
+ snprintf(path, sizeof path, "/proc/%d/maps", pid);
+ FILE *f = fopen(path, "r");
+ if (!f) { perror("maps"); exit(1); }
+ while (fgets(line, sizeof line, f)) {
+ uint64_t lo, hi;
+ char perms[16], rest[768];
+ if (sscanf(line, "%lx-%lx %15s %*s %*s %*s %767[^\n]", &lo, &hi, perms, rest) < 3)
+ continue;
+ if (strchr(perms, 'w') && nwr < MAXR) { wr[nwr].lo = lo; wr[nwr].hi = hi; nwr++; }
+ if (strstr(line, "nvidia") && nnv < MAXR) { nv[nnv].lo = lo; nv[nnv].hi = hi; nnv++; }
+ }
+ fclose(f);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2) { fprintf(stderr, "usage: scan PID\n"); return 1; }
+ int pid = atoi(argv[1]);
+ load_maps(pid);
+ printf("writable regions=%d nvidia regions=%d\n", nwr, nnv);
+
+ char mp[64];
+ snprintf(mp, sizeof mp, "/proc/%d/mem", pid);
+ int fd = open(mp, O_RDONLY);
+ if (fd < 0) { perror("mem"); return 1; }
+
+ size_t CH = 4 << 20;
+ static uint8_t *buf;
+ buf = malloc(CH + 64);
+ int hits = 0;
+ for (int r = 0; r < nwr; r++) {
+ uint64_t a = wr[r].lo;
+ while (a < wr[r].hi) {
+ size_t n = (size_t)((wr[r].hi - a) < CH ? (wr[r].hi - a) : CH);
+ ssize_t got = pread(fd, buf, n, (off_t)a);
+ if (got <= 0) { /* try smaller granularity */
+ size_t n2 = 256 << 10;
+ if (n > n2) { n = n2; continue; }
+ a += 4096; continue;
+ }
+ if ((size_t)got < n) {
+ /* partial read: scan what we got, then continue */
+ n = got;
+ }
+ n -= n % 8;
+ uint64_t *w = (uint64_t *)buf;
+ for (size_t i = 0; i + 4 <= n / 8; i++) {
+ uint64_t sub = w[i], last = w[i + 1], cur = w[i + 2], sem = w[i + 3];
+ if (sub == 0 || sub > 1000) continue;
+ if (last == 0 || last > 1000) continue;
+ if (cur > 0x200000000ULL) continue;
+ if (sem < 0x10000 || sem > 0x100000000ULL) continue;
+ uint64_t vaptr = 0;
+ if (pread(fd, &vaptr, 8, (off_t)(sem + 0x10)) != 8) continue;
+ if (!in_nv(vaptr)) continue;
+ uint32_t val = 0;
+ if (pread(fd, &val, 4, (off_t)vaptr) != 4) continue;
+ if (val > 1000) continue;
+ uint64_t p = a + i * 8 - 0x9418;
+ printf("P=0x%lx sub=%lu last=%lu cur=0x%lx sem_obj=0x%lx sem_va=0x%lx sem_val=%u\n",
+ p, sub, last, cur, sem, vaptr, val);
+ hits++;
+ }
+ a += n;
+ }
+ }
+ printf("hits=%d\n", hits);
+ return 0;
+} \ No newline at end of file