| Commit message (Collapse) | Author | Age |
| ... | |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The counter enumeration/injection workflow lived in the guest's /tmp and was
lost on every restart. Make it durable under tools/guest-diag:
- sem_counters.py: translate a process's per-channel u32 completion counters
(16-byte stride in the /dev/nvidiactl counter page) to guest PAs through
/proc/<pid>/pagemap; --pairs emits handle,va,pa triples.
- sem_slots.py: read/write the counter slots via /proc/<pid>/mem (fallback
for the host counter publish).
- read_va.py: hex dump a process VA (UVM sysmem GPU VAs are usually valid
CPU VAs in the owning process); --u32 for method streams.
- inject_counters.sh: host-side one-shot: push the tool, take the GR handles
from the live chan_dump, enumerate, then register each counter with
sema_counter and pin its VA with sema_map_add.
- push_guest_tools.sh: push the new tools after every VM start.
- launch_qemu_direct.sh: parameterized mdev UUID/paths instead of a stale
hardcoded one; committed so it survives checkouts.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- svc_handle_chan_dump()/svc_decode_stream(): static snapshot buffers. The
128-channel local array made an ~18 KB frame, which overflows the 16 KB
kernel stack in the function prologue and panicked the host 2-3 s after a
VM attached the vGPU (proven from EFI pstore: guard page hit at
svc_handle_chan_dump+0x20, sub rsp,0x4850).
- svc_pump_channels(): write-back now also persists expected_sem_payload,
rescue_last and rescue_fail. The pump works on a snapshot copy, so
without this the stale-entry skip and the rescue rate limit could never
fire and the payload expectation was reinitialized every pass.
- svc_targeted_resolve(): sliced scan (128 MB per call, one VA at a time,
failed-VA cache) instead of a full-RAM scan per miss; no longer appends
to the sorted map out of order.
- svc_rebuild(): merges new scan results into the previous map (fresh
translation wins in place, new VAs appended) instead of replacing it
wholesale, so live translations survive a scan-yield collapse.
- Warning fixes: misleading indentation, unused variable, jiffies
typecheck. Frame audit: largest frame now 872 B.
- Includes the previous session's uncommitted work: sema_counter /
shadow_scan / shadow_dump debug params, exit stage markers, pdev ref
fix, and the dynamic dispatcher request_firmware-out-of-spinlock fix.
|
| |
|
|
|
|
|
|
| |
Entries whose push buffer was overwritten (the rescue cannot validate any
candidate page) were retried forever, rescanning RAM every 5 s and
leaving the ring stuck behind them. After three real rescue failures
(rate-limited attempts do not count) the entry is consumed with a
'skipping stale entry' log and the pump moves on. New skip= stat.
|
| |
|
|
|
|
|
|
| |
Mid-slot entry VAs were rejected by the alignment guard, leaving their
false translations permanent. Candidate 2 (the group's page minus the
push length) is the PA of the entry VA's page regardless of alignment;
pin only the pages the push occupies for mid-slot entries and the whole
1 MB slot for slot-aligned ones. Validation by read-back is unchanged.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Kernel: the slot-aligned failing entries carry pushes whose release group
is not at the page's fixed +0x10 offset, so the shape matcher found
nothing. Scan every 4-byte offset for the exact group (hdr 0x20038090,
hi==1, lo&0xfff==slot, follower LAUNCH_DMA sem-release; payload may lag
the tracked expectation) with the header compared first. Each match
yields two candidate pin bases - the group's page and the page implied by
treating the group as the end of this entry's push - and each candidate
is validated by pinning and reading the entry VA back before it is
accepted. Live: 13 rescues pinned the MEMOPS slots; the 12700-byte push
then decoded to 29 op-runs with a real release, and memset=338 fills
(page-table clears) executed ~13 s before the client's rc=999.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The content rescue matched only the release group bytes and had matched
GSP firmware pages. It now requires the full known push shape around the
release (two SET_OBJECT class binds, the 3-word SET_SEMAPHORE_A run with
this channel's next payload, and the LAUNCH_DMA semaphore-release
follower), and it is also invoked when a trusted read resolves but the
buffer does not parse as a push (false content-scanned pair; observed
firmware/kernel-data pages), not only when the VA is unmapped. The rescue
pins the whole 1 MB push-buffer slot, which is what the UVM MEMOPS
channels' pushbuffer pool (0x1200_0000 + n*1MB) needs. New false= stat.
|
| |
|
|
|
|
| |
The long bogus pushes (RISC-V tails) could not be tied back to the ring
entry they came from; log the GPFIFO entry VA with each push so the
false translations are identifiable and can be compared against probes.
|
| |
|
|
|
|
|
|
|
|
| |
The discovered VA->PA map is content-scanned and can hand a ring entry's
push VA a false translation; observed: GSP firmware pages read as a
12700-byte method stream whose fills would have been executed into
vidmem. Work now requires the buffer to start with a plausible first
method (INC_METHOD, address 0, sane count that fits the length); releases
still apply from such buffers so a shifted stream is not lost. New
'denied' counter in the sweep stats.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Log one line per ring-decoded push (channel, engine, length, op-run
count, decoded release VA/payload, last 24 bytes) to make the
push->tracker path observable; it showed that the content rescue had
been pinning unrelated RAM pages: pushes of length 4196/8500/12700 whose
tails are RISC-V code (ecall/jal) - GSP firmware or other code pages whose
bytes matched the expected release pattern. Those pages decode as
plausible but bogus method streams, so work executed from them can write
garbage into vidmem. Rescued pages now apply the release only
(allow_ops=false); work requires a page read through a trusted
translation.
|
| |
|
|
|
|
|
|
|
|
|
| |
NVA06C_CTRL_CMD_INTERNAL_PROMOTE_FAULT_METHOD_BUFFERS is sent at
channel-group allocation; it hands the GSP each runqueue's 12 KB CE fault
method buffer as {base (GPU physical), size, alignment, addressSpace,
cpuCacheAttrib} plus a bar2Addr. Parse and log them, and keep the last
set per channel-group object so the addresses (guest structures we cannot
otherwise enumerate) are available to the engine emulation. Live: two
12 KB buffers per group, base = guest PA, addressSpace = 1, buffers
zeroed (no faults posted yet).
|
| |
|
|
|
|
|
|
|
| |
The 15 s pinner loses the race against the client's internal deadline in
most boots: in the one boot where UVM's page-table write pushes were
submitted the pin had landed early, and later pins (60 s+) left the client
dead before submitting anything. Poll the guest pagemap every 2 s and pin
0x20400f000 once per cdt pid (re-pinning the same pid also stirred the
pump's rewind repeatedly, which is why the guard exists).
|
| |
|
|
|
|
|
|
|
|
| |
New module parameter walk_probe <va> runs the recorded-va-space walks and
the discovered-directory walk directly (pin/lat/pair map bypassed) with
per-level tracing, and prints the result of each. This separates 'the
page tables are not walkable' from 'the VA->PA pair map already answers'
when a translation is missing. Baseline on a live boot: root PDB entries
are zero (L0 e=0 idx=0) so the writes UVM issues into the level pages
have no parent entry yet.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The CE pushes UVM's MEMOPS channels submit release through SET_SEMAPHORE_A
plus a LAUNCH_DMA with SEMAPHORE_TYPE=RELEASE_ONE_WORD. That path still
gated the push's collected fills/copies on the semaphore being readable
and behind the payload - the same bootstrap deadlock as the REPORT_SEM
path fixed before: the page-table writes that make the semaphores
translatable were dropped. Run the work unconditionally there as well
(trusted-ring pushes only).
Also log a one-line LAUNCH_DMA inventory (channel, engine, dma word,
modes, offsets, line length, collected op count) for the first pushes
read through rings, which is how the UVM page-table write sequence
(fill 512x8 zero + 16-byte PTE copies + release) was identified.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
The pump gated collected fills/copies on the tracking semaphore being
translatable and behind the release payload. On real hardware the work
always executes and the release only orders observers, so the gate
dropped work exactly when it was needed to bootstrap translations
(UVM's CE memsets writing page tables into vidmem, whose tracking
semaphores live in the address space those writes create) and skipped
pushes as stale as soon as a tracking semaphore advanced past them.
Execute the work at the release method for every push read through a
trusted ring; swept-RAM decoding still never runs work. Count op runs
in the sweep stats (ringops).
|
| |
|
|
|
|
|
|
|
|
|
| |
ctx999.py arms the scanner entry/returns plus cuCtxCreate and dumps the
ctx->mgr->reg->record chain at the stop. First live capture: the scanner is
called with param_2=1 during normal context creation and correctly returns 0
on a zero record (mgr[+0], the channel handle, and the record walk are now
confirmed live). pin_miss_pages.sh must match the exact VA pmapall printed:
guest_pmap_all.py returns the first nvidia page at-or-above va-min, so a page
that is not present resolves to an unrelated mapping (it pinned a UVM page
for 0x20400f000).
|
| |
|
|
|
|
|
|
|
|
| |
pin_miss_pages.sh watches the host journal for release-miss VAs, resolves
each page for the live cdt pid through the guest pagemap and injects it (the
injection rewinds the pump so releases consumed under a stale pin are
re-read); it re-pins when a new cdt pid appears. cuda_drv_test prints
cuGetErrorName/String on failure and, with CDT_HOLD=<seconds>, stays alive so
the RM error record and tracker state can be inspected after cuCtxCreate has
given up.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
record
A freed client's notifier events (hSrcResource 0) stayed valid in the event
table, so the fallback wake-up nudge kept posting POST_EVENT records for a
(hClient, hEvent) pair the guest RM no longer knows; every one asserts in
CliGetEventInfo (kernel_gsp.c:466) and is dropped (171 failures in the
15:24 window of the last run, zero after this fix). FREE now retires the
matching event record (and a client's records when its root object is freed).
bp999.py now walks rdi -> ctx -> ctx[0x1291] -> +0x10 -> +0x10 and prints the
RM error notification record, and push_guest_tools.sh ships it to the guest.
|
| |
|
|
|
|
|
|
|
|
| |
The guest RM's expiring waits are kernel busy-polls and all of their
functions are notrace, so ftrace/kprobes cannot name them. sysrq-l NMI
backtraces can: this sampler triggers them and keeps only the Comm and
[nvidia] frame lines per round, so the wait/teardown stacks survive dmesg
ring wraps. Caught the adapter-shutdown scrubber stack
(channelReadChannelMemdesc <- ceutilsUpdateProgress <- scrubberDestruct <-
memmgrDestroyInternalChannels <- gpuStatePreUnload <- nv_shutdown_adapter).
|
| |
|
|
|
|
|
| |
The rewind used entries - (N - get) for get < N, which for an empty ring
(get=0, put=0) jumped last_get to entries-8, so the pump read ring slots the
producer had never reached and could execute stale/garbage entries. Replay
only recently consumed slots, clamped at 0.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A pin injected after the pump consumed pushes that release through that VA
resolved against the old (or bogus) translation, so the releases were
compared as stale against the old page's values and dropped - a new client
that maps fresh pages at the same VAs then waits forever. Rewind every
channel's last_get by 8 ring entries on injection so the pump re-reads those
pushes under the new translation; the release and fill application paths are
forward-progress guarded and idempotent, so re-execution is safe. The handler
runs in the service thread, which also runs the pump, so no pass can be
in flight during the rewind.
Diagnosed from cdt4: its tracker releases were consumed while the pin still
pointed at the previous cdt's page (value 1), so payload <= cur and every
release was dropped as stale; re-pinning afterwards could not resurrect them
because the ring entries had already been consumed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The content sweep reads arbitrary guest RAM and ran the full push decoder on
every page, so fabricated method streams in unrelated data executed
fills/copies: one boot scanned 65M pages, 'decoded' 124k pushes and ran
dozens of memsets from false positives - writes into live guest memory (a
guest kernel crashed in nvidia_uvm right after such a boot).
- Swept pages now only permit the bounded semaphore-release writes; fills
and copies execute only for pushes the pump read through a trusted ring
translation.
- Pushes read for a compute (GR) channel apply releases only: their method
space is not the copy engine's, so aliased encodings must never become
memory writes.
- sempages.py derives the pages to pin from the client's tracker objects
(sem object + sem memory) instead of matching bare sem-object shapes, which
pinned 140 pages where the client has ~53 sems; shape scan remains as a
fallback when no tracker resolves.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two failure modes kept every GR channel dark despite the ring layout being
known:
- The CE region size was latched on the first autopin attempt, which can run
before all CE channels are registered; a too-small base then points every
GR candidate at a chunk whose entry 0 is zeros, and it stays wrong for the
life of the boot. Recompute the base from the live CE ranks on every pass.
- An existing pin for a ring VA (e.g. from a convention guess) made the
autopin mark the rank done without validating the ring - a wrong USERD is
then never corrected. Validate the candidate chunk (entry 0 decode + USERD
put/get) first and only fall back to trusting an existing pin when the
chunk does not validate; on success overwrite the pin.
Also log one diagnostic line per GR rank when the chunk does not validate
yet, so a silent autopin failure is visible in dmesg.
Live: fresh boot, no manual ring pins - 20/20 GR channels auto-pinned
(correct USERD 0x142000 + 0x3000*i) and ran entry 0 (get=1 sub=1) once the
push pages were bridged.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- The CE semaphore/memset method groups also arrive on subchannel 0 (CUDA's
push library binds the copy class on compute channels to carry the
work-submission releases), so the stream decoder accepts both 0 and 4.
- GR (compute) channel rings live in the same video-memory allocation as the
CE rings, 0x3000 bytes per channel after them: ring (0x2000) at
ce_end + 0x3000*rank, USERD at +0x2000. Discover and pin them once the CE
ranks are known; verified against ring entry 0 (1 MB aligned push VA in
the client window, sane length) and the USERD's put/get, so a layout
change costs a failed pin, not a wrong one. Gated by sema_gr_rings
(default on).
- memprobe: require the sem-VA triple in the sem-object scanner (a bare
qword in the window matches thousands of unrelated pointers once the
ring/pushbuffer windows are part of the range).
Live evidence: ring entries read through the guest's /proc/pid/mem decode to
the GR channels' first pushes; pinning the ring (fb 0x140000+0x3000*rank),
USERD (ring+0x2000) and first-push pages made all 20 GR channels execute
their entry 0 for the first time (get=1 sub=1).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The content sweep now:
- decodes a release whose method stream continues with any INC_METHOD,
not only the CE LAUNCH_DMA group, so the releases at the head of a
compute/GR channel's first push are applied too;
- remembers releases whose target VA had no translation (deferred list)
and retries them every service pass, so a VA->PA injection lands them
immediately instead of after the next full sweep;
- re-arms the fast sliced sweep for a few seconds after an injection;
- treats a channel whose USERD/ring cannot be resolved as stalled, so the
sweep keeps looking for the releases its unreadable pushes carry.
tools: add per-cdt client-pin helper (sem pages + /dev/nvidia0 windows),
sem-page scanner and memprobe fixes (short-read guard, --brief).
Live-verified: injecting a client sem page applied 12 deferred releases
within a second; the service kept applying (89 -> 202) while cdt ran.
|
| |
|
|
| |
shares GR's runlist/PBDMA
|
| |
|
|
| |
replies in the ioctl tracer
|
| | |
|
| | |
|
| |
|
|
| |
pitfall
|
| | |
|
| | |
|
| |
|
|
|
|
| |
Guest driver was receiving SUCCESS replies as 'unexpected events' (0x48, 0x49).
These async init RPCs are fire-and-forget per GSP-RM protocol; driver doesn't
expect a reply on the status queue. CONTINUATION_RECORD still sends SUCCESS.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Added TU104_CTRL_INTERNAL_MEMSYS_L2_INVALIDATE_EVICT (0x20800a6c)
- Added TU104_CTRL_INTERNAL_GR_GET_FECS_TRACE_HW_ENABLE (0x20800a38)
- Added TU104_CTRL_SYSTEM_MAP_SHARED_DATA (0x730151)
- Fixed async RPCs (72 GSP_SET_SYSTEM_INFO, 73 SET_REGISTRY, 71 CONTINUATION_RECORD)
to send SUCCESS replies instead of silent consume
- Added explicit handlers for RPC 47 (UNLOADING_GUEST_DRIVER) and 70 (UPDATE_BAR_PDE)
with proper reply semantics
Guest driver was failing at GSP-RM level with unknown RPCs 47, 70, 72, 73.
Channels registered then immediately unregistered.
Now they should stay registered and complete initialization.
|
| |
|
|
|
|
|
|
|
|
| |
- Add expected_sem_payload tracking to svc_channel for CE channels
- Implement svc_rescue_push_page() to scan guest RAM for push with
expected semaphore release when VA translation fails
- Add svc_init_expected_payload() to initialize expected payload from pool
- Add rate-limited logging of distinct stalled VAs (svc_log_stalled_va)
- Advance expected_sem_payload on successful push decode
- Pushes SEMA_MAP_MAX to 65536, SVC_PIN_SLOTS to 32768 for scale
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
mappings into the service
The pin table became the primary VA->PA store once push-buffer regions and
bridged client mappings started adding thousands of pages per boot; at
8192 slots with an 8-probe window, inserts were silently dropped and
lookups missed at half load. 32768 slots and a 32-probe window keep the
mapped set intact.
tools/guest-diag/{guest_pmap_all.py,bridge_sems.sh} translate the CUDA
client's /dev/nvidia* mappings through the guest's own pagemap and inject
each present page into the service as a sysmem pin. With the client's
semaphore pages pinned the service applies their releases into the page
the client polls (verified: applied 67 -> 109, misses stop growing for
those VAs), where before every write went to the vidmem shadow.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
the libcuda tracker wait
The vidmem window convention turns any VA above the window base into a
vidmem offset, but the CUDA client's GPU semaphores are sysmem objects
mapped into its address space at those same VAs. A release applied through
the convention therefore landed in the vidmem shadow instead of the page
the client polls, and the completion was silently lost: the libcuda
tracker it waits on never advanced. Semaphore reads and writes now use
trusted translations only (pins, learned cache, discovered map, page
walks), so an unresolved semaphore is counted as a miss and stays visible
instead of corrupting a shadow.
tools/guest-diag/trkinfo.py dumps the libcuda tracker the client spins on:
the tracker object behind p+0x9410, the semaphore object it references,
the u32 semaphore memory it polls (a /dev/nvidiactl mapping backed by
guest RAM) and the VMA that memory lives in.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The service pins the CE channel rings and push buffers without any
guest-supplied addresses. Rings are derived from the channel rank among
the live CE channels (ring at FB 0x80000 + 0x20000*rank, USERD at
ring + 0x10000) and verified against the ring's first GPFIFO entry before
the pin is stored. Push-buffer base pages are found by their first-push
signature (SET_OBJECT on subchannel 0, SET_OBJECT on the compute
subchannel, tracking-semaphore release at page offset 0x10 with payload
1); the release's in-page slot offset names the channel and the ring's
first entry names the push-buffer VA, then the whole 1 MB region is
pinned and marked hot.
Pinning a pair also re-arms the page-directory discovery and feeds it the
verified VA/PA pairs as samples, so the walk can translate the parts of
the pool no base page describes.
With rings and push buffers pinned the pump executes the submitted work
(gpfifo done grows, semaphore releases apply, released kept in vidmem)
and the guest kernel UVM waits complete.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Debug injections could only teach sysmem translations, but the UVM CE
channel rings and USERDs live in the frame buffer window, and the
progress service had no candidate for their USERD (the allocation
parameters carry an offset relative to a client pool, not the FB
offset). Add an aperture field to the pinned translations and to the
sema_map_add debug parameter (va,pa[,len[,aperture]]), and probe the
observed UVM layout as well: the USERD sits one 0x10000 block after the
ring for the data-path channels.
With the rings pinned, the pump now resolves and decodes the CE rings
(the entries point at 1 MB pushbuffer regions); only the pushbuffer
VA->PA translation is still missing, so the entries are kept pending.
|
| |
|
|
|
|
|
| |
The probe dumps {type, CPU VA, GPU VAs, size} on every
uvm_rm_mem_get_cpu_va call (and the first 64 bytes of the object's CPU
mapping with nested fetchargs), which is how the host-side learned map
can be checked against what the guest actually created.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The learned VA->PA map only covered guest physical addresses below 5 GB,
but a 4 GB guest has RAM low plus a remapped window above the PCI hole
(top around 6 GB). Structures that landed in the top gigabyte (for
example the UVM semaphore pool) were never discovered, which made the
semaphore translations flaky from boot to boot: releases then could not
be applied and the guest's tracker waits never completed.
Scan and accept translations over the full 6 GB window, and rescan the
pages that have carried release groups in the rolling sweep (pushbuffer
pools are recycled, so those pages hold the next releases). Also log the
first distinct release misses and the sweep position so a stuck wait can
be told apart from a translation gap.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
- re-post the completion event for a bounded window after a channel
completes work (notifier consumed or semaphore release applied), so a
client that starts waiting after the edge-triggered wake-up still gets
a wake-up; the OS event classes carry no source object, so the hint
broadcasts to the registered events
- add rmstate (dump msgq cursors, guest consumption position, event
table) and rmpost (post an event record by index or to all) debug
parameters, both executing in kthreads because the IOMMU read path
only works with a NULL current->mm or the mapping owner's mm
- report the underlying error codes from the event post path
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- admit {GPU VA -> PA} pairs only when the preceding bytes form a valid
client memory descriptor header (type 0/1, CPU+GPU mapped bits), prefer
validated pairs over headerless candidates under first-wins dedup, and
invalidate the translation cache on every rebuild; fixes stale identity
entries shadowing live pool pages and lets the guest UVM channel
bring-up complete on its own
- capture OS event allocations (class 0x79) and post event records
(function 0x1003) into the guest status queue when a channel's busy
notification is consumed, with a broadcast fallback, serialized with
replies via a queue lock
- add BAR0 shadow introspection (dump_bar0/scan_bar0) and guest-side
diagnostic scripts for the VM cycle
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The guest's CUDA stack was stuck inside context creation because the work it
submits is never executed by the emulated GPU. Two forms of pushed work were
missing, and the completion path had grown far too slow to be useful:
- Channel tracking: on a channel allocation parse the GPFIFO GPU VA and entry
count, the USERD address/aperture and the instance block, hand them to the
progress service and drop them again when the channel is freed.
- Host-class (C46F) semaphore releases: pushes on a compute channel signal
progress with a five-dword method run (SEM_ADDR_LO/HI, PAYLOAD_LO/HI,
EXECUTE) rather than the copy-engine group the service already understood,
so those releases were never applied. Decode both forms.
- Emulated vidmem: channel blocks (USERD/instance) and some client semaphores
live in the emulated frame buffer, whose VAs are a window over the BAR1
backing rather than guest RAM; access them through the right aperture.
- Latency: the service's full-RAM sweep took seconds per pass, so guests'
progress waits took whole seconds and the driver tore its own setup back
down in the meantime. Sweep guest RAM in bounded, chunked windows on every
pass, remember the pages pushes are actually found in and revisit those
first, and keep the VA->PA map complete (dedup, sort, binary search) so
semaphores resolve reliably.
Also add a vidmem poke parameter for bringing up and debugging emulated
frame-buffer state.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Merge and remove the pre-reboot flat documents, preserving their still-useful
material in the structured tree: debugging workflows and the EPT-livelock
case study (05-operations/02), performance microbenchmarks and A/B
methodology (05-operations/01), the version-upgrade runbook
(05-operations/02 section 4, with corrected host/guest framing), kernel-code
pitfalls (07-developers) and the OpenRM build/load order
(03-architecture/06 section 7). The remaining legacy files were verified
redundant and removed.
* docs/README now records where each migrated topic lives.
* Portability: the config YAML files are called out as design targets that no
code reads yet, with what adding support actually requires today.
* Getting started: the OpenRM step is marked optional (native vGPU-management
workflows only; the emulated path uses the distro driver).
* tools docs: rmtool/rmtop marked as planned, pointing at the implemented
tools/rmq subset.
* wiki: new CUDA-Userspace-Driver deep-dive page (public-safe, links the
canonical userspace/cuda analysis) and index update.
* scripts/check-docs-links.py plus a CI step so relative links cannot rot.
* STATE.md references to removed documents repointed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Name recovery: name_candidates.py proposes the hand-written API-layer
implementation for each exported wrapper by grouping version variants and
intersecting their callees; 180 high-confidence proposals recorded in
annotations/name-candidates.tsv, 29 of them body-verified and promoted to
names.tsv with evidence in subsystems.tsv.
* Engine records: identified the 0x14-byte per-engine descriptor, mapped its
fields (kind, engine type, instance, class id, CE caps) and the existence
callback, and documented how the missing async copy engine (COPY14) leaves
the secondary record zeroed and blocks context creation (docs/05 section
3.7, public-safe).
* Targeted type recovery: AnalyzeFunctions.java runs the parameter-ID
analyzer over a curated list of 80 functions; 16 improved materially and
the typed decompilations are kept under the version run tree.
* Cross-version: cudatool.py fdematch measures how names transfer between
patch versions (570.144 -> 570.211.01: exports 100%, verified internals
~70%, generated wrappers must be re-resolved by relocation, never by
address arithmetic); documented in the upgrade playbook.
* Corpus tooling: diff_corpus.py (version-to-version corpus diff) and
subsystem_digest.py (per-subsystem call trees).
* Deprecate the old per-version helpers whose address handling and analysis
timeout produced wrong results.
Generated corpora and typed outputs remain untracked under the version run
tree.
|
| |
|
|
|
| |
The per-area coordination file was local scratch (gitignored); future
parallel work is announced through the project handoff instead.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Two more retry loops surfaced once the guest driver got past the CE binding:
- BAR0 region reads returned -EINVAL ("would be handled by mmap"), so a
QEMU-trapped read of BAR0+0x88084 failed and the driver polled it forever.
Serve reads from the BAR0 shadow/trap handler (and mirror BAR1 reads from
the emulated vidmem backing).
- Config-space writes above offset 0xFF were refused with -EINVAL, so the
driver's write to extended config 0x704 (PCIe device control area) never
took effect and it retried. Accept and store extended-space writes; keep
the legacy identity registers fixed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Status now matches the live state: guest driver probe and nvidia-smi work;
cuInit/device queries work; cuCtxCreate returns 999 because the emulated
engine list is missing the async copy engine (COPY14). The userspace
libcuda segfault is recorded as solved, with its mechanism (an RM
allocation reply must echo request parameters; zeroing them corrupted the
caller's saved frame pointer).
* Correct the emulation claims: only a subset of RM controls are
special-cased; the rest return a success reply with zeroed parameters whose
consumed fields are still being corrected; allocation replies are coherent
but no server-side object model exists.
* Add the eight-point emulation checklist and reply-fidelity ladder as
explicit gates, documented in userspace/cuda and linked from the
architecture, implementation and operations docs.
* Fix operational errors: build/test commands, module load order, mdev type
names, LFS references, debugfs claims, in-repo firmware claims, CI claims,
portability matrix (guest status, config layout, userspace driver facts).
* Mark historical material: one superseded banner per legacy document with a
pointer to its replacement; STATE.md marked as a 2026-09-21 snapshot.
* Wiki: fix the index, add status banners and in-place factual corrections
(msgq transport vs legacy mailbox, BAR definitions, error statuses,
migration, glossary), and note the archived 2023 imports.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add the analysis of the NVIDIA CUDA userspace driver used by Open-IOV VMs:
* docs/01-08: architecture (layers, object model, threads, sync, memory,
channels, launch), build and execution model, the driver/kernel/GPU
interface contract, virtualization approaches, the 570.144 decompilation
map with the corrected libcuda crash path and the current engine-topology
blocker, tooling, and a version-upgrade playbook.
* tools/: version-agnostic toolchain - stdlib ELF/interface toolkit
(exports, unwind-table function map, wrapper resolution, version delta,
crash address decode), callgraph walker, corpus annotator, and Ghidra
analysis/decompilation/name-map scripts with resumable parallel drivers.
* 570.144/annotations/: our name map (exports + resolved wrappers + verified
internals) and subsystem index, tracked so naming work accumulates.
* READ-ME-FIRST.md: reading guide with the fast lookup recipes.
The full decompiled corpus and annotated corpus stay untracked (vendor-
derived, gitignored under the version run/ tree).
|