summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAge
* tools/soak.sh: fix the present-clients probe (the for-loop's exit status was ↵Arthur Hanson Rasmusson7 hours
| | | | 1 whenever the last listed client was absent, so a partial battery always failed with 'no-client-binaries-in-/tmp'); append true inside the probe
* r445b wedge hard re-arm trigger: the r445 battery shows every post-dispatch ↵Arthur Hanson Rasmusson8 hours
| | | | no-store episode leaves the warm ladder sem probe ALIVE (the ladder block runs; only the client launch no-writes), so the re-arm now fires on the FINAL no-write retry - TSG PREEMPT bWait=1 (forced context save/unload) + lane-enable/schedules re-run - before the last re-publish; default off
* r445 wedge hard re-arm experiment (gsp_phys_gr_wedge_rearm, default off): on ↵Arthur Hanson Rasmusson8 hours
| | | | the proven engine-wedged warm-sem-probe failure, one bounded recovery attempt - TSG PREEMPT bWait=1 (forced context save/unload) + the m155 extended re-arm (mode-35 lane-enable tail + GPFIFO schedules + doorbell) + a repeated probe - before the historical WEDGED break
* r444 copy-snapshot ownership: key the fail4 held-copy staging snapshot by ↵Arthur Hanson Rasmusson9 hours
| | | | | | | | | | | | | | | | | | | | | (channel, ring entry, push-content hash), not (dst,src,total) alone The wedge_ab deterministic reproducer (bad = mutated-element count) root cause: a held CE copy's source snapshot was captured for one ring entry, left behind when that entry's copy executed through a path that never consumed it (hardware-primary forwarded copy, or a post-execution re-decode whose copy was re-held), and then consumed by a LATER entry's copy that happens to share the (dst,src,total) triple - the client's cudaMemcpy released early with the PREVIOUS step's bytes in the device buffer, and the next GR launch computed on stale inputs (r441/r442/r443 evidence: step N read step N-1 content; sema-bigcopy src16 shows the fresh live source at execution time while dst16_after shows the old snapshot's bytes). Owner identity is (ch->h_object, entry_idx, svc_pass_hash); the pass hash separates a ring slot reused by a fresh push from the entry that captured the snapshot. svc_opdef_clear() additionally frees any snapshot still owned by a consumed entry, so no snapshot can outlive its entry.
* docs: SESSION 13 handoff (transformer=wedge class, four negative wedge ↵Arthur Hanson Rasmusson10 hours
| | | | experiments, the r439 stale-release variant + r441 first-attempt zeroing, r437 battery 10/15, frame animation blocked by the wedge) + frame-sequence tool + LG doc update + transformer stage-bisect tools
* r441 zero the guest-visible release words on the FIRST attempt too (not only ↵Arthur Hanson Rasmusson10 hours
| | | | outcome retries): the r439 evidence shows a first attempt breaking its poll on a stale value (qmd_rel=0x5 from the previous launch's engine write, want=6) while the engine never fetched the deposit (sentinel intact) - the host then shipped a completion for a launch that did not run; zeroing forces the poll to wait for this launch's own engine write, so the timeout ladder and the software-authored completion are the honest path and the wedge classification can no longer be satisfied by a stale value
* r436 full sysmem PTE aperture/VOL matrix: gsp_phys_rmcall_pte_coh becomes a ↵Arthur Hanson Rasmusson11 hours
| | | | 4-mode selector (0=0xf aperture3+VOL historical, 1=0xd aperture2+VOL r431, 2=0x5 aperture2 non-volatile, 3=0x7 aperture3 non-volatile) applied consistently to the leaf PTE and the single PDE (bit0 = IS_PDE there), so the r431 finding (aperture 2 with VOL still 1 is a pair the reference RM never emits) can be A/B'd against the consistent encodings
* r434 wedge instrumentation + CWD-slot path: post-retire QMD64 dump ↵Arthur Hanson Rasmusson12 hours
| | | | (hardware-only w50/w51 INNER get/put = the SKED's CTA dispatch counters, which the submission-time dump cannot show) so the healthy-vs-wedged diff proves whether the grid was dispatched and truncated; post-OK qmdwin reads the launch's own bank; gsp_phys_rmcall_gr_cwd_slot >= 0 emits the CUDA driver's CWD-slot PRI write (SKED_DEBUG_1 ENABLE_CWD_SLOT_COUNT via falcon scratch) + SET_CWD_SLOT_COUNT in the init preamble for the mission's slot-count A/B (-1 = off)
* r433 RELEASE_MEMBAR_TYPE A/B: gsp_phys_gr_rel_membar forces QMD word11 bit14 ↵Arthur Hanson Rasmusson13 hours
| | | | (FE_SYSMEMBAR) on forwarded GR launches so the engine flushes pending sysmem stores before writing the release semaphore - the post-dispatch store-loss signature (release host-visible, data stuck in L2) is what an unflushed write-back L2 looks like from the host; 0 keeps the guest's captured FE_NONE for a one-flip A/B
* r431b revert the coherent-PTE default: the clean-boot A/B showed aperture 2 ↵Arthur Hanson Rasmusson13 hours
| | | | (SYSTEM_COHERENT) is worse on this platform (the first client of the boot wedged with 0/983 and the wedge persisted across the sweep), so the historical NON_COHERENT aperture stays the default; gsp_phys_rmcall_pte_coh=1 remains for experiments (it did make the engine's partial 1-page writes visible sooner)
* r431 sysmem leaf-PTE aperture fix (root-cause candidate): map every host ↵Arthur Hanson Rasmusson13 hours
| | | | dma_alloc_coherent page as SYSTEM_COHERENT (aperture 2) instead of SYSTEM_NON_COHERENT (3) - the reference RM picks the aperture from the allocation's CPU cache attribute, and non-coherent L2 let engine stores linger invisibly (the no-execute wedge) while re-staged copy-in content stayed invisible to the engine; gsp_phys_rmcall_pte_coh=0 restores the historical aperture for a boot-time A/B
* r430 wedge dispatch-window sampling: skedrec samples every poll iteration ↵Arthur Hanson Rasmusson13 hours
| | | | (the release lands ~7ms after the doorbell; the old 8-iteration gate saw at most one sample), full 64-word QMD64 dump per launch (hardware-only w50/w51/w52/w53 included) for the healthy-vs-wedged diff
* r427 idempotent fast-accept: a zero-write launch whose identity (QMD minus ↵Arthur Hanson Rasmusson15 hours
| | | | release0 + staged content checksums) matches an earlier writing launch accepts immediately (no retries, no quiet holds); recorded for every writing launch; wedge diagnostics retained
* r425 wedge diagnostics + init-once A/B: SKED/FECS/TPC/CWD register witnesses ↵Arthur Hanson Rasmusson15 hours
| | | | (healthy vs wedged baselines in-log), prev-out late-store witness, gsp_phys_rmcall_gr_init_once (emit the compute init preamble once per boot vs per launch)
* tools: frame_reader picks the largest kvmfr shm (a stray empty 'kvmfr-*' ↵Arthur Hanson Rasmusson16 hours
| | | | file existed); wedge_ab same-program vs second-launch discriminator
* tools/lg + docs: guest frame producer path (CUDA -> ivshmem -> host) and the ↵Arthur Hanson Rasmusson17 hours
| | | | | | | | | | | | | | | | | Looking Glass status - tools/cuda-ab/frame_producer.cu: renders an animated Julia frame on the guest GPU and publishes it into the ivshmem BAR (the kvmfr 128 MiB window) with a small header + RGBA payload. - tools/lg/frame_reader.py: host-side reader of /dev/shm/kvmfr-<uuid> that saves each published frame as a PPM (the transport half of the frame path). - tools/guest-diag/egl_frame.c: EGL probe (device/surfaceless/default platforms) - live result: eglQueryDevicesEXT sees the NVIDIA device and eglInitialize succeeds, but eglMakeCurrent fails EGL_BAD_ALLOC (0x3003), the same VASpace-allocation wall as Xorg's 'Failed to allocate VASpace object'. - docs/05-operations/06: the state, the blockers and the exact remaining pieces (guest GL VASpace allocation; LGMP session producer).
* sema: r420d bounded 2D-copy geometry witness (sema-op2d)Arthur Hanson Rasmusson17 hours
| | | | | | | Every copy op logs dst/src/bytes/rows/dpitch/spitch beside the decoded line_length/line_count/pitches, so the memset2d readback forensics can tell 'one row per push' from 'N rows in one op' and whether the pitch methods arrived. Bounded by the existing opadd budget.
* tools/cuda-ab: wedge_bisect - bisect the no-execute wedge trigger by ↵Arthur Hanson Rasmusson18 hours
| | | | | | | | | inter-launch activity Modes A/B/C/D add none / an extra H2D / an extra D2H / a 500 ms sleep between the verify and the next launch of the wedge_recover shape. The inputs mutate every iteration, so a no-execute launch is reported (bad>0), never masked by deterministic content.
* sema: r420c 2D fills/copies with pitch == row length cover all rowsArthur Hanson Rasmusson18 hours
| | | | | | | | | | | | | | | | | | victory_memset2d failed deterministically (bad ~= 12.5M of 12.58M) because its pitched operations carry PITCH == LINE_LENGTH (cudaMallocPitch returned pitch 4096 for width 4096) and the r402 2D decode only entered row mode when a pitch was WIDER than the row. The flat path then ran ONE row (LINE_LENGTH bytes) per op, so every cudaMemcpy2D readback and H2D upload delivered only its first row and every cudaMemset2D-sized region beyond it kept stale content - the 'deterministic readback loss' (45K of 12.58M correct ~= the rows the single runs happened to cover). LINE_COUNT is now authoritative for the flat case too: pitch == row length (or no pitch method) means CONTIGUOUS rows, so the single run covers rows*line bytes (element-exact when the line divides evenly, else byte exact). A pitch wider than the row keeps the r402 row-wise mode; 1D ops are unchanged. Both the fill (cudaMemset2D/fill) and the copy (cudaMemcpy2D) decode are fixed.
* gr: r420b author the guest QMD release on every outcome when release0 is ↵Arthur Hanson Rasmusson18 hours
| | | | | | | | | | | | | | | | | | | redirected With gsp_phys_rmcall_gr_rel_mod=1 (release0 -> module semaphore, the ordering fix for the engine-release-before-copy-out race) the engine never writes the guest's own QMD release word, so the host must author it on EVERY backend outcome. The hold's success/fail edges do; a launch with no deferred release records (no hold engaged) fell through and its client hung on a word nothing would ever write - the r414 saxpy f0 cur=5 stall. The backend now reports qmd_rel_redirected in the copy result whenever it points release0 at the module semaphore (rel_mod, or no targetable guest release page). svc_fwd_gr_work folds that into the existing gr_rel_unobserved latch, which makes the bounded outcome check author the word on done (success or failure) - the same forward-only write the hold edges perform. rel_mod=0 paths are unchanged (the engine still authors the word and the latch is only set on an unresolved release page).
* gr/sema: r420 pause completion deadlines under the backend wedge-quiet holdArthur Hanson Rasmusson18 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The r419 soak reproduced the user's mid-boot degradation with the wedge fix in tree: victory_matmul printed bad=65536 while its launch was held by the booter's WEDGE-QUIET window - the client was released ~115 s before the post-hold accept. Root cause: two sema-service deadlines are shorter than the deliberate quiet hold and fire under it, authoring the launch's completion release (and applying its recorded releases) while the engine has not run and the copy-out has not happened: - the 12 s GR release hold (SVC_FWD_GR_HOLD_TIMEOUT_MS) expiry (GR-STALL-fwd-hold ... releases + QMD word software-applied), and - the 3 s per-launch consumption bound (gsp_phys_gr_hold_max_ms) firing the busy-defer consume-with-software-release path, whose inline apply authors the capture's QMD release (GR-REL-AUTHOR src=hold). Evidence (r419 live): push be94 captured 131333.687, WEDGE-QUIET holds 40 s + 80 s until 131345.598, accept 131346.552 - while the sema hold expired at 131230.978 (GR-STALL-fwd-hold waited_ms=12032) and the inline apply authored va=0x204027f7c pay=6 at 131341.734 (h=0x5c00001f). The client's verify completed on the authored word and read stale data. Fix: the booter publishes gsp_phys_gr_quiet_hold_active() exactly around the quiet msleep (bounded by construction). The sema service pauses under it: svc_fwd_hold_expired() pushes the GR deadline (bounded by a 600 s defence-in-depth cap, announced once per hold as GR-HOLD-PAUSE); svc_gr_hold_bound_expired() pushes the per-launch bound (GR-HOLD-BOUND-PAUSE); and the busy-defer one-shot window re-holds while the flag is set so the consume-with-sw-release path cannot run during a quiet hold. The held launch is then forwarded and copied out after the hold, and its completion is authored only on the hold's done edge - after the data write-back.
* gr: r411 sticky wedge episode - quiet the first retry of any zero-write ↵Arthur Hanson Rasmusson20 hours
| | | | | | | | | | | | | | launch once the boot has seen a quiet heal (or a no-write accept) r418 with the r410 quiet path showed the wedge alternating one launch at a time: every second push no-wrote and was accepted (streak was reset by the healed launch in between, so the quiet trigger never armed), e.g. c584 NOWRITE / c92c healed / d424 NOWRITE / d7cc healed / ... 6 holds, 6 heals, 7 accepted no-writes. A zero-write accept (or a successful quiet heal) now arms a sticky wedge episode for the boot; any later zero-write launch takes the quiet path on its first retry, so in an episode every wedged launch either heals (engine writes, client data correct) or is classified loudly instead of riding through the quick-retry accept.
* gr: default wedge quiet window 40 s (r417 live: a 20 s host hold did not ↵Arthur Hanson Rasmusson20 hours
| | | | | | | | | | | | | | | heal, the next 40 s hold did - legit engine writes resumed) r417 reproduced the wedge deterministically with wedge_recover v2 (ITER 0 green, ITER 1 zero-write, both with the legacy win0 shadow path on and with the icache-invalidate bit forced off - the bit is not the trigger) and exercised the r410 quiet path for the first time: the 20 s hold left the outcome at 0 pages, the following 40 s hold logged 'WEDGE-QUIET healed: engine wrote 1 page(s) after the 40000 ms hold (streak was 1)'. A shadow-win0=0 A/B showed the engine executes but fetches the wrong program in that legacy shape (all-32768 wrong), so the win0 shadow path stays on. Default base raised to 40 s so the first hold heals instead of paying 20 s + 40 s.
* gr: r410 wedge quiet window - bounded idle hold before retrying a lane whose ↵Arthur Hanson Rasmusson20 hours
| | | | | | | | | | | | | | | | | | | | | previous launch also no-wrote (r416: 58-launch sticky wedge clears after ~50 s quiet); wedge counters in state; wedge_recover v2 unmask The r416 boot reproduced the sticky no-execute wedge inside 60 s: 58 consecutive launches accepted zero writes while the lane stayed busy (wedge_recover v1's deterministic verify masked every one of them), and the first launches were green again only after the lane sat idle ~52 s. Both r409 (~37 s idle heal) and r416 therefore show the wedge clears on idleness and persists under back-to-back retries (r154/r409), so the retry loop now holds a quiet window (gsp_phys_gr_wedge_quiet_ms, default 20000, doubling on the second quiet retry, 0 disables) before the normal fresh-bank + resched retry when the previous launch also no-wrote. The whole-launch stall budget is relaxed only on this bounded recovery path. NOWRITE lines now carry the consecutive streak and quiet/heal counters, and the state file shows nw_streak/wedge_quiet/wedge_heals. wedge_recover v2 mutates the inputs every iteration so a stale (never executed) launch can no longer match the expected values, and classifies the readback STALE-PREV(NOWRITE) vs OTHER/PARTIAL.
* tools/cuda-ab: memset_probe + wedge_recover forensics clients (session 10)Arthur Hanson Rasmusson21 hours
| | | | | | | | | | | | | | | | memset_probe: linear 8 MB cudaMemset + D2H with first-bad offset and a 4 KB page map (correct / other / malloc-prefill) - separates 'fill under-delivered' from 'readback delivered wrong pages'; standalone green, bisects the memcpy_roundtrip memset phase. wedge_recover: launch+verify loop that on failure sleeps N seconds and retries the same iteration (same context), reporting per-iteration attempts and launch times - tests whether an idle gap heals the per-boot no-execute wedge (r409 log shows a ~37 s client-side gap healed a wedged run). Also ships the missing inplace_scale run binary (its source landed in 7685d1b3).
* tools/cuda-ab: inplace_scale - minimal in-place scale repro for the r407 ↵Arthur Hanson Rasmusson25 hours
| | | | | | | | | drop-stale release race One H2D, one in-place scale launch (128 KB = 32 pages), one D2H, per-page diff. The client made the r406/r407 stale-release race reproducible in isolation: with the drop-stale fix the same binary runs 6/6 + 4/4 green across two fresh boots (was intermittent 2/3 before).
* sema: r408 acquire-wait gate defaults ON (the r408 streams2d readback race) ↵Arthur Hanson Rasmusson25 hours
| | | | | | | | | | | | | | + explicit param desc With the gate off (the mission cycle recipe omitted sema_wait_gate=1), the c2 readback's C56F ACQ_CIRC_GEQ pay=4 ran at 106617.279 with cur=2 - before the c2-add launch was even submitted (106617.411) - and read the not-yet-produced buffer (all zeros). With the gate on the same readback holds until the scale channel's progress counter reaches 4 (sema-wait: hold ... cur=2 waited_ms=353 -> pass ... cur=4) and the ordering is correct. The holds are bounded (sema_wait_hold_ms, default 4000) and fail open loudly, so the pre-r336 pass-through remains available with sema_wait_gate=0 for an A/B.
* sema: r407 drop-stale must not deliver a held entry's releases on a rewind ↵Arthur Hanson Rasmusson26 hours
| | | | | | | | | | | | | | | | | | | (only consumed entries are stale) The r406 inplace_scale repro root cause: the H2D copy's operand translation was unresolved (memcopy rc=-2) and the entry was held with its release withheld (correct); a pin-batch rewind then re-opened lower indices (83) while the held entry (91) sat ahead, and the unconditional svc_opdef_drop_stale treated 91 as an already-consumed entry and applied its withheld release at 104955.751. The copy itself only executed at 104957.418 - the client raced past its blocking cudaMemcpy, launched, the launch's copy-in read the stale buffer (previous run's data) and the copy landed after the launch's copy-out: wrong results with a healthy-looking 32/1032 changed and no classifier firing. An entry is only 'passed' if the ring consumed it (slot_done_epoch); gate the stale drop on svc_replay_seen so a rewind can never deliver a still-held entry's release early.
* gr: r405b late-write probes - retire LATE-PROBE (+500 ms re-scan) and a ↵Arthur Hanson Rasmusson26 hours
| | | | | | | | | | | | | tunable settle window (gsp_phys_gr_settle_ms) The r405 streams2 forensics show a new shape of the no-write class: the in-place scale launch wrote 1 of its 32 expected pages and the partial-changed count was content-stable for 300 ms, so the retire wait declared 'settled' and the copy-out shipped one page. Two runtime knobs discriminate and test the fix in one cycle: gsp_phys_gr_late_probe=1 re-scans +500 ms after the retire wait and logs whether the engine was still writing; gsp_phys_gr_settle_ms raises the content-stable window (default 300 ms).
* gr: r405 restore the no-write classifier input - propagate the tracked page ↵Arthur Hanson Rasmusson26 hours
| | | | | | | | | | | | | | | | total to the retire-wait out-param ed91540a (r345) changed gsp_phys_gr_scan_pages to return the changed count and report the tracked total through an out-param, but the caller saved it into a local and never wrote *n_tracked. Every launch since reported n_tracked=0, so the caller gate (wrote == 0 && n_tracked) was never true: the first-attempt witness, the outcome re-execution retries (fresh qmdwin bank + release zeroing + re-publish), the NOWRITE accept with release-word restore, and the late-store check have all been dead code. The r404 forensics show the regression directly: 'RETIRE-WIT n_data=968 n_tracked=0' beside 'output retirement wait: 0/1032 pages changed (no writes)' for the same launch. Propagate n_all so the classifier fires again.
* docs: GPUBreach-class audit and threat model for the host write pathsArthur Hanson Rasmusson29 hours
| | | | | | | | | | | | | | | | Audit of every host-side write whose target derives from guest data, against the GPUBreach (IEEE S&P 2026) chain: GPU PTE corruption -> arbitrary device read/write -> driver bugs -> CPU root. Findings: the host is structurally off that path (guest GPU page tables host-emulated, physical GPU PTEs host-owned, every write aperture-bounded by vfio_dma_rw to guest RAM or the vidmem shadow, no guest DMA to host buffers), and the remaining wrong-but-valid write class is bounded by the per-page resolution + refusal guards (FILL-TRUNC, FILL-PT-REFUSED, LOWFILL-REFUSED, GRFILL-DROP, stalled-VA demand, sema_copy_dst_pin_guard, DST-DIVERGE). Documents residual risks, what is not claimed (no isolation or side-channel claim; physical Rowhammer is out of scope), and three follow-ups.
* sema: r402 pitched (2D) fills/copies + copy-dst divergence witnessArthur Hanson Rasmusson29 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Two additions for the memset2d/memcpy_roundtrip and readback classes: 1. Pitched transfers. The CE decoder now captures LINE_COUNT (0x41c), PITCH_IN (0x410) and PITCH_OUT (0x414); a fill/copy whose LINE_COUNT is > 1 and whose destination pitch exceeds the row length builds a row-wise op (svc_fill/svc_copy are thin wrappers around the existing 1D bodies, advancing dst by dpitch and src by spitch per row). Each row keeps the whole per-page resolution/ledger/guard machinery, and a failed row's retry re-runs already-written rows with the same pattern (idempotent). A flat transfer carries pitch == row length (or no pitch method) and keeps the historical single-run path unchanged. Bounded 'sema-2d' row names every 2D op build. Note: the current victory_memset2d traffic reaches the engine as GR kernels plus per-row 4 KB CE copies, so this capability does not yet trigger for that client - it is the correct decoder for the CE-class 2D shape (driver channel_utils.c memset2d emits LINE_COUNT/PITCH). 2. DST-DIVERGE witness: when a copy destination resolves from the write ledger, a read-only resolver probe cross-checks the answer and logs (bounded, gsp_sema_dbg) when the writer's page differs from the live resolver's - the 'writer follows the ledger while the reader holds another page' shape behind the failed D2H staging class (streams2 c1 zeros, smiley pass failures). Zero rows fired on r403, so the ledger is not the active divergence for that boot; the witness stays for the next failing capture.
* sema: r401 acquire-wait hold bound + session-wide exactly-once capture memoryArthur Hanson Rasmusson29 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Two fixes for the streams2 / multi-stream ordering class, both verified on fresh boot r401 with the acquire gate enabled: 1. sema_wait_hold_ms (new module param, default 4000 ms) replaces the hardcoded 100 ms acquire-wait bound in svc_run_ops. The old bound is shorter than one emulated GR launch completion (0.5-1.6 s observed), so a D2H readback's ACQ_CIRC_GEQ on the producer channel's progress counter (op=3 pay=4 on 0x20400ffd0) gave up and ran BEFORE the scale launch wrote d_c2; the client then verified pre-scale data (bad=32767). r401 log: the same entry now holds ~1.2 s across cur=1->4 and runs after GUEST GR LAUNCH OK (copy-back optrace 92315.594824 with dst16_after = the post-scale bytes). Fail-open is preserved: a genuinely unsatisfiable acquire still expires, just late enough that the dependency's work has landed (late-but-correct over early-and-wrong). 2. svc_gr_seen: a session-scoped open-addressed (push_va, hash) table behind svc_gr_cand_push_seen(). The 4-slot candidate ring + 8-VA history evicted a real capture within ~12 later captures, so a true replay of an already-forwarded launch was re-captured and re-executed (r399: the same nine launch pushes re-submitted every ~10-11 s for minutes). Cleared in svc_session_flush because a new client's identical-content pushes restart their release counters - a boot-scoped table would silently drop them (LAUNCH-SKIP). Also adds tools/cuda-ab/streams2d.cu: streams2 with per-array/per-4KB-block diff reporting plus the device pointer dump, which localised the remaining failure to the D2H staging write path (our staging-page resolution vs the guest's view).
* sema: r398 size the inline-once table to 8192 slots (256 KB)Arthur Hanson Rasmusson31 hours
| | | | | | | | r398 evidence: the memset's inline write executed twice for the same push (85634.101649 first, 85642.940808 replay 70 us before the D2H readback, zeroing the accumulator). 76 inline writes happened between the two - the 64-slot table had evicted the key. 8192 slots give a ~100x margin over the busiest observed burst.
* sema: r391f take 2 - once-only GRCE inline writes keyed by (push_va, push ↵Arthur Hanson Rasmusson32 hours
| | | | | | | | | | | | | | | | hash, dst, bytes) The first take gated on !replay, which broke pushes whose first pass was untrusted (their bytes are only authored on the later trusted pass) and hung the second client of the boot. Key the inline write by (push_va, push content hash, dst, bytes): a replay of the same push is a genuine duplicate and is skipped, a new push (its release payload makes the hash unique) always runs. Table is session-scoped (cleared by svc_session_flush), 64 slots. Root cause retained: victory_reduce's cudaMemset(d_sum,0,8) is a GRCE LOAD_INLINE_DATA write; every re-decode of that push re-ran it and re-zeroed the accumulator after the launch's copy-out (the sum=0 class).
* sema: r391f once-only GRCE inline writes - the sum=0 class root causeArthur Hanson Rasmusson32 hours
| | | | | | | | | | | | | | | | | | A REPLAYED ring entry must not re-run its LOAD_INLINE_DATA writes. The fill/copy ops were already gated by allow_ops (cleared for entry_replay), but the inline-write gate was 'trusted || allow_ops' and a replay is trusted by construction, so every re-decode of an already-processed push re-wrote its inline bytes into the vidmem shadow. victory_reduce's cudaMemset(d_sum, 0, 8) is exactly such an inline write. Observed on r396: 'sema-grce: inline write dst=0x7845ef000000 -> pa=0x7c00000 ap=vidmem bytes=8 data8=0000000000000000' fired 86 us before the D2H readback of the same VA - zeroing the accumulator the launch had just written (OUT-PAGE-POST val8=0000008000080000 = the correct sum) so the client read zeros (sum=0, bad=1). The same replay rewrote the page repeatedly (482 inline writes/boot). The r383 replay-capture path only needs to CAPTURE the launch; the inline bytes were authored on the first (non-replay) pass.
* sema/boot: r391e print the shadow base pointer in the copy-out and bigcopy ↵Arthur Hanson Rasmusson32 hours
| | | | | | | | | | witnesses Rule in/out a stale or duplicate vgpu->bars[1] shadow between the launch copy-out (svc_fwd_req.vgpu) and the D2H reader (svc_copy's vgpu): the sum=0 runs show the write landing (OUT-PAGE-POST val8 = the sum) and the reader of the same ledger page reading zeros 8 ms later with no logged writer in between. Diagnostic only.
* boot/gr: r391d post-write witness - read the VA's landing page immediately ↵Arthur Hanson Rasmusson32 hours
| | | | | | | | | | | | | after the copy-out write The sum=0 class: OUT-PAGE-WIT shows the changed page's bytes in the bounce (the correct sum) and the ledger resolution (pa=0x7c00000 ap=FB), the copy-out writes hpa=0x16f07a000, and the D2H read of the same ledger page 8-34 ms later reads zeros. sema-fbhpa proves __va(hpa) == base+pa at submit time. This witness reads the page right after the memcpy through the same path the D2H reader uses, so the next failing run names whether the write target and the reader's page differ (aperture/staleness) or the write vanished.
* sema/boot: r391c OUT-PAGE-WIT resolution witness for the sum=0 readback classArthur Hanson Rasmusson32 hours
| | | | | | | | | | The GR copy-out now prints, per changed page, the landing-table resolution of the VA (the exact source the D2H reader's ledger-first branch uses) and its first 8 bytes beside the write target hpa - a launch/readback disagreement (write landed on another page/aperture than the reader resolves) becomes one line instead of a forensics session. Diagnostic only (bounded by the existing copywit budget).
* sema: r391b fix svc_op_translate polarity in the per-page fill resolverArthur Hanson Rasmusson33 hours
| | | | | | | | | svc_op_translate returns 0 on success; the new svc_fill_dst_page_pa tested it without negation, so every page answerable only by the walk/scan returned -ENOENT and the fill truncated (r391 boot: FILL-TRUNC for the page-table writes at va=0x...a00200 -> the client stalled at init). Also demand the unresolved page through the pin channel before failing (stalled VA row -> the userspace stream pushes it to the guest scanner).
* sema: r391 per-page destination resolution for virtual fills - the r390 ↵Arthur Hanson Rasmusson33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | guest panic root cause The 383620-byte context-init zero fill (FILL-NOREMAP class) resolved only its FIRST page through the pin (va=0x7c36c7400000 -> pa=0x131b63000, the pin stream's first run = 29 pages) and then wrote the whole 375 KiB contiguously past it. The pin stream shows the VA's pages are independent guest allocations with split runs (0x131b63000 / 0x131a80000 / 0x128340000), so the contiguous write covered unrelated memory - on r390 exactly the guest kernel's page-table pages 0x131ba1000/0x131ba2000/0x131bab000. The direct map grew three 4 KiB holes and the guest died with 'Fatal exception in interrupt' (unmap_page_range / cpuacct_account_field / psi_task_change faults on physmap addresses). svc_copy has always translated virtual operands per 4 KB page ('a linear PA walk past the first page reads the wrong memory'); svc_fill never did. New svc_fill_dst_page_pa() resolves every page of a virtual fill through the same authority order (fresh pin wins and repairs the landing table, then the landing table, then the resolver chain); the SYS write loop clamps each chunk to the page boundary and writes at that page's own landing; a page with no resolution fails the fill loudly (FILL-TRUNC) instead of writing through a contiguous guess. The >= 64 KiB landing-table pre-store now records only the contiguous VID (shadow) case; SYS landings are stored per page as they are written. Also extends the r384 page-table-shape refusal to every page of a virtual zero fill (the r390 fill's first page was the client's buffer, so the first-page-only check could not see the PTE pages it later covered). Evidence: /tmp/opencode/r390-live.log (FILL-EXEC + sema-opadd lines), /tmp/opencode/r390-guestram.raw (three zeroed PTE pages, CR3 walk), pin log 12-pin_gr_stream-r390.log line 789 (the split runs).
* sema: r384b narrow the fill pin-demand hold to SYS (guest RAM) resolutions + ↵Arthur Hanson Rasmusson36 hours
| | | | | | | | | | | | | | | FILL-EXEC witness - The r384 boot held a large fill whose walk resolution was VID (the emulated vidmem shadow) - the hold was pointless overhead there and the re-decode re-resolves (the resolver is non-deterministic), so the hold now applies only when the fill would land in guest RAM (SYS aperture), the class that zeroed the guest's page-table pages. Shadow resolutions stay immediate. - FILL-EXEC witness (bounded 64/boot): va, pa, aperture, provenance and pattern of every >= 4 KiB virtual fill execution - the decisive line for the boot-corruption forensics; the large zero fills were invisible until now.
* sema: r384 fill-destination guards - pin-demand hold for large unproven ↵Arthur Hanson Rasmusson36 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | fills + page-table-shape refusal for zero fills (the boot-corruption lottery root-caused to zero writes landing on guest page-table pages) Forensics from the r383 boot (guest panic at t=216 during victory_strided): the guest kernel's direct map had TWO 2 MiB holes (phys 0x105000000 and 0x131800000) because their PTE pages at gpa 0x12d3c2000/0x3000 - two adjacent 4 KiB page-table pages - were found all-zero. Kernel objects (the kprobe nodes UVM registers at module load) lived in those regions; the first access after the zeroing faulted (Oops #1 get_kprobe from uvm_init_entry), cascading to the t=230 panic. The zeroing is an 8 KiB all-zero write, the exact shape of the guest's window page-table clear (LINE_LENGTH=8192, value=0), and the emulation's virtual fill resolver is demonstrably non-deterministic: four executions of that same 8 KiB fill resolved to four different guest pages (0x126af8000, 0x12d8e4000, 0x12f20c000, 0x1187fb000 - every one refused by the below-floor guard). The below-floor guard covers window VAs only; a >= 1 TiB VA fill that resolves through the walk/scan had no guard at all. Two nets in svc_fill, both default-on (sema_fill_guard=1) and both fail-open/histed: - net 1: a >= 64 KiB virtual fill whose only authority is the walk/scan (no pin, no landing-table entry) is held through a bounded 800 ms window (sema_fill_guard_ms) while its VA is demanded through the pin channel (the userspace pin stream injects the guest-pagemap truth), so the retried decode resolves through a real pin. Mirrors the m169/r378 copy guards; releases with the historical behaviour after the bound. - net 2: a ZERO fill about to land in guest RAM on a page whose first 64 qwords are all present+NX+in-range PTEs is REFUSED loudly (FILL-PT-REFUSED) - a page table page is never a legitimate zero-fill destination. Pin-backed resolutions are exempt (guest pagemap truth). New witnesses: FILL-HOLD (held fills) and FILL-PT-REFUSED (refused page-table targets), both bounded.
* sema/boot: r383 kill the blanket bounce copy-out (alias+staleness write ↵Arthur Hanson Rasmusson37 hours
| | | | | | | | | surface) + write guards; REPLAY-CAPTURE closes the silent launch-drop hole; CE operand misses feed the pin-demand channel - bounce copy-out now records staged_hpa[bi] per launch and skips: (a) recs whose hpa != staged slot content (alias/leftover), (b) pages the engine did not change (~955 of 968 per boot launch); the remaining changed pages re-validate via gsp_sema_gr_write_guard before the 4 KiB memcpy. Removes the blanket 968-page write-back that was the remaining boot-corruption lottery vector (guest slab freelist clobbered by a foreign page write). - new bounded WGUARD-SKIP guards: gr_write_guard (pin-first re-resolution) on copy-out, release-word zero/restore (rel_va plumbed through the submit), stale-recover-zero, counter release; svc_write_guard pin-agreement on 4/8-byte SYS/FB service writes; svc_copy SYS-dst hold on a fresh-pin contradiction. - svc_qmd_accum replay hole: a trusted replay of an unseen push now captures (REPLAY-CAPTURE) instead of silently dropping; known push -> LAUNCH-SKIP witness; capture history ring prevents double-capture. - svc_op_translate miss path emits the stalled-VA demand signal for CE operands.
* sema: r377 pin-demand for unresolved launch operand pages - every dropped ↵Arthur Hanson Rasmusson38 hours
| | | | data-fill page is logged as a stalled VA (the userspace pin stream watches dmesg for that line and pushes the VA to the in-guest scanner's demand file), so the bounded launch hold can resume on real pins instead of waiting out its bound (the r345 wedge)
* sema: r376 pin-agreement on the copy ledger-first branches - a fresh ↵Arthur Hanson Rasmusson38 hours
| | | | disagreeing pin beats a recorded landing on both dst (write) and src (read) at top level and per page, repairing the entry; closes the stale-entry write (guest-corruption) and read (wrong-result) classes
* sema: r375b drop the resolver-answer ledger store - a stale resolver page ↵Arthur Hanson Rasmusson39 hours
| | | | recorded as the write authority poisons every later write of the VA (r375 boot slab GPF in kmem_cache_alloc at guest t=77s before any client); the table is fed by writes and fresh pins only
* sema: r375 read-after-write authority - the landing table wins for device-VA ↵Arthur Hanson Rasmusson39 hours
| | | | copy sources (top-level and per page), and a resolver answer is recorded so launch/read paths converge; the engine output can no longer be read through a different page/aperture than it was written
* sema: two-path identity check for the FB shadow hpa (__va(hpa) vs base+pa) - ↵Arthur Hanson Rasmusson39 hours
| | | | the sum=0 class shows the engine output written through one path and read through the other
* sema: page-note resolution diagnostic (va/pa/ap/branch) for the launch-page ↵Arthur Hanson Rasmusson39 hours
| | | | vs readback disagreement (sum=0 class); budget 512