summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/scan2.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
commit93769b1e19b4ce2cf1738d72e600adc5a9ef315b (patch)
tree4414e33bdfc1c8770f52572bcfd627cc830397ec /tools/guest-diag/scan2.c
parent13c07f7585c71bb75870d2a25475b4c9401a57fc (diff)
downloadopen-iov-93769b1e19b4ce2cf1738d72e600adc5a9ef315b.tar.gz
open-iov-93769b1e19b4ce2cf1738d72e600adc5a9ef315b.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/scan2.c')
-rw-r--r--tools/guest-diag/scan2.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/tools/guest-diag/scan2.c b/tools/guest-diag/scan2.c
new file mode 100644
index 0000000..6220038
--- /dev/null
+++ b/tools/guest-diag/scan2.c
@@ -0,0 +1,88 @@
+/* scan2.c - find qwords whose value points into a /dev/nvidia* mapping of
+ the target process, and report the u32 stored there (semaphore hunt).
+ usage: scan2 PID [max_print] */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define MAXR 4096
+static struct { uint64_t lo, hi; char name[64]; } nv[MAXR], wr[MAXR];
+static int nnv, nwr;
+
+static int in_nv(uint64_t a, int *idx)
+{
+ for (int i = 0; i < nnv; i++)
+ if (a >= nv[i].lo && a < nv[i].hi) { if (idx) *idx = i; 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], name[128] = "";
+ if (sscanf(line, "%lx-%lx %15s %*s %*s %*s %127[^\n]", &lo, &hi, perms, name) < 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;
+ snprintf(nv[nnv].name, sizeof nv[nnv].name, "%s", name);
+ nnv++;
+ }
+ }
+ fclose(f);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2) { fprintf(stderr, "usage: scan2 PID [max_print]\n"); return 1; }
+ int pid = atoi(argv[1]);
+ int maxp = argc > 2 ? atoi(argv[2]) : 200;
+ load_maps(pid);
+ printf("writable=%d nvidia=%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;
+ uint8_t *buf = malloc(CH + 64);
+ int printed = 0, scanned = 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) {
+ if (n > (256u << 10)) { n = 256u << 10; continue; }
+ a += 4096; continue;
+ }
+ if ((size_t)got < n) n = got;
+ n -= n % 8;
+ uint64_t *w = (uint64_t *)buf;
+ for (size_t i = 0; i < n / 8; i++, scanned++) {
+ uint64_t v = w[i];
+ int idx;
+ if (!in_nv(v, &idx)) continue;
+ uint32_t val = 0;
+ if (pread(fd, &val, 4, (off_t)v) != 4) continue;
+ if (val > 0x100000) continue;
+ if (printed < maxp)
+ printf("at 0x%lx -> 0x%lx (%s) val=%u\n", a + i * 8, v, nv[idx].name, val);
+ printed++;
+ }
+ a += n;
+ }
+ }
+ printf("scanned=%d printed=%d\n", scanned, printed);
+ return 0;
+} \ No newline at end of file