| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
| |
r141 showed the 68-pages-per-pointer change starved the operands: the
launch's own QMD VA (0x204608000) and other low-VA candidates each consumed
68 window pages, so a 256 KB operand resolved 0 pages before the 205-page
cap. Give the full span only to high, cudaMalloc-shaped VAs, skip the QMD
VA entirely, and give every other candidate one page. Three 256 KB operands
(3x68=204) now fit.
|
| |
|
|
| |
scrubber fix)
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
victory_matmul (256x256 float: 256 KB per operand) failed with all-wrong
results while 128 KB workloads passed: the relocation bounce window was
112 pages with a 100-page data cap and 33 pages per pointer, so each 64-page
operand was truncated and the engine ran on partial/mismatched windows.
Grow the planted bounce window to 208 pages (main-PT slots 0x110..0x1df),
move the mail page to the last data-free slot (206, marker 207), and raise
the per-pointer cap to 68 pages and the data cap to 205 (three 256 KB
operands = 3x68 = 204 <= 205). Operands larger than 256 KB still hit the cap
and need a chunked data path (documented at the define).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A green forwarded launch completes in ~170-195 ms, but an intermittent
subset times out with qmd_rel stuck at 5 (cold context save/unload, or an
entry the PBDMA never fetched). The existing recovery only replays the
schedule verbs, which cannot help once the entry was fetched or never
latched, so the client fell back to the software release and read
stale/zero results.
On a timeout, after the schedule re-arm, re-publish a FRESH ring entry with
the same PB/QMD content and re-issue schedule+doorbell, up to
GSP_PHYS_RMCALL_GR_ATTEMPTS (3) with a GSP_PHYS_RMCALL_GR_RETRY_MS (2000 ms)
poll. Safe against double execution: the timeout path never copies the
result out to the guest, so a timed-out attempt did not reach the client -
only the eventually-successful attempt is visible. New counter
gsp_phys_gr_retries and a 'retry N/M fresh ring entry' log line.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The host publishes every forwarded launch into the one-page ladder ring
modulo GSP_PHYS_RMCALL_GPFIFO_ENTRIES (8). Commit 3b82047c declared the
mode-35 user-lane channel with 1024 entries for capture fidelity; the
engine's GET/PUT then wrap at 1024 while the host wraps at 8, so at the
host's first wrap (GP_PUT 7 -> 0) the engine desyncs and never fetches
another entry: launches 1..7 green, the 8th and all later ones silent
(qmd_rel=5, ch_rel=0), which is the 'launch lottery'.
Live proof (r138): the failure fires exactly at slot=7 (first wrap) and
every launch after it fails; vecadd_loop (100 launches) dies at the wrap.
M1's two-launch acceptance never wrapped, so the regression was latent.
Set the declared count back to the host ring constant; the wrap-only
fidelity difference against the captured real-client ring is documented at
the define.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
scrub freeze)
guest_pin_stream: find the scrubber channel buffer among the nvidia vmap
areas (size in the CeUtils channel set, 906F ring shape at +0x64000 when
non-empty), walk its pages with kcore and emit '#scrub <fin_pa>,<hsem_pa>'
(the finish payload at +0x6c004 and the host semaphore at +0x6c000).
pin_gr_stream: handle '#scrub' lines and register the PAs through the
sema_scrubbuf_add module parameter, so the kernel's svc_scrub_pass can
author the guest's scrub progress.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
freeze)
The guest PMA scrubber (in-guest CeUtils CE channel, 4096 GPFIFO entries)
waits on its channel buffer's finish payload (offset 0x6c004) after the
third CUDA session's pages must be scrubbed; nothing in the emulation
authored it, so cudaMalloc froze in scrubCheckAndWaitForSize.
- channel_add: detect the 4096-entry scrubber channel and stash its USERD
PA/ring geometry (the channel itself is left untouched: no rank change,
no pump change - the colliding numeric-handle FREE may still unregister
it, the geometry survives).
- sema_scrubbuf_add debug param: register the finish/host-semaphore word
PAs the guest scanner resolves (vmallocinfo + kcore walk), because the
RM kernel VA space collides numerically with the client CE window in the
global VA map and cannot be resolved through it.
- svc_scrub_pass (service thread, per pass): from the channel's own USERD
GPPut, track submitted scrub blocks across wraps, then author USERD
GP_GET = put, host semaphore = put and finish payload = submitted.
Forward-only, idempotent, zero writes while the scrubber idles.
Live-validated mechanism (r137 VM): authoring the finish word at the kcore-
resolved PA let the frozen victory_matmul leave scrubCheckAndWaitForSize
and proceed to its launch.
|
| |
|
|
|
|
|
|
| |
The one-shot CE mem emission pinned the whole 16 MB window including
pages whose content was zero at the time; the host then read zeros for
the other CE ranks' pushes. Sweep the mem every 2 s, skip zero pages,
emit only new/changed {va,pa} pairs, and burst the Kcore PA cache every
30 s so a remap is re-emitted instead of shadowed by the cache.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
tracking-sem case
The second-client stall leaves exactly one live uvmt event: a tracking
semaphore spinning with val=0 (the other channel/one-shot probes are inlined
in this driver build and never fire). The sem is a member of a uvm_channel_t
whose records sit in the sem's own window and carry the CE ring GPU VA
(0x121010000+) plus back-to-back object handles; the channel's pool pointer is
the first field at channel+0 (channel = sem-0x80), and the pool chain already
satisfies _chain_mems_at once it is tried. The resolver now expands the
candidate set from every ring-VA word's surrounding records and their targets
before scoring. Verified live: the r134 spinning sem resolves to the CE
push-buffer rm_mem with 413 pin runs, where the bare sem-window scan had
produced none.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
freshness on an unknown page PA
Two scanner defects seen in r131: (1) a resolved CE mem whose first vmap
page could not be translated at store time stored page_pa=0, and the
freshness check then failed on every probe, dropping the latch and
re-resolving in a tight loop - and each failed re-resolution left the host
with no pins for the channel at all; (2) the stale path discarded the latch
before knowing the re-resolution would produce anything. Unknown PA now
counts as fresh (the {cpu,gpu} object check is the evidence), and a stale
refresh keeps the previous latch unless a new resolution actually emits
runs.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
displaced pin pair
The r129 cross-page evidence: a 216-byte CE push whose SET_SEMAPHORE_A +
LAUNCH_DMA tail fell in the next 4 KB page, whose injected pin resolved to
an all-0xFF page while the first page decoded perfectly. A continuation
chunk read from an unvalidated source (injected pin, its displaced pair, or
the linear window guess) is now rejected when the whole chunk is 0xFF, the
displaced ipin-alt pair is tried as a new source, and a bounded line names
the rejected (va, pa, src) at the fix site.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
release
The entries the pump holds for the 8 s CE grace are exactly the ones whose
decode found no release. Under SEMA_DBG this logs the decode state
(have_sem, rel va/payload, ops) and the first 64 push bytes for every
content-bearing CE push that decoded no release (2048-line budget,
all-zero reads are filtered so they cannot wash it out). Used in r129 to
show that a push whose tail crosses the CE page boundary reads 0xFF
garbage for its second page - the sem+LAUNCH_DMA live exactly in that
tail, so only boundary-crossing pushes were undecodable.
|
| | |
|
| |
|
|
|
|
|
|
|
|
| |
clear_trace() on a pid switch dropped exactly the one-shot uvmt/uvch
events of the new client when they landed in the switch instant; the
pipe reader then never saw them and the whole session ran with an empty
sem set (r126: vecadd_loop sem=0 for minutes while its CE entries paid
the 8 s grace). Scan the ring tail once per switch and seed the sets
instead - stale kptrs that are also re-learned resolve to no content and
are deferred by the candidate scoring.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
The kptr-keyed one-shot latches assumed object identity, but UVM frees and
re-creates CE push-buffer rm_mems and channels mid-session and the slab
reuses the same addresses; a resolution taken before such a move pinned
pages that read all-zero when the host used them, so every CE ring entry
stalled in the 8 s grace (r125: the live pushes sat at new vmap pages of
the same rm_mem kptr). Candidates are now scored by their window content
(a live push buffer is full of method streams, a freed range reads zeros)
and the best is pinned - all-zero candidate sets emit nothing instead of
poisoning the host map. A resolved mem is re-validated every ~2 s against
its own {cpu,gpu} fields and first-page PA; when they move, the latches
drop and the current truth is re-emitted.
|
| |
|
|
|
|
|
|
|
| |
The pump works on a snapshot copy of the channel table; without the
end-of-pass write-back the hold window was re-armed every pass and a
launch whose argument pointers never translate was never consumed (r122:
smiley's launch held forever). Persist gr_hold_until/gr_hold_idx so the
hold is exactly one bounded window per entry, then the entry is consumed
as before.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
derive the CE vmap pairing per allocation
Two second-client zeros/stall countermeasures:
- svc_gr_data_fill now reports when a launch carries high (device-space)
argument pointers and none of them resolves through any trusted source.
svc_gr_request refuses to forward such a launch and leaves the capture
unconsumed; the pump holds the ring entry for one bounded window per
entry (gsp_sema_gr_grace_ms) and retries it, so a translation that
appears a pass later (scanner pin, published directory, learned pair)
is used instead of executing the kernel against unresolved pointers.
On window expiry the entry is consumed exactly as before (bounded
zeros, never a hang). Bounded per-session fill diagnostics name the
source that serves each candidate (ipin/pin/lat/map/vas/disc/win) and
dump the published vaspace walk results for misses.
- The CE push-buffer kcore chain resolver derives its vmap page offset
per allocation instead of using a fixed shift: the rm_mem size is read
from its real offset (570.144 layout) and paired with the vmallocinfo
area page count, so a leading header page is only skipped when it
actually exists. With an unreadable size the two candidate offsets are
content-probed with the host's method-stream plausibility test and an
ambiguous result keeps the status-quo pairing. This removes the
off-by-one that fed wrong push pages to the pump (content-rescue
crawl).
|
| |
|
|
|
|
|
|
|
|
|
| |
The +1 vmap pairing was content-validated on one boot's CE push-buffer
allocation (4097-page vmap: five rescue anchors at k+1), but r116/r117
show the leading header page is not universal: with the shift applied
client #1 stalls mid-run (rescues resume) where it was green without it.
Reverting the shift restores the previous behaviour; the kernel-side
repair from 16124929 stays (a content-validated rescue replaces the
injected pair, so a wrong pin is corrected once per page instead of
being re-rescued on every pass).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
rescues repair injections
The CE push-buffer uvm_rm_mem is vmalloc'd as a 4097-page area: one
leading page plus the 4096-page (16 MB) GPU data window, so GPU data
page k lives at vmap page k+1. The kcore chain resolver paired page k
with vmap page k, pinning the adjacent push for every page; the pump
then read the wrong push, decode failed, and the host fell into the
content rescue which crawled one entry per ~2 s (r115: rescue_run=4202,
entry_va=0x12001b18c repeating). Verified against five independent
content-validated rescue anchors (k=20..28, all delta +1), and the vmap
area boundary confirms the extra page (nv_vm_map_pages 4097 pages).
Five fixes:
- resolve_mem_pins() takes page_off; the CE chain and uvbp push-buffer
paths pass mem_page_off() (1 when the vmap is exactly 16 MB + 1 page;
0 for direct-mapped mems like the semaphore pool).
- a content-validated rescue page now also replaces the injected-pin
entry (svc_rescue_try / svc_rescue_run_try), so a stale or wrong
injection can no longer shadow the validated page and re-run the
rescue on every pass.
Evidence: r115 rescue anchors va 0x120014000->pa 0x12a2e2000 .. va
0x12001c000->pa 0x12a2de000 all at vmap offset k+1; the candidate pages
decode as the adjacent push (wrong semaphore payload) before the fix.
|
| |
|
|
|
|
|
|
|
|
|
| |
Two robustness fixes for the sequential client battery. cdt_pid() now
picks the highest-pid CUDA candidate: preferring a name-prefix match
kept the scanner pinned to a previous client that was still tearing
down while the new client had already started pushing, so its first
pushes were unreadable, the release expectation drifted past the real
payloads and the stall followed. The CE push-buffer chain resolver now
also runs for uvch channel kptrs, so the pins do not depend on the uvmt
semaphore events alone.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
stall)
The second CUDA client's GPFIFO entries in the CE push-buffer window
(0x120000000) had no injected pin: that window is never mapped into the
client's pagemap, so the scanner's window scan cannot see it, and its
only supplier - the one-shot uvbp kprobe event - is raced by two trace
clears (the scanner's pid-switch clear and semfix's trace-tail clear).
When the event loses the race the entry reads fall back to the ~250 ms
content rescue, which is the second-client stall and the same
resolution-miss class as the ISSUE-0001 lottery.
The guest scanner now walks channel->pool->manager->pushbuffer->rm_mem
in kernel memory with kcore and pins the push-buffer pages directly (no
trace event to lose), and the trace reader's dedup marks reset on a
client switch so a reused kptr cannot suppress the new client's #pb.
Boot evidence (r112): rescue reject ipin=0 for va_page=0x120023000,
rescue scans 175 ms - 1 s each, want incrementing to 39. Smoke test of
this fix on the stalled VM: 478 pin runs (~7955 pages) streamed within
seconds, first va=0x120000000 -> pa=0x108090000. A bounded kernel log
now prints the first CE push-buffer pins of each session.
|
| |
|
|
|
|
|
|
|
|
|
| |
(second-client zeros)
The watcher's pins for the second client's a/b/c buffers can land between
the service loop's svc_handle_map_add() and the launch capture; the fill
then misses them via svc_ipin_lookup, resolves 0 pages, relocates nothing,
and the win0 param page keeps the driver's guest VAs (rk1: candidate[0..2]
-> 0 new pages; DIAG win0[0] 160=753e4ec00000). Drain the queue right
before svc_gr_req_fill() (same service thread, no race).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
registration; scanner streams anonymous high-VA buffers
Second-client wedge fix: a new GSP session re-registers the same channel
handles/ranks, but the per-rank one-shot ring/push-buffer discovery latches
stayed set from the previous session, so the new session's ring was never
re-autopinned (ring_auto=0 pb=0/0, nomap growing) and the guest spun in its
channel-creation wait. svc_chan_rearm_rank() clears the latches on every
channel registration; all post-fix cycles launch the second client.
Scanner: guest_pin_stream.py now streams the client's anonymous high-VA
mappings (cudaMalloc buffers were skipped by the old len(parts)<6 check),
so the host can learn their pages.
Diagnostics: PT-window lines, per-window first words, post-OK qmdwin
w48..59. Remaining: the fill-time svc_ipin_lookup miss for the second
client's a/b/c pins (they exist in the pin log but are not seen at fill
time) - next session.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
(second-client fix)
r99/r100: the fresh session's reused pool page reads the previous session's
residue (cur=2) before the first genuine release (pay=1) is translated; the
translated read set ch->pool_rel_seen, so every later residue release
(payload <= cur) was silently dropped by the final else and the client spun
at DEVICE forever. A read that applied or deferred nothing now leaves the
flag clear so the r63/r64 residue re-seed still fires for the first genuine
release of the session.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(second-client fix)
Second-client launches scanned a stale/reused guest param page that still
held the FIRST client's device VAs: zero new candidates resolved, nothing
was relocated, and the engine executed with unrelocated guest pointers
(r97 evidence: client#1 '15 candidate ptrs, 100 pages resolved' and win0
param 160=110400; client#2 '12 candidates, 1 page' with 160=75552ec00000
unrelocated). The driver-authored inline param block is captured from the
pushbuffer at request time, so scanning it makes pointer discovery
independent of guest-page reuse timing. Adds svc_gr_scan_cand()/
svc_gr_scan_inline() and the DIAG win0/guest-param proof line. Client #1
stays green (4 cycles); the remaining second-client stall is the pool
semaphore residue (see next commit).
|
| |
|
|
|
|
|
|
|
| |
- titles.json: map relative doc links to https://git.vgpu.io/open-iov.git/tree/...
(the host runs cgit; /blob/ URLs do not exist)
- check_site.py: verify every git.vgpu.io URL on every page resolves (HTTP
status check, cached, with backoff)
- site pages: repository home links point at the .git/ URL
- .publish-manifest.json: revised revision records
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
- tools/site: Markdown-to-MediaWiki converter (tracked-paths-only link
mapping, local-marker scan, About-message insert), WikiBot publisher
with diff/check modes and publish manifest, live site auditor, image
uploader, site-only page sources (landing page, About, index, sidebar,
banner templates, About-message template).
- wiki: new public deep-dive sources (project status, install, FAQ,
system overview, GSP and GSP-RM, execution frontier, host module,
guest stack, UVM, physical backend, driver lifecycle, risc-v-gsp-rm-debugger,
hardware/software matrix, HAAEEP, glossary); refreshed CUDA userspace
status; corrected cross-document links; README rewritten for the new set.
- wiki/.publish-manifest.json records each published revision for rollback.
|
| |
|
|
|
|
|
| |
default
smiley (cudaMallocManaged-class, known-failing until the param-offset
fix) moved last so a baseline pass exercises the other 13 first.
|
| |
|
|
|
|
|
|
| |
victory_saxpy, victory_reduce (shared+atomics), victory_matmul (tiled
shared), victory_strided, victory_memset2d (pitched), victory_atomics,
victory_streams_events (3 streams + events), victory_math (mixed
int/float/double). Each verifies via readback and prints STATUS OK|FAIL.
soak.sh now runs the full 14-client set (seq or sustained).
|
| |
|
|
|
| |
Discriminates engine-side writes of float data (kernel ran with c on this
buffer) from non-kernel writes (pointers/QMD-shaped words).
|
| |
|
|
|
|
|
| |
8 changed pages x 4 passes for smiley vs 33 for victory's vadd - the
indexes name the relocated range (bi >= 0x40 = the c-pointer output
window 0x150000+) and discriminate engine-side partial dispatch from a
guest write-back/read attribution failure.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
save/unload lottery)
r90 evidence: the 3rd session's forwarded launch entered SKED (CWD VALID)
and was then saved/unloaded by the FECS before dispatch; qmd_rel stayed at
5/6, GP_GET froze, and every later launch on the boot was never fetched
either. The service owns no repair path, so the channel stayed dead until
reboot.
On the first poll timeout, re-issue the two GPFIFO_SCHEDULE controls the
stage-4 sequence used (channel-level 0xa06f0103 + TSG-level 0xa06c0101,
both proven accepted) and re-ring the work-submit doorbell, then poll one
more full window before the postmortem. No BIND, no PROMOTE (m76-m81
proved the explicit PREEMPT/tail variants stop the QMD enqueuing).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ipin-first data resolution
Two fixes and one diagnostic for the all-zero-results class (r89: smiley's
4 vadd launches reported GUEST GR LAUNCH OK yet every output word read 0):
- gsp_phys_booter: copy the guest data pages into the bounce window BEFORE
gsp_phys_rmcall_publish_locked() rings the doorbell. The fill used to run
after the kick; the engine front end starts within ~7 ms, so the kernel
could read the window before it was filled.
- gsp_phys_booter: per-page checksums at copy-in, compared at copy-out;
the copy-out log now reports 'N changed by engine'. An all-unchanged
window after a reported completion is the front-end-ran/grid-never-
dispatched signature (completion semaphores are front-end authored).
The first 3 data (va,hpa,reloc) triples are logged per launch.
- gsp_sema_service: svc_gr_data_fill resolves data pages through
svc_ipin_lookup() first (guest-truth pins), falling back to
svc_resolve_va, mirroring the pool resolver order; a wrong page here
silently runs the kernel on zeros. First 16 resolved (va,pa,ap) triples
are logged for post-mortem comparison against the guest's own mapping.
|
| |
|
|
|
|
|
|
|
|
|
| |
failure)
The watcher's resolve_sem_pool read sem->page->mem->vas through a
process-lifetime cache: a transient zero captured while UVM was still
initialising the structures was served forever, the pool pin never
landed, and the second-session client hung in cudaMallocManaged
(r88 evidence: 'pool unresolved (retry)' from the watcher while the
same walk succeeded from a fresh QMP client). Cache is now opt-in.
|
| |
|
|
|
|
|
|
|
| |
Two failure modes found when the scanner detects clients by device fd:
a transient boot nvidia-smi was picked and its exited pagemap read back
EOF, and scan_window advanced by got=0 forever (busy spin, no stream);
and non-client nvidia fd holders must never be committed to. Break on
got<=0 in scan_window (scan_range already did), skip nvidia-smi/
persistenced/Xorg, and prefer /dev/nvidia-uvm holders.
|
| |
|
|
|
|
|
|
|
|
| |
The guest pin scanner only tracked processes whose comm matched
CLIENT_PREFIXES (cdt,va,victory). An arbitrary CUDA binary (e.g.
/tmp/smiley) was invisible: no pages streamed, no VA->PA pins injected,
the service could not read its pushes and the client hung in
cudaMalloc/uvm_tracker_wait. Detect compute clients by the CUDA device
they hold open (/dev/nvidia-uvm preferred, then any /dev/nvidia*), with
the prefix match kept as the first-choice path.
|
| |
|
|
|
|
|
|
| |
Password auth with key auth disabled outright: the host's id_rsa is
passphrase-protected and a stale copy of its public key in the guest's
authorized_keys made plain ssh hang on the passphrase prompt (the
reported 'sshpass hangs'). Wrapper defaults to 127.0.0.1:2222
ubuntu/ubuntu, overridable via VGPU_GUEST_*.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The launch line carried both an explicit rtl8139 on netdev net0 and a
stray '-net user,hostfwd=tcp::2222-:22 -net nic' pair, creating a SECOND
slirp network with a second NIC and a second 2222 forward. The SSH
connection landed on one slirp instance while the guest's replies left
through the other interface, stalling the handshake before auth. The
explicit rtl8139 now owns the only user netdev with the 2222 forward.
The generated launch_qemu_rootport.run.sh is patched in place by the
harness from the same line.
Verified: sshpass -p ubuntu ssh -p 2222 ubuntu@127.0.0.1 -> nvidia-smi
green. Guest-side companion fix (persisted in the qcow2 image): the
cloud image's /etc/ssh/sshd_config.d/60-cloudimg-settings.conf set
PasswordAuthentication no; it is now yes.
|
| |
|
|
| |
This reverts commit f5961087aa17111c6cdb7f6641626c0c877eee6b.
|
| |
|
|
|
|
| |
(ISSUE-0002)"
This reverts commit 32a9123b087c67c2a8126c6e9789ce36f7371045.
|
| |
|
|
|
|
| |
closing (ISSUE-0002)"
This reverts commit b839a12de675818f41a8cb388e5663d804c2a1f7.
|
| |
|
|
|
|
| |
payload from GP_PUT (ISSUE-0002)"
This reverts commit cf560b257eac2394da84825f12ba0e4192dc74db.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
GP_PUT (ISSUE-0002)
The CeUtils scrubber channel (entries=4096, GPU-global) stays registered
across client sessions now that deletion is client-scoped, but its channel
buffer memory is reused by later clients' push buffers: entry-pumping its
stale ring invented work and perturbed the session (r79/r80: the first
client wedged on an rwsem). The pump now skips channels with the
scrubber layout (entries >= 4096) and instead publishes the word the pma
scrub actually waits on - the channel buffer finish payload at
gpfifo_va + 8*entries + 4 (live-verified: 0x120064000 + 0x8000 + 4 =
0x12006c004, the address from the hung client's register dump) -
forward-only from the channel's own GP_PUT (one payload per submitted
push, the same counter the guest's ceutilsUpdateProgress polls).
Skipping the scrub's actual memset work is acceptable for the emulated
vidmem: the guest's scrub clears pages of its own shadow, and the
emulation's job here is the completion contract. Revisit if per-tenant
vidmem scrubbing is required.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(ISSUE-0002)
r79 regression from keeping the CeUtils scrubber channel registered
(client-scoped deletion): the session flush trigger required EVERY
channel to close, and the scrubber never closes, so the per-session
discovery reset never ran and the next client inherited the previous
session's map/pins (the r9 class; the first client of r79 wedged the
guest on an rwsem with no output).
The session is now keyed by owning client: channel_add records
svc_sess_client and requests the flush when a channel of a DIFFERENT
client registers while the previous session is live (then waits for it,
exactly like a pending flush); channel_del's flush trigger counts only
channels of the current session client, so persistent kernel/GPU-global
channels (the scrubber) no longer keep a dead session open.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
r78 validation of the client-scoped deletion: the boot session's CeUtils
scrubber channel (client != the UVM client, entries=4096) stayed
registered as intended, but it consumed CE rank 0 and every UVM channel's
rank shifted by one. Ring autopin and push-buffer pairing derive the ring
and pool-semaphore offsets from the rank (0x121010000 + 0x30000*rank,
0x121000000 + 4*rank), so the first client's pairing went to the wrong
offsets and the guest wedged on an rwsem (sysrq: rwsem_spin_on_owner).
Rank is now counted only among live channels of the same owning client;
the UVM client's channels keep ranks 0..5 and the kernel/GPU-global
scrubber gets its own (unused for the pool layout) rank. Missing clients
keep the old counting.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Handles are per-client, but the FREE path unregistered any channel whose
numeric handle matched the freed object, with no client check. r77 root
cause of the third-client pma scrub hang: the boot session's CeUtils
scrubber channel (h=0x2, gpfifo=0x120064000, entries=4096) was
unregistered when an unrelated class-0x2080 object with handle 0x2 in
client 0xc1d00011 was freed. The guest kept using the live channel for
the scrub; the service no longer pumped it, its pushes were never
decoded and the channel-buffer finish payload (pbGpuVA+0x6c004) was
never written, so scrubCheckAndWaitForSize polled forever (sysrq stack:
ceutilsUpdateProgress -> channelReadChannelMemdesc).
Channel registration now records h_client (the RM alloc header's client)
and deletion matches (h_object, h_client); a missing client on either
side keeps the handle-only behaviour. Re-registration keeps the
counter/release slots only for the same (handle, client) pair. Live
proof from the hung VM: sema_probe translates the finish-payload VA
0x12006c004 to pa=0x10f962004 aperture=ram - the word the guest polls is
reachable; the channel was simply invisible to the pump.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
BAR1 aperture (ISSUE-0002)
The pma scrub in a second/third CUDA session memsets a legitimate vidmem
offset at 262M (inside the 512M turing shadow) and the copy path rejected it
with -EINVAL because every FB bounds check compared against
vgpu->bars[1].size, the physical BAR1 aperture exposed to the guest (256M on
TU104). The op was held and retried forever (opdef), the GR scrub waited in
scrubCheckAndWaitForSize and the client froze.
All bounds checks that guard a dereference of the emulated vidmem shadow at
vgpu->bars[1].vaddr now use nv_vgpu_fb_emul_size() via svc_fb_shadow_size():
the copy/fill paths, svc_read_ap/svc_write_ap, svc_ap_ok, the page-directory
discovery scans, svc_lookup's vidmem VA translation, the GRCE inline write,
svc_fwd_operand_hpa and the debug scans. The 2 MB leaf path of svc_gmmu_walk
now validates through svc_ap_ok like every other leaf path so an
out-of-shadow translation falls through to the shadow fallback instead of
reaching the copy path. The RM page-directory debug peek is bounded the same
way.
Evidence: r75b live log: sema-bigcopy dst_va=0x76aa08e02200 -> pa=0x10602200
ap=0 prov=3; sema-bigop rc=-22 repeated; guest sysrq stack
scrubCheckAndWaitForSize -> pmaAllocatePages.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
r73 c3 rank2: discovery read the previous session's residual put (67); the
pump consumed the live entries 0..1, the r48 resync handled the first drop,
but the guest's counter then settled at put=1 while last_get=2 and
userd_wait_fresh was already consumed. The loop condition last_get != put
then marched ~1023 slots the producer had not written, holding each stale
entry for the full CE grace (one fake release per 8 s) - the client looked
wedged and the exec timed out.
When a drop leaves the pump ahead of the producer on a channel with fewer
than half a ring of submissions, rewind last_get to put instead of marching.
A genuine ring wrap needs a full ring of submissions, so this cannot skip a
live entry.
|
| |
|
|
|
|
|
|
|
| |
r72 showed the broad rule holding entries on small failed ops too: two
opdef holds on h=0x5c000059 (entries 82/84) were never resolved and withheld
their releases for the whole session, while c2 hit the pre-existing GR launch
forward timeout. The scrub class this rule exists for is always large (r58/
r71: 1 MiB / 297 KiB / 608 KiB), so only failures of ops >= 256 KB mark the
pass op-pending; small failing ops keep the old consume-and-apply behaviour.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(ISSUE-0002)
r71 c3 reached the pma scrub and froze in scrubCheckAndWaitForSize: three
vidmem memsets (1 MiB / 297 KiB / 608 KiB) failed with -EINVAL because
svc_op_translate resolved their client-VA destinations through a walk to an
out-of-bounds vidmem translation before the scanner pinned the real sysmem
pages. Only svc_op_translate's own failure sets op_tr_pending, so the pump
consumed the entry and applied the release while the memset work was lost.
svc_run_ops now marks the pass op-pending for any op that did not run
(rc != 0, rc != SVC_COPY_FORWARDED): the pump holds the entry and withholds
its releases (bounded by SVC_OPDEF_HOLD_MS) so the retried decode picks up
the injected pin and runs the memset; on expiry the release is flushed and
the op stays skipped, exactly like the -ENOENT path. Sessions with no failed
ops (c1/c2 were 0 fails in r71) are unaffected.
|