diff options
| -rw-r--r-- | BIGPATH-REPORT.md | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/BIGPATH-REPORT.md b/BIGPATH-REPORT.md new file mode 100644 index 0000000..75b0273 --- /dev/null +++ b/BIGPATH-REPORT.md @@ -0,0 +1,197 @@ +# BIGPATH-REPORT — B-2 grown data-bounce region (offline implementation) + +* Branch: `bigpath`, based on `ecfb1278` (m155). Worktree: + `/home/rmcore/Git/integdev_gpu_drv/open-iov-bigpath`. +* Scope: implement `AGENT-chunked-path-design.md` §3 (B-2) — make GR launches + with arbitrarily large operands (vector_add 3×4 MB, victory_math 320 pages, + memcpy_roundtrip 8 MB) execute correctly by replacing the 205-page / + 68-pages-per-pointer data window with a boot-planted 16384-page (64 MiB) + region, with fail-closed cap semantics. +* Constraints honoured: offline only — no module load/unload, no QEMU/mdev, + no guest, no dmesg writes, no reboot. Build: `kernel && make -j8`. + Commit local on `bigpath` only; no remote push. + +## 1. Build result + +Clean build `make -j8` from a `make clean` state: **exit 0**. +Warning delta vs the HEAD baseline (same toolchain): + +| Baseline (ecfb1278) | After B-2 | +|---|---| +| `gsp_phys_booter.c` frame 1120 B > 1024 (`gsp_phys_backend_guest_gr_submit`) | frame **1104 B** (same pre-existing warning, shrunk by the static scratch) | +| `gsp_sema_service.c:12518` unused variable `n_win` | removed (fixed in passing) | +| `main.c:402` frame 1304 B; `%x` vs `unsigned long` in `gsp_phys_rmcall_stage3` | unchanged (pre-existing) | + +No new warnings; the touched lines are `-Wextra` clean. + +## 2. Site → change table + +| # | Spec item | Site (post-change) | Change | +|---|---|---|---| +| 1 | Constants | `kernel/gsp_phys_booter.h:366-369` | `GSP_PHYS_RMCALL_GR_DATA_BOUNCE_VA0` 0x0A000000, `_SLOT0` 80, `_PT_PAGES` 32, `_PAGES` 32*512=16384. Shared header constant: the SVC derives its reloc base and cap from here (no drift, design R5c). | +| 2 | Boot chunk fields | `kernel/gsp_phys_booter.c:2325-2330` | `struct gsp_phys_boot_chunk rmcall_gr_data_bounce;` (16384 pages) + `rmcall_gr_data_bounce_pt` (32 PT pages) added to `boot_stage`. | +| 3 | Stage-3 plant | `kernel/gsp_phys_booter.c:9770-9840` | One-shot (`!pages`) plant next to the 208-page bounce plant: allocate the data chunk (`gsp_phys_chunk_alloc`, one call, contiguous + per-page fallback) and the PT chunk, zero both, write PD0 dual entries 80..111 (same shape as ext pool 32..79: 0 at `slot*16`, `gsp_phys_rmcall_pde(dma)` at `slot*16+8`), then for every page i write `gsp_phys_rmcall_pte(page_dma(i))` at `PT[i/512] + (i%512)*8`; `dma_wmb()`; log `data-bounce region planted: …`. All at stage 3, before any engine fetch. Gated by `gsp_phys_gr_data_region`. | +| 4 | Old window untouched | `gsp_phys_booter.c:9727-9769` (unchanged), mail `9756`/marker `9765`, mail injection mva `17492-17493` | The 208-page window, mail slot 206, marker 207 and the bank-4 mail injection stay byte-identical; only its comment records the B-2 decommissioning as a data carrier. | +| 5 | `bi` helper | `gsp_phys_booter.c:16933-16953` (`gsp_phys_gr_data_chunk`), `16961-16982` (`gsp_phys_gr_data_bi`) | One helper returns `(reloc_va − VA0)>>12` bounded `< 16384` for the grown region (`GSP_PHYS_GR_DATA_BI_NONE` outside); with the parameter off it serves the legacy window bounded by `MAIL_SLOT`. A chunk selector names the active data chunk. | +| 6 | Five sites replaced | retire wait `:17025`, fill_bounce `:17091`, copy-in `:17972`, copy-out `:18653`, window diag `:18698` | All five inline `(reloc_va − 0x110000)>>12` + `MAIL_SLOT` bounds replaced by the helper + chunk selector. No other copy-path semantics changed. | +| 7 | Checksum/scratch arrays | `bounce_csum_in` `:17156` → 16384 entries (static); `checked[]` retire wait `:17015` → static 16384 entries | 64 KB each, off the kernel stack (design risk #4). Single-inflight caller documented in place. | +| 8 | SVC reloc base | `gsp_sema_service.c:12371-12372`, used `:12768` | `SVC_GR_DATA_RELOC_BASE` = shared grown constant; `_OLD` 0x110000 for the parameter-off path. | +| 9 | SVC per-ptr cap | `gsp_sema_service.c:12381-12382`, used `:12703` | 4096 (runaway guard); old 68 kept for legacy. Stop-on-miss still bounds real spans. | +| 10 | SVC total cap, fail-closed | `gsp_sema_service.c:12391-12392`, check `:12749-12767` | Cap = `GSP_PHYS_RMCALL_GR_DATA_BOUNCE_PAGES` (16384); on hit: `svc_gr_data_stalled = true` + `pr_err(… CAP-HIT: region full, launch held fail-closed …)` + return — no silent truncation, the existing bounded hold/retry path takes over. Old 205 kept for legacy. | +| 11 | SVC array headroom | `gsp_sema_service.c:3931` | `SVC_GR_DATA_MAX` 16384 → 32768 (gr_data[] and the backend hand-off array). | +| 12 | R3 hygiene | `gsp_sema_service.c:12671-12700` | Skip the launch's own param VA and the qmd_word 32..47 gr_pages (bank/param) as data candidates, next to the existing QMD-VA skip. Critical for B-2: without it the param-page candidate would consume up to a 4096-page span of resolvable guest memory. | +| 13 | Static asserts | `gsp_phys_booter.c:2365-2410` | Build-time disjointness/geometry contract: 32 PT pages × 512 = 16384 pages; VA0 == slot 80 × 2 MB; root/PD2/PD1 index 0 and PD0 80..111 ≤ 128; end ≤ VAS vaSize 0x10000000; region above ext pool end 0x0A000000; region disjoint from old bounce 0x110000..0x1dffff, win0 0x1e0000.., guest scratch 0x200000... | +| 14 | Module param | `kernel/gsp_phys_gpu.c:1080-1097`, decl `kernel/gsp_phys_gpu.h:357` | `gsp_phys_gr_data_region` (int, 0644, default 1). Read by the stage-3 plant, the SVC fill and the copy path. Boot-fixed (set at insmod). | +| 15 | Teardown | `gsp_phys_booter.c:19611-19613` | Free the two new chunks in `gsp_phys_rmcall_fini` (and, as a one-line in-passing fix, the old 208-page bounce chunk that was leaked there). | + +## 3. Deviations from the design + +1. **Shared header constants instead of per-file duplicates.** The four + region constants live in `gsp_phys_booter.h` and `gsp_sema_service.c` + derives `SVC_GR_DATA_RELOC_BASE`/`SVC_GR_DATA_BOUNCE_MAX` from them. The + design (§3.2, R5c) explicitly wanted the relocation base "comment-bound" + or shared to prevent drift; a shared constant is the stronger form. +2. **`bi` helper covers both modes.** The design's helper description assumes + the grown region only. Because the module parameter must flip the whole + data path back (spec item 7), the helper also serves the legacy window + (bounded by `MAIL_SLOT`), and a small `gsp_phys_gr_data_chunk()` selector + picks the chunk for the copy path. Behaviour with the parameter on is + exactly the design's. +3. **`checked[]` made static, not a bitmap.** The design allowed either; the + static array mirrors the existing single-inflight static scratch pattern + and keeps the wait logic byte-identical. The dedup loop remains O(n²) as + at HEAD; worst case (16384 records) is ~134M u32 compares once per + launch — accepted for bring-up (see residual risks). +4. **Old bounce chunk now freed in `rmcall_fini`.** Pre-existing leak spotted + next to the new frees; freeing it is safe (`gsp_sema_service_work_quiesce` + runs before `gsp_phys_boot_staging_free`). Reported here because it is a + teardown behaviour change beyond the B-2 allocation lifecycle. +5. **Memory-leak observation not fixed:** `rmcall_gr_shadow_win0` and + `rmcall_gr_mail` are also never freed in `rmcall_fini` (pre-existing, out + of scope). Likewise `rmcall_ctx_pt[]` last slot can collide with the ext + pool PD0[0] if the server MAIN context ever reaches the 32 MB maximum + (pre-existing latent; the live MAIN is ~1.2 MB). Neither is touched here. +6. **No F1-style permanent refusal on a persistent cap hit.** Per the spec, + the cap hit marks the launch stalled for the existing bounded hold. Note + honestly: that hold is one-shot per GPFIFO entry; if the region is + genuinely too small (negative control, > 16384 unique operand pages), the + entry can be consumed after the hold window expires, exactly like every + other stalled launch at this revision. The CAP-HIT `pr_err` makes it + visible, but the permanent fail-closed guarantee is `AGENT-bigcopy` + F1/§4 territory and was explicitly kept out of this change (design risk + #6). + +## 4. Risks + +**Design risk #1 — engine walker reach for PD0 80..111 (LOW).** The plant +shape is byte-for-byte the ext pool pattern (PD0 dual entry small half → +fresh 4 KB PT; leaves = `pte(dma)`), which is proven engine-readable at PD0 +32..79; entries 80..111 sit in the same PD0 page and same root/PD2/PD1 chain +(indices all zero, asserted at compile time). The only unproven ingredient is +the slot range itself. Fallback if the first big launch faults/times out with +`changed=0` and the data chunk otherwise healthy: move the region to the +reserved win1 data windows (`GSP_PHYS_RMCALL_VA_GR_DATA_BASE` 0x100000000, +prewin install) — the copy-path changes carry over unchanged. + +**Design risk #3 — 64 MB contiguous `dma_alloc_coherent` fails → per-page +fallback (MEDIUM).** `gsp_phys_chunk_alloc` warns and falls back to 16384 +per-page coherent allocations; boot-time stage-3 cost grows (seconds) and +memory is fragmented across pages (harmless to correctness: each PTE uses the +page's own DMA). Watch the boot log for `contiguous 16384-page coherent +allocation failed` and stage-3 wall time. Mitigation if needed: split the +chunk into a few smaller contiguous allocations — deferred until measured. + +**Other risks carried from the design:** +* *Per-pointer span overshoot.* 4096 pages is a runaway guard; stop-on-miss + still bounds a real operand. If a client's operands are laid out + contiguously with resolvable neighbours, one candidate can consume up to + 4096 pages and the cap can be reached before all operands are in. The + fail-closed stall + CAP-HIT log would expose this on the first big cycle; + the cap value (design open question #4) is the tuning knob. +* *Copy cost.* Up to 64 MB in + 64 MB out per launch (tens of ms), plus up to + 300 × 5 ms retire-wait polls over 16384 pages when nothing changes — all + bounded by the existing wait exits; correctness first (design risk #8). +* *Param flip consistency.* `gsp_phys_gr_data_region` is boot-fixed; a + runtime flip after the stage-3 plant would desync SVC vs plant. Documented + in the param description; the default cannot desync. + +## 5. Grep audit — remaining uses of the old bounce VA0 / 0x110000 + +`grep -rn "RMCALL_GR_BOUNCE_VA0|SVC_GR_DATA_RELOC_BASE_OLD|0x110000" +kernel/*.c kernel/*.h` (excluding unrelated hits `bar_emulation.c:62` LTC, +`gsp_emulation.h:40` firmware block): + +| Site | What it is | Indexes data pages? | +|---|---|---| +| `gsp_phys_booter.c:2338` | the legacy constant definition | no | +| `:2349-2351` | win0-vs-bounce overlap `static_assert` (layout) | no | +| `:2399` | B-2 disjointness assert | no | +| `:9744-9745` | old bounce plant `pr_info` | no | +| `:1011, 2306, 2320, 2371, 16952` | comments/history | no | +| `:16975, 16977` | `gsp_phys_gr_data_bi` legacy branch — reachable only when `gsp_phys_gr_data_region=0`, where operand records really are in that window; bound `MAIL_SLOT` excludes mail/marker | only in legacy mode, by design | +| `:17492-17493` | mail-injection `mva = VA0 + (MAIL_SLOT<<12)` — the mail message page, never a data record | no | +| `gsp_sema_service.c:12372` | the legacy reloc base constant (param-off path) | only in legacy mode | +| `gsp_sema_service.c:12367, 12478, 12646` | comments | no | + +The five data-page index derivations all now go through +`gsp_phys_gr_data_bi()`; with the grown region on (default), no code path can +index a data page through the old window. The mail injection and the old +window's own plant/diagnostics are the only remaining consumers, exactly as +the design requires. + +## 6. Sanity math (checked by computation) + +* `32 × 512 × 4096 = 67 108 864 B = 64 MiB` ✔ +* VA range `0x0A000000 .. 0x0DFFFFFF` (end-exclusive `0x0E000000`) `< + 0x10000000` (VAS vaSize) with 32 MB slack ✔ +* PD0 slot = `0x0A000000 >> 21` = 80; slots 80..111 ≤ 128 (non-shared VAS + ceiling) ✔ +* Disjointness: ext pool `[0x04000000, 0x0A000000)` meets the region exactly + at VA0; old bounce ends `0x1E0000`, win0 ends `0x1F0000`, guest scratch + ends `0x2200000` — all far below 0x0A000000 ✔ (all compile-time asserted) + +## 7. Live validation commands for the lead (supervised; NOT run here) + +```sh +# 1. Bring the branch build into the campaign tree (lead decides merge vs +# manual copy of vgsp.ko) and confirm the param exists: +git -C /home/rmcore/Git/integdev_gpu_drv/open-iov-bigpath log --oneline -1 +cd /home/rmcore/Git/integdev_gpu_drv/open-iov-bigpath/kernel && make -j8 +modinfo vgsp.ko | grep gsp_phys_gr_data_region + +# 2. One full supervised cycle with the B-2 default (grown region ON; +# module args unchanged, gsp_phys_gr_data_region defaults to 1): +cd /home/rmcore/Git/integdev_gpu_drv/open-iov +./backups/evidence-20261002-victory/victory_grfwd_cycle.sh b2-r1 + +# 3. Boot gate (host dmesg) — expect exactly one plant line, no alloc error: +# vgsp-boot: rm-call: data-bounce region planted: 16384 pages at VA +# 0xa000000..0xdffffff (PD0 slots 80..111, 32 PT pages, before first fetch) +# and no "data-bounce region allocation failed" / no +# "contiguous 16384-page coherent allocation failed" (or accept the +# fallback warning and time stage 3). + +# 4. Guest clients: push the battery and run the three big clients plus the +# regression set (the cycle already runs the runner; for manual runs): +./tools/cuda-ab/push_battery.sh +# in the guest: run /tmp/victory_math /tmp/vector_add /tmp/memcpy_roundtrip +# plus regressions (victory_matmul smiley mall victory_mail victory_saxpy +# victory_strided victory_reduce victory_atomics victory_memset2d +# victory_streams_events vecadd_loop). +# Expected host log: "svc-gr data fill: … pages resolved (reloc 0xa000000+)" +# with NO "CAP-HIT"; copy-out "changed by engine" > 0 naming output pages; +# guest: MATH badf=0 badd=0 badi=0 / RESULT bad=0 / ROUNDTRIP bad=0 csum=269221888. + +# 5. Rollback / A-B trial (legacy 205-page window, one flip at insmod): +./backups/evidence-20261002-victory/victory_grfwd_cycle.sh b2-legacy-r1 gsp_phys_gr_data_region=0 + +# 6. Negative control (over-region, > 16384 unique operand pages, e.g. +# vector_add n=2^23): expect the CAP-HIT pr_err + hold, no silent success. +``` + +## 8. Rollback parameter + +`gsp_phys_gr_data_region=0` at insmod restores the legacy 205-page / +68-pages-per-pointer path (reloc base 0x110000): the stage-3 plant is skipped, +the SVC keeps the old caps, and the copy path indexes the old bounce chunk. +Boot-fixed; do not flip at runtime. |
