| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
| |
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)
|
| |
|
|
| |
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
|
| |
|
|
| |
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
|
| |
|
|
| |
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
|
| |
|
|
| |
the sum=0 class shows the engine output written through one path and read through the other
|
| |
|
|
| |
vs readback disagreement (sum=0 class); budget 512
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(svc_handle_map_add) and wins over the ledger in svc_gr_page_note, svc_gr_data_fill and svc_fill; gate the displaced-pin fan-out on a current pin match
Root cause class (sub-agent audit + r371 log forensics): the landing table
(ledger) moved only on host writes, so a VA re-pinned to a NEW page (CUDA
reuses VA ranges across processes) kept resolving to the OLD, freed page.
Every later write through that entry landed on memory the guest kernel had
since reused - the r371 mail client's guest oops (NULL page array in
nv_free_system_pages, 8 zero bytes) is this class. Fixes: (1) svc_handle_
map_add repairs a disagreeing ledger entry from the fresh pin (PIN-REPAIR);
(2) svc_gr_page_note and svc_gr_data_fill keep a live pin over the ledger
(PIN-WINS); (3) svc_fill checks the pin before the ledger fallback; (4) the
pool alt fan-out writes the displaced page only while the current pin still
names it (alt_skip). New diag: pinrep= alt_skip=.
|
| |
|
|
| |
wrapper's EXIT= marker is lost when the guest's process reaping stalls (observed: victory_mail reached STATUS OK but the zombie was never reaped; soak reported a false still-running failure)
|
| |
|
|
| |
indirect/bank operands (the kernel output buffer) resolved there while the client D2H readback used an older ledger landing, read stale zeros and the kernel looked wrong (victory_reduce sum=0 with the correct sum proven in the bounce page)
|
| |
|
|
| |
- the 0x204020000 engine-window clear resolved to a different guest-RAM page on every execution and zeroed 8 KB of guest kernel memory (gmain NULL deref in __fdget, task_struct corruption)
|
| |
|
|
| |
arm-on-VA-change rule moved the deadline on every held entry (streams2 wedge: opdef=955/13/0, drain held climbing, expired 0); entries held while a bound is active ride it and flush together
|
| |
|
|
| |
copies (bounded) so zero-walking tables trace to their building copy or prove the source was zero
|
| |
|
|
| |
LINE_LENGTH_IN is the size in BYTES (count=line_length/elem; the old count=line_length wrote elem x too much), value from DST_X mapping (CONST_A/CONST_B), r367
|
| |
|
|
| |
proved below-floor window fills executing via unproven resolution zeroed guest RAM (slab GPF -> guest panic); add LOWFILL-WIT resolution witness for below-floor fills
|
| |
|
|
| |
constants) + opt-in vidmem-window fill execution (gsp_sema_winfill, off) + FILL-RAW raw-push diagnostic; remapconst log budget 256
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
guest-RAM fill branch + diagnostics
The opdef hold used a slot-keyed deadline that a pin-batch rewind
re-arms on every replay (observed opdef=3301/32/0 with the guest
wedged); the bound is now keyed to the launch push VA and written
back through the pump snapshot, like the GR hold bound (r213).
The fill op builder also accepts physical SYS destinations below the
VA floor (guest-RAM page-table clears; bounded by SEMA_PA_MAX).
The vidmem-window zero-fill experiment (r362) was reverted: executing
those fills with elem=1 wrote 4-byte partial zeros and broke results
(no drops but sum=0); the window fills need their true element size
and value semantics decoded first (see handoff).
|
| |
|
|
| |
expiry and wedged client init; keep the content-hash witness and the bound-expiry retry-forward)
|
| |
|
|
| |
run - stale GPU page tables class); launch hold without capture trust + bound-expiry retry-forward (no silent launch drop); guarded zero-fill for client device VAs; walk/rehold diagnostics
|
| |
|
|
| |
readback reading a stale page (victory_reduce sum=0 class); add GMMU walk trace + fwd-hpa diagnostics
|
| |
|
|
| |
expect LAUNCH_COUNT=1)
|
| |
|
|
| |
retire-wait tracked-total fix; sema acquire wait gate per-entry + C56F op semantics (opt-in); fill-shape decode diagnostic
|
| |
|
|
| |
launch runs its engine work twice; the multi-pass class root cause)
|
| |
|
|
| |
(vector_add green), multi-tenant live, battery frontier (multi-pass content + streams2 ordering)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The streams2 readback-before-scale class is root-caused: core CUDA
starts compute-channel pushes with a C56F SEM_EXECUTE acquire
(ACQ_CIRC_GEQ on a tracking semaphore; e.g. the D2H readback push
waits on 0x20400fef0 >= its sequence number) and the decoder ignored
it, so the copy ran ahead of the scale launch it waits for. The gate
implemented here (decode the acquire; svc_run_ops holds the push's
work until the semaphore satisfies, with the driver's
release(N)+acquire(N) same-push pattern treated as satisfied;
op-pending bounded hold; kill switch at 2048 holds; diagnostics
sema-wait held rows with a per-session budget) OVER-HOLDS on boots
where a channel's first pushes wait on counter values only their own
withheld release would install (wait counts reach thousands, the
client stalls; r337/r338/r339). The tracking-semaphore value
semantics (what the guest word should read vs the driver's sequence
numbers) need a dedicated pass before this can be enabled.
Default OFF so behaviour is the pre-r336 one; enable per-boot with
sema_wait_gate=1 for the experiment. Everything else (pin-wins,
vector_add, the battery) is unaffected.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
readback-before-scale class)
Core CUDA starts each compute-channel push with a C56F SEM_EXECUTE
acquire method (five words [ADDR_LO][ADDR_HI][PAYLOAD_LO][PAYLOAD_HI]
[EXECUTE]; op 0/2/3/4/5 = acquire/equal, strict GEQ, circular GEQ,
AND, NOR). The decoder handled only op 1 (release) and 6 (reduction),
so every wait was ignored and a push's work could run ahead of the
dependency it waits on. Observed on streams2: the D2H readback push
carries ACQ_CIRC_GEQ on the channel progress counter (0x20400ffd0 >=
4, the 4th push = the scale launch); the readback executed before the
scale, and the client verified the pre-scale buffer (bad=32767, c2 =
a2+b2 without the x2).
Now the decoder records the acquire and svc_run_ops honors it before
running any of the push's work: satisfied (read + circular/equal/GEQ
compare) -> proceed; unsatisfied -> set op_tr_pending, so the entry is
held and its release withheld (bounded by SVC_OPDEF_HOLD_MS, loud) and
the re-decode runs the work once the counter advances. Unreadable
semaphore: fail-open (pre-r336 behaviour). New stat wait=held/pass.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The m180 unification redirected a divergent write to the ledger's page
(where an earlier write landed) even when the current translation was
pin-backed (guest pagemap truth, op_tr_src == 1). When the guest
remaps/reuses a VA (free + reallocate, or migration), the ledger page is
freed and can be reallocated by the guest kernel: the redirected write
then smears client copy data over kernel memory. Observed on the r335
vector_add run: an RM map/AVL node's pointer field held client c-data
(floats 551.25/552.0), the free-path traversal faulted
(mapFindLEQ_IMPL/_mapInsertBase), and the guest panicked
(Attempted to kill init). 4448 write-side divergences in that run.
Now a pin-backed translation wins: the write goes to the fresh page and
the ledger store after the write re-homes the entry, so readers converge
on the same page. Non-pin translations (2..5) keep the m180 redirect -
they can carry stale PTEs (m169) and the write history stays the
authority there. New counter sema-svc ledger pinwins.
|
| | |
|
| |
|
|
| |
(status-queue SWAP_RX cursor); guest CUDA kernels green end-to-end (mail/matmul/transformer); large-buffer class frontier
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Under MSGQ_FLAGS_SWAP_RX (both sides set it; flags=1 in both headers) the
guest driver's msgqRxMarkConsumed writes its STATUS readPtr to
pOurRxHdr->readPtr, and the driver's pOurRxHdr is the COMMAND-queue buffer's
RX header (msgq.c msgqRxLink swap branch: pReadOutgoing = &pOurRxHdr->readPtr
with pOurRxHdr from msgqTxCreate's pBackingStore = pCommandQueue). The
status queue's own +rxHdrOff is the mirror we publish - our command-queue
read position.
The status free-space check read the mirror, so it tracked our own writes:
with the guest mid-drain the ring was declared full (free=0, peer=0,
write=62/63), replies were written into it anyway, unread records were
overwritten, and the guest RM read a newer record - GspMsgQueueReceiveStatus:
Bad sequence number. Expected 447 got 510. Possible memory corruption. -
after which every RPC failed (status 0x25) and the first client's cudaMalloc
returned device busy or unavailable. That is the boot lottery: on a lost
boot the first client (mail) FAILs and the boot is poisoned for every later
client.
Evidence (r330 vs r332): r330 mail FAILed at the first cudaMalloc and only
one channel unregistered in the whole boot (the guest RM never tore its
channels down after the status desync); with the fix r332 mail + matmul pass
and every client's channels unregister (79 unregisters, one session flush
per client).
Also adds bounded diagnostics: sema-d2hmap (per-page destination resolution
of >=1MB host-dest copies) and a raised DIVERGE witness budget.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(cold-run gap)
The fwd-defer arm took priority over svc_opdef_release, so a pass whose op
was still pending recorded its fence release in svc_fwd_rel (applied at the
hold break / fallback) instead of the opdef slot - the fence fired while
the copy was still owed, the driver refilled the ping-pong staging, and the
late capture/read got refilled bytes (cold-run vector_add gap: one to four
chunks per cold boot). svc_fwd_defer_arm() is now skipped when
svc.op_tr_pending, so those releases go through svc_opdef_release and apply
only when the retried pass has no pending op (the op has run by then).
Measured cold-run vector_add bad across this iteration: 193536 -> 100352
(r323) -> 479232 (r324 wrong queue-pending experiment, reverted) -> 66560
(r325, ~1 chunk). All other acceptance items green on r325 (mail OK, smi OK,
matmul OK, transformer OK).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
denied passes
Two fixes for the cold-boot classes (CONT.60):
1) Pending releases starved forever: svc_apply_pending resolved the pool
semaphore with h=0, but the verified pool resolver is channel-keyed - it
never matched the per-channel pool entries while the very same lookup at
decode time succeeded (matmul r322: 'pool-rel cand ... rrc=0 cur=0' then
'pending release starved va=0x121000010 payload=1 tries=4/64...' forever,
the client hung and the boot died). Pending entries now record the channel
they were decoded for (struct svc_pending_release.h, set from svc.cur_ch
which svc_decode_stream stamps at its top) and svc_apply_pending resolves
with it. Also applies to the 'completion hint rc=-2' class.
2) The fence escaped on denied passes: in the P6b wave-2 overflow branch
the release was queued only when n_ops>0; a denied pass (n_ops==0) but
op-pending (a copy still owed) applied the release inline, letting the
driver refill the ping-pong staging before the copy ran - the cold-run
capture gap (vector_add run 1 bad=157696/193536). The queue condition is
now n_ops>0 || svc.op_tr_pending.
Measured (r323 fresh boot, full sequence): mail OK, nvidia-smi OK, matmul
OK (no death - the r322 killer), transformer OK (no stall), vector_add
cold-run bad=100352 (two chunks, down from 157696-193536; warm runs remain
bad=0).
|
| |\ |
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Root cause of the vector_add chunk drop (CONT.55 chase): the sw-copy
client's GR-classified GRCE channel (eng=0, h=0x5c000059) decodes its
1MB H2D chunk copies as CE transfers, but ops on that channel run only
once the pin/trust stream (injected) reaches each push page. The first
pass over a chunk push lands before that; with allow_ops=0 the copy was
never built and the entry was consumed silently. All later passes
classify as replays (slot_ops_complete=1), so the entry was never
retried: 6 of 8 chunks skipped, kernel computed on stale VRAM
(vector_add r302-r307: 2-5 of 8 chunk ops ever existed, the rest never
ran; the +2MB 'phase' signature is stale residue).
Fix: a denied launch that WOULD have built a type=1 device-dst copy
(no remap, both offsets, out >= SVC_VAS_FLOOR) with a trusted push now
marks the pass op-pending. op_tr_pending un-completes the slot, so the
next pass is treated fresh and the copy runs as soon as trust (injected
with allow=1) or the operand translation arrives - the existing
m163/opdef hold+retry machinery. Replay passes are deliberately
eligible (that is what makes the retry possible); a per-slot
slot_pend_tries cap (4 per put epoch) prevents a slot whose trust never
arrives from wedging the channel in 10s hold cycles.
Measured (r308, sema_dbg): all 8 consecutive chunk dsts build ops
(0x...cc..d3) and retry to success - 28 CEAUDIT rc=0 soft copies, 38
rc=0 vs 20 rc=-2 executions; previously max 5 dsts and only the last
2-3 ran. Regression checks on r309 with the fix: probe RAWA2+PROBE2B
bad=0, victory_mail OK, victory_matmul OK (one transient first-run
fail, clean re-run), transformer OK. vector_add now advances through
the full H2D set but still does not complete (retry storms stretch the
copy phase; the run later wedges in the GR stale-wedge recovery loop -
named as the next lead).
Diagnostics kept (dbg-gated, bounded): sema-pend set/hold witness,
sema-consume consumed-slot witness, sema-entry de-gated for eng=0
channels, dmatrace extended with replay/eng/pend_would, budgets raised
under sema_dbg so boot init cannot spend the trace before the run.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
ops-order release guard
1. CONT.53 step (1): device-dst copies from host sources now snapshot the
source at op-build (bounded pool 16 x 4 MB, 30 s TTL) and execute
from the snapshot, so the staging read happens at the push's
processing position.
2. The capture gate is aperture-based (dst VID, src SYS) after the r300
captures showed a naive VA-floor gate also caught D2H readbacks and
froze pre-kernel zeros.
3. Ops-order release guard: a pass that built ops queues its releases
through the pending pass instead of applying inline, so a fence
never clears before the pass's copy ops read their source.
A/B (r297/r299/r300): snapshots fire (6-7 per run) but the +2 MB phase
persists (win@0/1M = exp[+2M]); the r300 capture contents show the H2D
op sources already carry late-chunk data at decode - the scrambling is
at the driver's staging hand-off into the push stream, before our
service sees the op (next instrument: correlate the client's PTRS with
per-capture buffer identity).
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The m169 device-dst guard defers a staged H2D up to 3 s; the driver's
ping-pong staging buffers are overwritten meanwhile, so a deferred read
returned a later chunk's content (the +2 MB vector_add phase = the 2x1
MB staging stride). Held copies now snapshot their source at hold time
(bounded: 8 slots x 4 MB, 30 s TTL) and the retried execution copies
from the snapshot, matching the hardware's in-order staging read.
r296 A/B: the snapshot never fires for vector_add - its H2D dsts
resolve with pins promptly and execute without the hold; the +2 MB
persists identically. So the staging overrun happens WITHOUT the
guard: the driver's 2-buffer staging discipline relies on the copy's
completion fence (a semaphore applied when the copy executes) to pace
the restaging; if our completion for chunk i arrives before/independent
of the staging read, the driver restages and our later decode reads
chunk i+2. Next lead: the staging fence's increment timing vs the
copy's execution (the release-before-work class extended to the H2D
staging fences), not the m169 hold.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
r295 measurement: rec[0] va=0x72a93cc00000 hpa=0x119155000 first8=43100000
43108000 = floats 144.0 144.5 = a[524288..524289] - i.e. the first
A-rec's backing page already holds the +2 MB data, before copy-in.
Chained with the r285 upload witnesses (the H2D op sources read the
other buffer's chunk-2/3 data), the +2 MB phase originates on the
HOST-BUFFER side of the uploads (the pinned/staged source resolution
for the client's host buffers), not in the GMMU walk (verified
correct against the driver's own format: PD3[48:47]/PD2[46:38]/
PD1[37:29]/PD0[28:21]/PT[20:12]).
|
| | |
| |
| |
| | |
(wd_rewind_off_until struct member repair)
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
first decode
vector_add was deterministic-wrong (bad=786335 checksum=359549561 identical
across boots) because the 1MB H2D chunk copies always read the driver's
ping-pong staging AFTER it had been refilled (the fence release applied long
before the late op execution; 60+ rc=-2 retry storms per chunk).
Two wiring fixes (r314-r315):
1) The decode-time snapshot was NEVER CONSUMED: svc_copy looked it up
(svc_copy_snap_lookup at the top) and freed it on success, but no code read
from it - every copy fell through to the live per-page source resolution
and read refilled staging. The source read loop now takes the bytes from
the snapshot when present (memcpy from snap + o). The copy also no longer
needs a live source translation, so it executes on its first allowed pass
instead of storming retries.
2) Capture on the DENIED pass too: the old capture gate lived in the
op-build block (allowed passes only - by then the fence fired and staging
was refilled). The denied device-dst copy branch now captures immediately
(pipeline-order moment), same translation-probe guard.
Measured r315 (fresh boot): vector_add first run bad=157696 (cold-run
capture coverage gap), second run bad=0 checksum=392344090.5 STATUS OK
with ALL EIGHT chunks clean and no retry storms (~75 s, guest survives).
Previously 786335 bad / identical checksum every boot.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
for the sw-copy client
Two fixes, both demanded by live evidence:
1) Stale-wedge republish loop (r311-r312): the pump's per-channel write-back
did not persist gr_pub_armed, so the residual watchdog re-armed every pass;
its recovery kept zeroing the completion word and re-publishing (pub-adv/
zero/stale-wedge 3s cycles, exit: pub-adv pa=... val=104 cur=0 last=0). The
word oscillated under a live client that then never completed (r311 vector_add
wedged; guest sshd died). Persist gr_pub_armed/counter_gen in the write-back
and keep them (plus slot_pend_tries) across same-generation re-registration.
Also guard the residue zero: never zero a completion word authored by the
live session generation (r312 instrumentation: pub-adv-wrc + stale-recover-
zero + skip witness). Verified r313: stale-wedge rows 0 (was 66+), client
completes, guest survives.
2) Staging snapshot capture for the sw-copy client (r311): the decode-time
H2D capture gate required src_aperture == CE_APERTURE_SYS, but the driver
sends no SET_SRC_PHYS_MODE for the 1MB chunk copies, so src_ap defaulted to
VID and the gate never matched - zero captures on every run r302-r310 while
executions read the (driver-refilled) staging late. Gate judge is now the
translation: capture when the first source page resolves through SYS. First
verified captures (r311: 2-3 per run, real client bytes in first4) - partial
coverage only; the remaining pipeline-order gap is the open lead (see
handoff CONT.57).
Diagnostics kept: snapgate witness, pub-adv-wrc, stale-recover-zero[-skip].
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Root cause of the vector_add chunk drop (CONT.55 chase): the sw-copy
client's GR-classified GRCE channel (eng=0, h=0x5c000059) decodes its
1MB H2D chunk copies as CE transfers, but ops on that channel run only
once the pin/trust stream (injected) reaches each push page. The first
pass over a chunk push lands before that; with allow_ops=0 the copy was
never built and the entry was consumed silently. All later passes
classify as replays (slot_ops_complete=1), so the entry was never
retried: 6 of 8 chunks skipped, kernel computed on stale VRAM
(vector_add r302-r307: 2-5 of 8 chunk ops ever existed, the rest never
ran; the +2MB 'phase' signature is stale residue).
Fix: a denied launch that WOULD have built a type=1 device-dst copy
(no remap, both offsets, out >= SVC_VAS_FLOOR) with a trusted push now
marks the pass op-pending. op_tr_pending un-completes the slot, so the
next pass is treated fresh and the copy runs as soon as trust (injected
with allow=1) or the operand translation arrives - the existing
m163/opdef hold+retry machinery. Replay passes are deliberately
eligible (that is what makes the retry possible); a per-slot
slot_pend_tries cap (4 per put epoch) prevents a slot whose trust never
arrives from wedging the channel in 10s hold cycles.
Measured (r308, sema_dbg): all 8 consecutive chunk dsts build ops
(0x...cc..d3) and retry to success - 28 CEAUDIT rc=0 soft copies, 38
rc=0 vs 20 rc=-2 executions; previously max 5 dsts and only the last
2-3 ran. Regression checks on r309 with the fix: probe RAWA2+PROBE2B
bad=0, victory_mail OK, victory_matmul OK (one transient first-run
fail, clean re-run), transformer OK. vector_add now advances through
the full H2D set but still does not complete (retry storms stretch the
copy phase; the run later wedges in the GR stale-wedge recovery loop -
named as the next lead).
Diagnostics kept (dbg-gated, bounded): sema-pend set/hold witness,
sema-consume consumed-slot witness, sema-entry de-gated for eng=0
channels, dmatrace extended with replay/eng/pend_would, budgets raised
under sema_dbg so boot init cannot spend the trace before the run.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
ops-order release guard
1. CONT.53 step (1): device-dst copies from host sources now snapshot the
source at op-build (bounded pool 16 x 4 MB, 30 s TTL) and execute
from the snapshot, so the staging read happens at the push's
processing position.
2. The capture gate is aperture-based (dst VID, src SYS) after the r300
captures showed a naive VA-floor gate also caught D2H readbacks and
froze pre-kernel zeros.
3. Ops-order release guard: a pass that built ops queues its releases
through the pending pass instead of applying inline, so a fence
never clears before the pass's copy ops read their source.
A/B (r297/r299/r300): snapshots fire (6-7 per run) but the +2 MB phase
persists (win@0/1M = exp[+2M]); the r300 capture contents show the H2D
op sources already carry late-chunk data at decode - the scrambling is
at the driver's staging hand-off into the push stream, before our
service sees the op (next instrument: correlate the client's PTRS with
per-capture buffer identity).
|