diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-25 01:48:37 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-25 01:48:37 -0400 |
| commit | 6fdbe6219f540f23070949648d09c9fd86029d79 (patch) | |
| tree | fc0cf9dc1a40d389c95917ddb542056745c6cf74 /tools/guest-diag/scan.c | |
| parent | 93431bdd896d9e6d9a25bebef0fb1af308dd64cd (diff) | |
| download | open-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.c | 105 |
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 |
