summaryrefslogtreecommitdiffstats
path: root/kernel/main.c
Commit message (Collapse)AuthorAge
* vgsp: guest GR forwarding backend and capture (gsp_phys_gr_forward, default off)gr-forwardingArthur Hanson Rasmusson7 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add a default-off guest GR (compute) forwarding path so a guest CUDA launch submitted on its GR channel can be executed by the physical GR engine on the ladder channel, with fail-closed fallback to the host CUDA bridge and the unchanged software release path. - New module parameter gsp_phys_gr_forward (default 0) and accessor. - New GR execution gate: boot_stage.rmcall_gr_exec_ok, latched only after a real GR submission logs REAL GR SEM OK; the backend refuses while it is unset. - Sema capture: a completed 64-word inline QMD on a trusted, non-replay GR decode becomes an svc_gr_cand (push identity, decoded release0, parameter/program/pointer fields, up to 8 captured inline-write records); the CUDA bridge stays authoritative while the parameter is off and is reached in order forward -> bridge -> software release. - Backend: gsp_phys_backend_guest_gr_submit() maps pages at their own guest VAs through fresh Tier-1 small-PT pages/PDE installs or relocates inline-captured pages to ladder shadow pages (Tier 2), builds SET_OBJECT + the inline-QMD method run + REPORT_SEMAPHORE on the compute subchannel, reuses the shared GPFIFO/USERD/doorbell publish tail (extracted from the CE submit path, CE bytes unchanged) and polls the QMD release and/or module semaphore, draining the epoch-gated fault queue on timeout. - Sema wiring: GR requests reuse the INFLIGHT/hold/deferral machinery so the guest channel release applies only on the submit's success/failure edge; hold shims preserve the channel engine type. - Counters and a work_gr state line plus a stats accessor. - Bounds are fixed: 16 pages, 8 inline records, 64 QMD words; every pointer/size checked, pool exhaustion and stale mappings fail closed. - New ABI layouts pinned with static_asserts. Compile-only change: no device test performed.
* vgsp: fix per-type VRAM type lookup and canonical FB-size encodingArthur Hanson Rasmusson7 days
| | | | | | | | | | | | | | | | | The 549d1e81 per-type VRAM change stripped an nvidia- prefix from mdev->type->sysfs_name, but sysfs_name is the registered type name verbatim; the mdev core only prefixes the type DIRECTORY with the parent driver string. Every lookup failed, so all mdevs silently fell back to 512 MiB, nvidia-vgpu-turing-1g was unreachable and available_instances capped at 1. Match sysfs_name directly in get_available, show_description and mdev_create. Also canonicalise the NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE encoder (BAR0+0x100ce0) by stripping factors of two from MAG so 512 MiB encodes 0x19 again (1 GiB 0x1a, 2 GiB 0x1b) instead of the non-canonical 0x204. Default-512M behaviour is now byte-equivalent to the known-good pre-VRAM module except max_instances=2. Module sha256 cb1724d3.
* vgsp: per-mdev emulated VRAM size (1.0 multiple mediate sizes)Arthur Hanson Rasmusson7 days
| | | | | | | | | | | | - nv_vgpu_type_info/ioctl gain vram_mb; nv_vgpu_device gains fb_emul_size bound from the mdev type at create (default 512 MiB). - New nvidia-vgpu-turing-1g type (1024 MiB); turing max_instances 1 -> 2; show_description reports the per-type framebuffer and max_instance. - Thread fb_emul_size through GSCI fb_length/region/frtsOffset, WPR2, NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE, the vidmem allocator bound and the BAR1 shadow; bar_info callback uses the per-device size. - UNTESTED at commit time: builds clean; validation blocked by the Xid 140 incident (reboot pending). See Handoff-vGPU-IO.md ADDENDUM 48.
* vgsp: hold every unreadable CE entry for the grace; delete the silent ↵Arthur Hanson Rasmusson7 days
| | | | | | | | | | pre-rescue fake An unreadable CE entry whose channel already had a decoded release VA was faked immediately and consumed with no log line, before any rescue attempt. A later pin-batch rewind then executed the skipped copy against a staging buffer the client had since refilled - the deterministic vadd input shift seen in runs 94/122/151/173b/215b, each with a silent pre-rescue fake. Now every unreadable CE entry with an expected payload is held for the bounded grace and the rescue is retried on each pass, so a translation that is still coming wins and the work runs before the release. Only an entry whose release was already delivered (the channel moved past entry_want) is consumed at once; the post-rescue fake remains the bounded, visible escape. The CE grace default moves 15000 -> 25000 ms (a translation arrived ~17 s after first examination in 215b). Under live campaign 229-236 (module 97eba5b7; green so far).
* vgsp: widen the CE pending-entry grace to 15 sArthur Hanson Rasmusson8 days
| | | | | | | | | | | A consumed entry's work is never run; if its release lands via the fallback before the entry's copies have executed, the client refills the staging slot the copies then read (observed as the deterministic one-chunk vadd input shift). Keep untranslatable CE entries pending longer so their copies run before any release reaches the client. 8-cycle pilot (141-148): zero corruption; a red-fingerprint cycle (held=1165, ring_auto=6) healed to ring_auto=26 with faked=0 and the exact checksum, where the 8 s window recorded 1 corruption in 36.
* vgsp: end-to-end CUDA acceptance in the guestArthur Hanson Rasmusson8 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The no-claim emulation path now runs a stock CUDA program end to end: device properties, cudaMalloc, a GPU-authored string kernel read back byte-for-byte, two 4 MB host-to-device copies, a 1 M-element vectorAdd executed on the physical GPU through the host bridge, and the device-to-host copy-back verified element by element. Three consecutive supervised cycles report MAIL + VADD bad=0 checksum=392344090.500000 + STATUS OK with identical input/output hashes. Two data-path correctness fixes make the transfers sound: - Once-only op execution per GPFIFO entry. The pump replays recently consumed ring entries when translation batches are injected so missed releases can land; re-executing a CE copy is not idempotent because its source is a client staging buffer that may have been refilled. Slots now record their raw entry words and a replayed entry matching that identity suppresses operations while still processing releases. - Per-page translation of virtual operands. svc_copy resolved only the first page of a VA range and walked the PA linearly; client staging ranges are frequently split (observed 195 + 61 pages), so the tail of alternating chunks was read from unrelated memory. Multi-page copies now re-resolve each 4 KB page through the trusted resolver. Also carries the earlier uncommitted emulation fixes that got the client to the launch (QMD address-window gate, counter registration persistence, 512 MiB emulated FB, bridge slot hygiene) and bounded diagnostics (sema-bigop, sema-bigcopy, bridge-in/out hashes, daemon INCHECK/OUTCHECK/dumps).
* vgsp: host CUDA bridge + sema release recovery; greeneye simulator waveArthur Hanson Rasmusson9 days
| | | | | | | | - kernel: gsp_cuda_bridge (QMD launch capture, debugfs job/out/done, param+output resolution cached from inline writes), sema drain fixes (never hold/starve a channel), GR ring autopin + counter autoreg, per-page push reads, counter-derive gate; module builds clean - tools/cuda-bridge: CUDA driver-API daemon executing mail/vadd kernels on the physical GPU, CUBB2/CBD2 v2 protocol, layout check + self-tests - tools/guest-diag + tools/cuda-ab: scanner/pin fixes, victory push-only mode - debug/risc-v-gsp-rm-vm: Phase S simulator wave (GSP device model, boot ladder, triage/re-demo harnesses, docs 30-41), GPGPU-sim scaffolding - STATE-CURRENT/docs updates
* kernel: GR context-promote bisection modes 4-17 and server-managed-ctxbuf ↵Arthur Hanson Rasmusson10 days
| | | | | | | | | | | | | | | | | | | | registry variant; complete vgsp rename; docs/tooling refresh - gsp_phys_booter: GR promote bisection modes 4-17 (two-phase zero-field VA, batched entries, hVirtMemory, bare VA, KMD SKIP_CTXBUFFER_ALLOC channel, old-interface GPU_INITIALIZE_CTX, FBMEM context buffer, UVM-faithful PA-only, PATCH/PM auxiliary promotes, server-managed no-promote path); PATCH/PM geometry queries and buffers; pre-boot SET_REGISTRY profile selection - gsp_phys_gpu: gsp_phys_rmcall_gr_promote clamp 0..17 and gsp_phys_srv_ctxbuf parameter; registry image variant with RMSetClientRMAllocatedCtxBuffer=0 - vgsp rename across kernel, scripts, tools and docs (module vgsp.ko, /sys/kernel/debug/vgsp/, vgsp-<subsystem>: log prefixes) - risc-v-gsp-rm-debugger user-facing rename and docs/CI refresh; guest-diag tool updates; README/SBOM/install/Makefile sync Live status: CE ladder and P6 guest-copy forwarding green; GR engine context commit still open (all promote shapes accepted or cleanly refused; the channel stays CTXNOTVALID) - see Handoff-vGPU-IO.md Addendum 21 (local).
* docs: add complete SBOM, ignore local deployment resources, remove stale ↵Arthur Hanson Rasmusson10 days
| | | | third-party references
* gsp-phys: freeze-safe release, boot-proof READY, and guest-wiring P2/P3/P5-wave1Arthur Hanson Rasmusson11 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Host-freeze fix bundle (validated 2/2 supervised cycles): - power unlock now latches D0/D3cold by default (new gsp_phys_repower, default 0); releasing the claim can no longer power-gate the board and hard-freeze the host on resume - bounded post-rebind readiness gate before dropping the locks; bounded D0 settle/verify before the unbind - READY means a live GSP-RM session: the async worker and the module-owned join only expose READY when init-done is seen and no unload was sent; otherwise the claim is released fail-open - FWSEC reads DMEM0/IMEM back before STARTCPU and fails fast when the staging is not visible - the claim harness leaves the board latched by default and takes --restore-power to opt back into the old restore Guest-wiring: - P2: generation-keyed fn65 static-config snapshot cache plus a default-off identity overlay (new gsp_phys_static_live) for name/short-name/VBIOS; the probe cycle runs once per backend generation at READY - P3: default-off read-only RM_CONTROL forwarding whitelist (new gsp_phys_ctrl_forward) with emulated-handle translation to the adopted server handles and full emulation fallback - P5 wave 1: default-off shadow execution of guest CE pushes on the ladder channel (new gsp_phys_work_forward) via a dedicated ordered work item; the ladder stage-4 submission is refactored into a shared bounded helper and the software release path stays authoritative Live: module-owned boot to init-done, guest smoke ALL OK 64/64 with P2/P3 enabled, 514 shadow copies observed on the physical CE; all cycles released cleanly with WPR2 down and no reboot.
* gsp-phys: mdev-owned backend lifecycle (P1)Arthur Hanson Rasmusson11 days
| | | | | | | | | | | | | | | | Add the gsp_phys_mdev_owned ownership selector (default 0: unchanged load-time module-owned claim/boot). With 1, module load claims nothing; the first mdev create starts a refcounted backend session whose claim+boot runs asynchronously from a work item, so mdev create and init_work never block. The last mdev remove releases after the emulation thread is stopped. Failures are fail-open: the backend stays OFF and the mdev keeps serving the emulation path. nv_vgpu_exit now gates the session STOPPING under the session lock, drains the emulation threads via mdev_unregister_driver(), and only then releases the claim; the module-owned path keeps its previous release position. A start while STOPPING is refused and a concurrent second stopper cannot release twice. No forwarding is added.
* gsp-phys: harden the RM transport and add the static-info probeArthur Hanson Rasmusson11 days
| | | | | | Applies the adversarial review fixes for the command-queue TX and unload RPC: the unload RPC is gated on GSP-RM init-done, debugfs fops pin the module, REG_POLL timeouts use microseconds, the host status readPtr is published, TX free space is checked, swap flags and barriers are corrected, and the legacy payload fallback is opt-in. Generalizes the transport to multi-element records and a reply-matching status-queue reader, and adds a debugfs probe that round-trips GET_GSP_STATIC_INFO (with a SET_GUEST_SYSTEM_INFO fallback), decodes the server configuration, and a read-only state snapshot file. All gated by gsp_phys_boot; the normal load path is unchanged.
* gsp-phys: command-queue TX and the GSP-RM unload RPC for clean teardownArthur Hanson Rasmusson11 days
| | | | Adds a minimal msgq producer on the command queue (element layout, checksum, sequence, dma_wmb before writePtr, doorbell) and submits the UNLOADING_GUEST_DRIVER RPC so GSP-RM shuts down and sets the scratch14 handoff bit the Booter Unload gate needs. Release attempts the RPC once before quiescing when a boot ran; on-demand testing is available through the debugfs file gsp-phys-unload-rpc while the module owns the GPU. GSP-RM processor suspend is polled on the GSP mailbox.
* gsp-phys: claim the physical GPU and stage real GSP firmware (backend rungs 1-2)Arthur Hanson Rasmusson12 days
| | | | | | | | | | | | | | | | Rung 1 (ownership): a default-off gsp_phys_gpu module param; on claim the distribution driver is released from 10de:1ed3, our pci_driver binds it, BAR0/1/3 are mapped and the falcon state is sampled; release unbinds ours and rebinds the distribution driver. Verified live: claim reads BOOT0=0x164000a1 with the falcon halted and mailboxes clear; rmmod rebinds nvidia and nvidia-smi stays healthy. Rung 2 (firmware): while the device is owned, gsp_phys_fw (default nvidia/570.211.01/gsp_tu10x.bin) is fetched with request_firmware, checked as ELF64 RISC-V, and its sections are logged (.fwimage, .fwversion, .fwsignature_tu10x). The image is held for the boot rung. The claim is default-off; the emulation path is unchanged.
* sema-svc: deliver UVM CE tracking releases without host-side pinsArthur Hanson Rasmusson12 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The runtime client's registration stalled when no guest-side pin scanner was running: the content rescue refused to run before the pool semaphore was translated (its expected payload was unlearned), and unreadable CE entries were consumed after two failed rescues ~40 ms apart, dropping the client's wait. The push pages then could not be found within the entry's grace window. - rescue: drop the learned-payload gate (the matcher only needs the channel rank and the release shape); keep unreadable CE entries pending for sema_ce_grace_ms instead of consuming after a fixed attempt count - expected payload: re-learn from the pool whenever it advanced (a deferred release could land after the first read, leaving the expectation stale) - matcher: require the expected payload exactly and validate the read-back stream carries it, so a recycled page of an older push cannot be pinned - scan: descending full-range pass (the work allocations live in the high RAM block) plus a +/-512 MB near pass around the verified push-buffer base - releases decoded with an untranslated semaphore are queued and applied when the page appears (svc_pending_add on both decode paths) - a CE push that reads as a plausible stream but carries no release for the channel is re-routed through the rescue instead of silently consumed - new module param sema_rel_recover (default off): after grace + rescue, apply the channel's expected tracking value so the client's wait clears; counter-visible as releases_recovered, distinct from sema_fake_rel Evidence: fresh boot, real releases, no host watcher, no kprobes - the six UVM CE first pushes are found by content rescue, their releases applied, and the client reaches cudaGetDeviceCount rc=0 (it then waits for the third push, which this change routes to the rescue).
* sema-svc: gate per-push/per-doorbell/RPC tracing behind default-off sema_dbgArthur Hanson Rasmusson12 days
| | | | | | | | | | | | | | | | | | A healthy run left dmesg dominated by per-operation lines (sema-push, sema-lda, sema-chan rel-apply, sema-grce, DOORBELL/BAR writes, GSPRM per-RPC lines, the teardown garbage-element stream). Introduce the module parameter sema_dbg (default 0) and route every high-frequency diagnostic through it; the finer-grained watch knobs (sema_ops_log, sema_copy_watch, sema_copy_pat, sema_copy_dst, sema_copy_dst2) only take effect while it is on. Boot stats, channel registrations, pin events and state changes stay unconditional. Also carries the per-side translation provenance (op_tr_src, printed as prov= in the destination-window watch) and the 16 KB destination window used to observe the guest's page-table writes. Verified: fresh boot + full cdt2 smoke test (64/64, ALL OK) leaves a 520-line dmesg with zero per-push/per-doorbell/per-RPC lines.
* sema-svc: destination-keyed copy watch (dump page-table writes)Arthur Hanson Rasmusson12 days
| | | | | | sema_copy_dst=dumps the source bytes of every copy whose destination falls in the given page, so the 32-byte page-directory updates the guest writes into vidmem can be read directly and their entry encoding learned.
* sema-svc: run CE work before its release, grace unreadable CE entries, ↵Arthur Hanson Rasmusson12 days
| | | | | | | | | | | | | | | | | | | payload-pattern audit - CE LAUNCH_DMA releases are now applied after the push's collected work runs: the client reads copied data as soon as it observes the release, so release-first let cuMemcpyDtoH observe a copy that had not executed. - Unreadable CE entries stay pending for a grace window (sema_ce_grace_ms, default 8s) before the release fallback consumes them, so a translation that lands within a service pass lets the push be decoded and its work executed instead of being dropped. - sema_copy_pat matches an 8-byte value against every copy's src/dst first word and scans decoded pushes for it, naming the submission that carries a known payload regardless of size/encoding. - sema-dma-skip logs transfer-shaped launches that collect no op; op log lines carry the channel handle; LAUNCH_DMA inventory follows OPS_LOG. - A real release application now records the release VA, so decoded pushes no longer trigger a spurious fake release.
* sema-svc: sema_vidmem_find pattern search (CE data-path ground truth)Arthur Hanson Rasmusson12 days
|
* sema-svc: sema_copy_watch (size-keyed src/dst byte audit for the CE data path)Arthur Hanson Rasmusson12 days
|
* sema-svc: sema_vidmem_dump param to inspect emulated vidmem (CE data-path audit)Arthur Hanson Rasmusson12 days
|
* sema-svc: sema_ops_log param (default 8) to audit executed CE operands; ↵Arthur Hanson Rasmusson12 days
| | | | run_cycle OPS_LOG knob
* gsprm: reply-latency logging + param dump cap; guest-diag: CDT_PAUSE, ↵Arthur Hanson Rasmusson13 days
| | | | watcher reaping, wider CE stream window
* sema-svc: sema_skip_ops parameter (apply releases without running pushed ↵Arthur Hanson Rasmusson13 days
| | | | memsets)
* kernel: grace window for untranslatable GR entries; tools: coalesce window ↵Arthur Hanson Rasmusson13 days
| | | | | | | | | | | | | | | | | pin output The first GR window pin landed ~2 s after the pump consumed the freshly created channels' GPFIFO entries on the first failed read, so the pushes (and the tracking-semaphore releases they carry) were lost. GR entries with an unresolvable push page now stay pending for sema_gr_grace_ms (default 8 s) before the stale-entry consume; a pin landing in that window makes the entry readable and it executes normally. The completion counter is still published from put at the end of every pass, so the client's counter wait is not delayed. guest_pmap_win.py coalesces contiguous VA+PA pages into run lines, so a 15k-page window transfers as ~200 lines instead of ~15k and the pin batch lands within a second of the pages appearing.
* sema-svc: optional CE release fallback for unreadable pushes (sema_fake_rel)Arthur Hanson Rasmusson13 days
|
* sema: fix host stack-overflow hang; robust VA resolution; dispatcher lock fixArthur Hanson Rasmusson13 days
| | | | | | | | | | | | | | | | | | | | | | | - 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.
* sema: add walk_probe - trace the page-table walk for a VAArthur Hanson Rasmusson14 days
| | | | | | | | | | 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.
* sem: run GR channels - accept CE methods on subchannel 0, discover GR ringsArthur Hanson Rasmusson2026-09-28
| | | | | | | | | | | | | | | | | | | | | - 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).
* kernel: add a channel-table dump param; tools: fix memprobe --max parsingArthur Hanson Rasmusson2026-09-26
|
* kernel: aperture-aware pinning and UVM CE channel USERD discoveryArthur Hanson Rasmusson2026-09-24
| | | | | | | | | | | | | | | 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.
* kernel: completion-event hints and GSP-RM state introspectionArthur Hanson Rasmusson2026-09-24
| | | | | | | | | | | | | - 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
* kernel: validate learned semaphore maps and post guest GPU eventsArthur Hanson Rasmusson2026-09-24
| | | | | | | | | | | | | | | - 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
* kernel: track channels and execute host-class pushed workArthur Hanson Rasmusson2026-09-23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* kernel: service BAR0/BAR1 region reads and extended config-space writesArthur Hanson Rasmusson2026-09-23
| | | | | | | | | | | | | 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.
* kernel: apply BAR0/BAR1 region writes to the emulated shadowsArthur Hanson Rasmusson2026-09-23
| | | | | | | | | | The mdev's region write handler returned success without touching the BAR0 shadow or the trap table, so register writes that arrive through the VFIO region path (QEMU-trapped accesses) never took effect. A fresh guest then polled a register that never changed and spun forever in cuInit (QEMU log: vfio_region_write(mdev:region0+0x88704) failed: Resource temporarily unavailable). Route those writes to the BAR0 shadow/trap handler and mirror BAR1 writes into the emulated vidmem backing.
* kernel: execute pushed CE work (PTE memsets, copies) and track semaphoresArthur Hanson Rasmusson2026-09-23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The progress service now decodes push buffers as method streams and performs the work the driver pushes, not just the tracking semaphore: - C5B5 method decoder: SET_REMAP_CONST_A/B + COMPONENTS + OFFSET_OUT + LINE_LENGTH_IN + LAUNCH_DMA = memset (into vidmem or guest RAM); OFFSET_IN + OFFSET_OUT + LAUNCH_DMA = copy; SET_SEMAPHORE_A/B/PAYLOAD + LAUNCH_DMA = release. Contiguous method runs (count 2/4) are applied in full - OFFSET_IN/OUT arrive as one run. - Pushes span page boundaries, so pages are decoded as method streams without a start marker. Collected operations execute only when the push's release is reached and still pending (payload ahead of the semaphore), so recycled buffers replaying old pushes are skipped and their stale memsets cannot overwrite newer state. - VA->PA map is first-wins: stale copies of freed allocations and unrelated adjacent u64 pairs produced bogus entries that hijacked a good mapping and sent semaphore writes to the wrong page. - dump_guest module parameter (hex dump of guest PA, kthread via completion; kthread_stop before the thread runs loses the work). With this the guest no longer stalls in uvm_tracker_wait and no longer oopses in the UVM path; the failure moved to a userspace segfault inside libcuda (NULL-0x38) after the driver's page allocations. Also add tools/cuda-ab: run one deterministic CUDA workload on the host (bare metal oracle) and in the guest, then compare the stable result lines. The binary links the CUDA runtime statically so the guest only needs the driver's libcuda.so.
* kernel: semaphore service forward-jump completion, stats, sema_probeArthur Hanson Rasmusson2026-09-23
| | | | | | | | | Relax the in-order rule to forward progress (payload > current), with the jump bounded and counted: UVM tolerates forward jumps up to 2M (2 * UVM_CHANNEL_NUM_GPFIFO_ENTRIES_MAX), and push buffers are recycled so intermediate pushes can be missed. Add miss/stale/jump counters to the rebuild log and a sema_probe module parameter to dump the service's map entry and live slot values for a GPU VA (diagnostics for tracker stalls).
* Open-IOV: initial public releaseOpen-IOV2026-09-23
Open-IOV virtualizes NVIDIA GPUs so that unmodified guest drivers run with real GPU functionality - CUDA first, 3D and video to follow - on unmodified hosts, without a proprietary vGPU license and without patching any driver, firmware or hypervisor. Core principle: emulate the interface, pass through the work. kernel/ open-iov-vfio.ko - host VFIO mdev driver: virtual GPU device (PCI config space, BAR shadows, MSI-X), GSP boot emulation, GSP-RM message-queue/RPC emulation, memory model (GPU-VA to guest-PA discovery) and the semaphore-completion service that advances guest UVM progress. userspace/ libiov.so management API and examples. tools/ guest diagnostics, firmware analysis wrappers, RM probes. scripts/ stack manager, VM harness, build/load/test automation. config/ hardware/version profiles (the portability surface). docs/ documentation tree - start at docs/README.md. wiki/ long-form firmware and protocol deep dives. Status: initialization works end to end for a stock 570.144 Linux guest on Turing (TU104): driver probe, nvidia-smi, the full GSP-RM control battery, object creation and the early CUDA/UVM start-up path. GPU work forwarding - the step that makes CUDA kernels execute on real hardware - is the active work item; see docs/04-implementation/01-known-knowns-and-unknowns.md. License: BSD-3-Clause for the project; GPL-2.0 for kernel modules that link GPL-only kernel interfaces. See LICENSE and docs/09-reference/legal-and-licensing.md.