Difference between revisions of "The Guest Stack and CUDASW"
m (Fix repository links: point to the cgit tree URLs) |
m (2026-10-30 wiki refresh: goals, GSP, graphics, performance, interfaces) |
||
| Line 5: | Line 5: | ||
<blockquote>'''Scope.''' What runs inside the guest, how the NVIDIA software layers sit on top of the device, and what the unmodified guest driver expects from the emulated GPU. Canonical source: [https://git.vgpu.io/open-iov.git/tree/docs/03-architecture/02-guest-stack-and-cudasw.md <code>../docs/03-architecture/02-guest-stack-and-cudasw.md</code>]; the docs tree wins on disagreement with this page.</blockquote> | <blockquote>'''Scope.''' What runs inside the guest, how the NVIDIA software layers sit on top of the device, and what the unmodified guest driver expects from the emulated GPU. Canonical source: [https://git.vgpu.io/open-iov.git/tree/docs/03-architecture/02-guest-stack-and-cudasw.md <code>../docs/03-architecture/02-guest-stack-and-cudasw.md</code>]; the docs tree wins on disagreement with this page.</blockquote> | ||
<blockquote>Status: 2026-10- | <blockquote>Status: 2026-10-30, tree <code>master @ b4930168</code>. Tags: <code>[live]</code> observed with the stock guest driver; <code>[gated]</code> implemented default-off behind supervised gates; <code>[wall]</code> known blocking limit; <code>[target]</code> designed, not built; <code>[planned]</code> roadmap.</blockquote> | ||
== 1. Vocabulary: what "CUDASW" means here == | == 1. Vocabulary: what "CUDASW" means here == | ||
| Line 20: | Line 20: | ||
nvidia.ko (RM + UVM + modeset)</pre> | nvidia.ko (RM + UVM + modeset)</pre> | ||
Adjacent members of the family: '''libnvidia-ptxjitcompiler''' (PTX→SASS JIT — usually "just works" once the driver initializes), '''libnvidia-fatbinaryloader / nvrtc''', '''UVM''' (<code>nvidia_uvm.ko</code> — [[UVM in the Guest|<code>UVM-in-the-Guest.md</code>]]), the '''graphics stack''' (<code>libGLX_nvidia</code>, <code> | Adjacent members of the family: '''libnvidia-ptxjitcompiler''' (PTX→SASS JIT — usually "just works" once the driver initializes), '''libnvidia-fatbinaryloader / nvrtc''', '''UVM''' (<code>nvidia_uvm.ko</code> — [[UVM in the Guest|<code>UVM-in-the-Guest.md</code>]]), the '''graphics stack''' (<code>libGLX_nvidia</code>, the driver's GL core, the Vulkan ICD, <code>nvidia_modeset</code>/<code>nvidia_drm</code> — partially live on the emulated vGPU: Xorg/GLX run, the engine executes GL method streams, and the Vulkan pipeline runs end to end; rendered pixels are the frontier — [[Graphics Execution|<code>Graphics-Execution.md</code>]]) and the '''video stack''' (NVENC/NVDEC) — roadmap. | ||
== 2. Layering rules the emulation must respect == | == 2. Layering rules the emulation must respect == | ||
| Line 92: | Line 92: | ||
→ faults, completions, events</pre> | → faults, completions, events</pre> | ||
Context creation and the full CUDA driver-API smoke | Context creation and the full CUDA driver-API smoke pass (<code>ALL OK</code>, copies matched) [live], and guest kernel launches now '''execute on the physical engine''' with engine-authored completions relayed to the guest [live]. The backend is a '''module-owned GPU running its real GSP firmware as the resource-manager server''' ([[Physical GPU Backend and Guest Wiring|<code>Physical-GPU-Backend.md</code>]]). The leading edge is the staged-transfer class, the every-boot acceptance campaign and per-guest isolation ([[The Execution Frontier|<code>Execution-Frontier.md</code>]]). Graphics work reuses the same submission machinery on its own frontier: the X server and GLX run, the engine executes GL method streams, and the Vulkan pipeline runs end to end; rendered pixels are the wall ([[Graphics Execution|<code>Graphics-Execution.md</code>]]). | ||
== 5. What the guest expects from the device, per phase == | == 5. What the guest expects from the device, per phase == | ||
| Line 138: | Line 138: | ||
== 7. Windows guests == | == 7. Windows guests == | ||
Windows brings its own kernel-mode driver, <code>nvlddmkm.sys</code>, which uses the same underlying GSP device/firmware model but different host interfaces (WDDM, MSI-X semantics, ROM/VBIOS quirks). The emulation target is the same: satisfy the firmware interface, forward the work. Windows support is a roadmap item ([[Hardware and Software Matrix|<code>Hardware-Software-Matrix.md</code>]]) [planned], and the design goal is that no Windows-specific code lives in the guest. | Windows brings its own kernel-mode driver, <code>nvlddmkm.sys</code>, which uses the same underlying GSP device/firmware model but different host interfaces (WDDM, MSI-X semantics, ROM/VBIOS quirks). The emulation target is the same: satisfy the firmware interface, forward the work. Windows support is a roadmap item ([[Hardware and Software Matrix|<code>Hardware-Software-Matrix.md</code>]]) [planned], and the design goal is that no Windows-specific code lives in the guest. The Windows/DirectX path — WDDM, the Direct3D user-/kernel-mode drivers, and what a bring-up requires — is described on [[DirectX|<code>DirectX.md</code>]]. | ||
== 8. Compatibility notes for versions == | == 8. Compatibility notes for versions == | ||
Latest revision as of 17:06, 30 October 2026
An absence of critical technical documentation has historically slowed growth and adoption of developer ecosystems for GPU virtualization.
This CC-BY-4.0 licensed content can either be used with attribution, or used as inspiration for new documentation, created by GPU vendors for public commercial distribution as developer documentation.
Where possible, this documentation will clearly label dates and versions of observed-but-not-guaranteed behaviour vs. vendor-documented stable interfaces/behaviour with guarantees of forward or backward compatibility.
The Guest Stack and CUDASW
Scope. What runs inside the guest, how the NVIDIA software layers sit on top of the device, and what the unmodified guest driver expects from the emulated GPU. Canonical source:
../docs/03-architecture/02-guest-stack-and-cudasw.md; the docs tree wins on disagreement with this page.
Status: 2026-10-30, tree
master @ b4930168. Tags:[live]observed with the stock guest driver;[gated]implemented default-off behind supervised gates;[wall]known blocking limit;[target]designed, not built;[planned]roadmap.
1. Vocabulary: what "CUDASW" means here
CUDASW is the family of NVIDIA software components that sit between an application and the GPU driver. The project's compatibility target is the whole stack, not one library:
application │ CUDA API (runtime) libcudart.so ─────────────────────────────┐ runtime: device/stream/event │ CUDA driver API │ management, kernel launch libcuda.so ───────────────────────────────┤ driver: contexts, modules, │ ioctls │ memory, channel submission /dev/nvidia* ─────────────────────────────┘ nvidia.ko (RM + UVM + modeset)
Adjacent members of the family: libnvidia-ptxjitcompiler (PTX→SASS JIT — usually "just works" once the driver initializes), libnvidia-fatbinaryloader / nvrtc, UVM (nvidia_uvm.ko — UVM-in-the-Guest.md), the graphics stack (libGLX_nvidia, the driver's GL core, the Vulkan ICD, nvidia_modeset/nvidia_drm — partially live on the emulated vGPU: Xorg/GLX run, the engine executes GL method streams, and the Vulkan pipeline runs end to end; rendered pixels are the frontier — Graphics-Execution.md) and the video stack (NVENC/NVDEC) — roadmap.
2. Layering rules the emulation must respect
- The kernel driver is the contract. Everything above it talks to
nvidia.kothrough stable ioctls, memory mappings and/dev/nvidia*nodes. If the kernel driver initializes and behaves, user space follows. - User space is opaque to us. We never intercept user-space APIs. All hooks are in the device model (host side) or in the hardware interface the kernel driver sees (guest side).
- Version skew is normal. Driver version, CUDA version and firmware version are three independent axes. The compatibility target is "the driver family that matches the emulated firmware profile", with configuration-driven adaptation for others.
3. Kernel-driver anatomy (what the guest brings)
| Component | Role | Why it matters here |
|---|---|---|
| RM core | object model, handles, locks, device lifecycle | drives the GSP boot and the whole RPC/control surface |
Resource server (resserv)
|
allocates/tracks objects, memory, channels | the client half of the client/server RM split |
Memory manager (memmgr)
|
VRAM/sysmem objects, mappings, page tables | the guest expects the GSP to own page-table leaves for its VA spaces |
| FIFO/runlist | channels, TSGs, GPFIFO, USERD, doorbells | where the guest's work is submitted |
| GSP client | message queues, RPC transport, event handling | the interface we emulate |
| UVM | unified memory, page faults, channel manager | starts early in CUDA init, extremely stateful |
nvidia_modeset / nvidia_drm
|
display / DRM | needed later for graphics |
| CE / GR HALs | engine programming | needed to execute forwarded work |
4. Driver initialization vs runtime
Understanding this split is the key to debugging.
Initialization (boot/probe) — deterministic, mostly one-shot; where compatibility is won or lost [live]:
PCI probe → identify GPU from config space and BAR0 registers → boot the GSP (our emulated handshake) → read static configuration (device info tables, FB/BUS info, VBIOS, clocks) → create root client/device/subdevice objects → initialize RM subsystems (interrupts, FIFO, memory, GMMU, PMU) → expose /dev/nvidia* and register with the kernel
The actual message/control IDs observed at each step are listed in Driver-Lifecycle-Field-Guide.md.
Runtime (per-process, per-context) — driven by user-space workloads; where execution is won or lost:
open /dev/nvidia* → cuInit → UVM registration (per process) → cuCtxCreate → object/allocations → memory maps → channel creation + push buffers + semaphores → kernel launches (GR) / copies (CE) / memops → faults, completions, events
Context creation and the full CUDA driver-API smoke pass (ALL OK, copies matched) [live], and guest kernel launches now execute on the physical engine with engine-authored completions relayed to the guest [live]. The backend is a module-owned GPU running its real GSP firmware as the resource-manager server (Physical-GPU-Backend.md). The leading edge is the staged-transfer class, the every-boot acceptance campaign and per-guest isolation (Execution-Frontier.md). Graphics work reuses the same submission machinery on its own frontier: the X server and GLX run, the engine executes GL method streams, and the Vulkan pipeline runs end to end; rendered pixels are the wall (Graphics-Execution.md).
5. What the guest expects from the device, per phase
| Phase | Guest action | Device/firmware expectation |
|---|---|---|
| Probe | config space reads, BAR sizing, MSI-X capability | a plausible TU104-family PCIe GPU |
| Boot | BAR0 register writes, WPR setup, firmware boot sequence | GSP boots, booter completes, "GSP init done" |
| Config | RPC GET_GSP_STATIC_INFO, device tables, VBIOS reads
|
consistent, self-describing tables |
| RM init | GSP_RM_CONTROL battery (FB/BUS/CE/INTR/GMMU/...)
|
correct shapes and plausible values |
| Objects | GSP_RM_ALLOC (root, device, subdevice, vaspace, channel, CE objects)
|
success + correct handles/params |
| Runtime | allocs/controls for maps and channels; pushes | executed work, semaphores, faults |
The RPC surface is described in GSP-and-GSP-RM.md and RPC-Message-Format.md; the boot handshake in WPR-Management.md.
6. Why user-space-only interception does not work
Two hard-won facts from this project:
libcudaissues rawsyscallinstructions, so anLD_PRELOADshim aroundioctl()sees nothing. Observing CUDA's kernel calls requires aptrace-based tracer (PTRACE_SYSCALL + PTRACE_GET_SYSCALL_INFO), as the project's diagnostics do.- **The CUDA driver talks to the kernel driver, not to the device.** All device interaction happens in
nvidia.ko. This is good news: the emulation boundary is a small set of kernel-side interfaces (MMIO, DMA, interrupts, the GSP protocol) rather than a large user-space API surface.
7. Windows guests
Windows brings its own kernel-mode driver, nvlddmkm.sys, which uses the same underlying GSP device/firmware model but different host interfaces (WDDM, MSI-X semantics, ROM/VBIOS quirks). The emulation target is the same: satisfy the firmware interface, forward the work. Windows support is a roadmap item (Hardware-Software-Matrix.md) [planned], and the design goal is that no Windows-specific code lives in the guest. The Windows/DirectX path — WDDM, the Direct3D user-/kernel-mode drivers, and what a bring-up requires — is described on DirectX.md.
8. Compatibility notes for versions
- The guest's driver and the emulated firmware profile must agree on the RPC message versions. The guest negotiates these at start-up (
SET_GUEST_SYSTEM_INFOcarries the VGX/RPC version); the emulation answers with a profile that matches the driver family in use. - CUDA versions ride on driver versions; the test matrix tracks (driver, CUDA, firmware) triples (
../docs/05-operations/01-performance-correctness-security.md).
9. Related documentation
../docs/03-architecture/02-guest-stack-and-cudasw.md— canonical chapter.Host-Module.md— the other side of the boundary.UVM-in-the-Guest.md,CUDA-Userspace-Driver.md— user-space driver internals.Driver-Lifecycle-Field-Guide.md,GSP-and-GSP-RM.md— the observed protocol reality.Physical-GPU-Backend.md,Execution-Frontier.md— where guest work is headed.