diff options
Diffstat (limited to 'docs/03-architecture/11-physical-backend-guest-wiring.md')
| -rw-r--r-- | docs/03-architecture/11-physical-backend-guest-wiring.md | 106 |
1 files changed, 69 insertions, 37 deletions
diff --git a/docs/03-architecture/11-physical-backend-guest-wiring.md b/docs/03-architecture/11-physical-backend-guest-wiring.md index 7db80dc..7328800 100644 --- a/docs/03-architecture/11-physical-backend-guest-wiring.md +++ b/docs/03-architecture/11-physical-backend-guest-wiring.md @@ -1,15 +1,17 @@ # Physical Backend Guest Wiring: Driving the Guest-Facing Emulation from the Live GSP-RM Session -> **Status: P0-P5(w1) implemented; P6a guest-page reachability proven live -> (2026-10-02).** The backend API skeleton +> **Status: P0-P5(w1) implemented; P6a guest-page reachability and P6b wave-1 +> guest-copy forwarding proven live (2026-10-02).** The backend API skeleton > (P0), the mdev-owned lifecycle (P1, fail-open; the async FWSEC boot on that > path is an open defect off the critical path), the static-config identity > overlay (P2, verified live in an A/B run), the read-only control > forwarding whitelist (P3, default off, verified live: ok=22/fallback=2, -> smoke `ALL OK` 64/64) and the P5 wave-1 guest-submission shadow execution +> smoke `ALL OK` 64/64), the P5 wave-1 guest-submission shadow execution > (default off, verified live: 514 real CE copies during a green guest smoke -> `ALL OK` 64/64) are in the tree. The physical -> backend itself is live: the module-owned +> `ALL OK` 64/64) and the P6b wave-1 guest-copy forwarding through +> module-built GMMU scratch mappings (default off, verified live: req=42 +> ok=42 verify_ok=42, 503 ladder shadow copies also run) are in the tree. +> The physical backend itself is live: the module-owned > GSP-RM completes initialization on the real TU104, serves the full > static-config reply, and shuts down gracefully. The host resource-manager > client ladder has since allocated memory, a virtual-address-space object with @@ -102,10 +104,12 @@ ### 0.3 The gap -The two planes now meet only at the lifecycle seam (P0/P1, mdev-owned -claim/release) and the static-config identity overlay (P2); controls, objects, -FB geometry, engine caps and work are still emulated. The remaining bridge -must be added at the reply point `gsp_rm_send()`, the inbound dispatch point +The two planes now meet at the lifecycle seam (P0/P1, mdev-owned +claim/release), the static-config identity overlay (P2), the read-only control +whitelist (P3) and, for eligible CE copies, the P6b wave-1 scratch-mapped work +path; objects, FB geometry, engine caps, real guest page tables and +hardware-primary release are still emulated. The remaining bridge must be +added at the reply point `gsp_rm_send()`, the inbound dispatch point `gsp_rm_handle_element()`, and the work-plane seams (see ยง2). --- @@ -212,8 +216,8 @@ Legend: **L** = live backend, **E** = existing emulation, **H** = hybrid. | 6 | `GSP_RM_ALLOC` (103) | echo request + `NV_OK`; channels/events registered locally (`:2322`) | **H** - echo for emulation-only classes; forward selected classes (root/device/subdevice, then channel/memory) once a guest<->server handle map exists; always keep local side effects | `gsp_rm_handle_rm_alloc` `:2322` | | 7 | `GSP_RM_CONTROL` (76) | ~25 static per-cmd handlers; unknown -> zeroed success (`:2611`, default `:2807`) | **H** - whitelist of side-effect-free queries goes live with emulation fallback; vGPU-specific controls stay **E** (`COPY_SERVER_RESERVED_PDES` `:2647`, `PROMOTE_FAULT_METHOD_BUFFERS` `:2654`) | `gsp_rm_handle_rm_control` `:2611`; new forward helper before the switch | | 8 | `GSP_RM_FREE` (10) | echo + retire channel/events (`:2882`) | **H** - forward when the object was backend-allocated; always retire local bookkeeping | `gsp_rm_handle_free` `:2882` | -| 9 | `SET_PAGE_DIRECTORY` (54) | recorded for translation + SUCCESS (`:2975`) | **H** - recording stays **E**; forwarding to the real MMU is P6b and guest pages are GPU-DMA-reachable on the reference host (P6a status below; page-table pre-build required) | `gsp_rm_handle_set_page_directory` `:2975` | -| 10 | `UNSET_PAGE_DIRECTORY` (79) | record remove + SUCCESS (`:3063`) | **H** - same gate as #9 (reachability resolved; pre-build required) | `:3063` | +| 9 | `SET_PAGE_DIRECTORY` (54) | recorded for translation + SUCCESS (`:2975`) | **H** - recording stays **E**; forwarding to the real MMU is P6c and guest pages are GPU-DMA-reachable on the reference host (P6a status below; page-table pre-build required). P6b wave 1 executes eligible copies without forwarding page-directory state, through module-built scratch page tables | `gsp_rm_handle_set_page_directory` `:2975` | +| 10 | `UNSET_PAGE_DIRECTORY` (79) | record remove + SUCCESS (`:3063`) | **H** - same gate as #9 (real page-directory forwarding is P6c; reachability resolved, pre-build required) | `:3063` | | 11 | `UPDATE_BAR_PDE` (70) | SUCCESS ack (`:3144`) | **E** now; **L** only when BAR1 is backed by real VRAM | `:3144` | | 12 | `UNLOADING_GUEST_DRIVER` (47) | SUCCESS ack (`:3155`) | **E** - the guest's own shutdown; the real session's shutdown is host-driven on backend stop (`gsp_phys_gpu.c:909`) | `:3155` | | 13 | default/unknown | generic SUCCESS (`:3169`) | **E** (fail-safe: never invent a live forward for an unknown function) | `:3169` | @@ -231,7 +235,7 @@ Legend: **L** = live backend, **E** = existing emulation, **H** = hybrid. | # | Guest-visible thing | Today | Target | Change point | |---|---|---|---|---| | 17 | GSP falcon boot regs (FWSEC/Booter/RISCV/WPR2), SW interrupt tree, MMU invalidate, L2 flushes | emulated auto-complete (`gsp_emulation.c:193-452`) | **E always** - the two GSP sessions are intentionally independent; guest boot must never depend on the physical session | `gsp_emu_poll_boot` `:193` | -| 18 | Guest VF doorbell `0x88704` | software pump (`main.c:826` -> `gsp_sema_service_doorbell` `:6369`) | **H** - pump classifies each push: pure state/release stays software; engine work is forwarded (P5) | `svc_pump_channels` `gsp_sema_service.c:5019`, `svc_decode_stream` `:2802` | +| 18 | Guest VF doorbell `0x88704` | software pump (`main.c:826` -> `gsp_sema_service_doorbell` `:6369`) | **H** - pump classifies each push: pure state/release stays software; eligible CE copies are shadow-forwarded to hardware (P5 host-buffer mode, P6b wave 1 guest operands) | `svc_pump_channels` `gsp_sema_service.c:5019`, `svc_decode_stream` `:2802` | | 19 | BAR0/BAR1/BAR3 shadows, PRAMIN window | host-RAM shadows (`bar_emulation.c:180`, `main.c:1205`) | **E** until real VRAM forwarding (P6) | `nv_vgpu_bar_emul_*`, `nv_vgpu_vfio_dev_mmap` | | 20 | legacy doorbell/shared-mem RPC class (`GSP_RPC_*`) | internal emulation client thread (`gsp_emulation.c:458-620`, `:674-694`) | **E / disable when READY** - not part of the guest physical-path protocol; gate it off in backend mode to avoid intercepting stray writes | `gsp_emu_thread_fn` `:674` | @@ -482,8 +486,9 @@ go-ahead, recovery plan, pstore, never unattended module-owned ladder copy; the software release path stays authoritative and no guest memory/VA is touched. Live: guest smoke GREEN `ALL OK` 64/64 with 514 real CE copies (194 requests coalesced/dropped while one was in flight, - 0 refusals, 0 timeouts). Wave 2 (hardware-primary release relay) and P6 - remain. + 0 refusals, 0 timeouts). The P6b wave-1 guest-copy forwarding has since + landed (P6 status below). Wave 2 (hardware-primary release relay) and the + real guest-page-table path (P6c) remain. * **Scope:** the debugfs ladder's real-submission half is **done** (cycle 25: channel allocates, page directory commits, `REAL COPY OK` on the physical CE in VA mode). The remaining work: bind each guest CE/GR channel to a real @@ -509,16 +514,16 @@ go-ahead, recovery plan, pstore, never unattended * **Rollback:** per-channel `forward=0`; software pump is untouched. ### P6 - Guest memory into the real MMU (end state: guest submission on hardware) -* **Status (2026-10-02): P6a - guest-page reachability proven live.** The - physical GPU's IOMMU group is an identity domain on the reference host and - the mediated device registers as an emulated-IOMMU VFIO device, so its - type-1 container keeps guest DMA mappings privately and no kernel - `iommu_domain` exists for it: `iommu_iova_to_phys` cannot translate guest - GPAs. Guest RAM is therefore backed by a QEMU shared file - (`memory-backend-file,share=yes,prealloc=on`); the module opens it and - translates GPA->HPA through the file page cache (`read_cache_page` + - `page_to_phys` + `pfn_valid`) behind the active-mdev gate, under the new - default-off `gsp_phys_guest_mem` parameter and write-only +* **Status (2026-10-02): P6a guest-page reachability and P6b wave 1 + (guest-copy forwarding, shadow mode) proven live.** P6a: the physical GPU's + IOMMU group is an identity domain on the reference host and the mediated + device registers as an emulated-IOMMU VFIO device, so its type-1 container + keeps guest DMA mappings privately and no kernel `iommu_domain` exists for + it: `iommu_iova_to_phys` cannot translate guest GPAs. Guest RAM is therefore + backed by a QEMU shared file (`memory-backend-file,share=yes,prealloc=on`); + the module opens it and translates GPA->HPA through the file page cache + (`read_cache_page` + `page_to_phys` + `pfn_valid`) behind the active-mdev + gate, under the default-off `gsp_phys_guest_mem` parameter and write-only `gsp-phys-guest-ram`/`gsp-phys-guest-gpa` debugfs controls (ladder trigger cases 6 host->guest write, 7 guest->host read, 8 fresh-slot PTE self-test). On the reference q35 4 GiB guest, GPA equals file offset below 4 GiB and @@ -529,12 +534,36 @@ go-ahead, recovery plan, pstore, never unattended TLB-invalidate path yet). **Live:** the physical copy engine copied 4 KiB from a real guest RAM page into a module buffer (G2H) and back into the same page (W2G), semaphore released; the guest process observed the write - in its own page; the driver-API smoke stayed green (`ALL OK` 64/64) and - release stayed latched (distribution driver rebound, protected region down, - exactly 5 power-domain locks intentionally held, 0 rail cycles, no reboot); - the informational PTE self-test passed. **Remaining (P6b):** page-directory - shadowing, real guest channels and push forwarding - guest-submission - forwarding is not implemented yet. + in its own page; the driver-API smoke stayed green (`ALL OK` 64/64); the + informational PTE self-test passed. **P6b wave 1:** with + `gsp_phys_work_forward=1 gsp_phys_guest_mem=1` the sema service captures + the first eligible copy per push from the software path's own resolved + operands (the real push shapes: a physical emulated-VRAM destination plus a + virtual source and vice versa, over a mix of sysmem guest RAM and + emulated-VRAM shadow pages), resolves each side to a host physical address + (guest RAM through the shared-file page cache; shadow pages through the + vmalloc-to-physical mapping of the emulated VRAM shadow), maps both onto + fresh module-built GMMU scratch slots and submits a real copy-engine copy + on the module-owned channel; any miss falls back to the existing + ladder-buffer shadow copy and the software pump stays authoritative. **PTE + fetch-line rule (learned live):** the engine caches PTE fetches at 128-byte + granularity and there is no invalidate path, so a scratch copy pair + consumes one whole 128-byte line (16 PTEs) from a pool of 16 zeroed + page-table pages built before the first engine access: capacity 512 pairs + per boot, and a line is never reused within a boot. **Live:** `req=42 ok=42 + verify_ok=42 verify_fail=0 fallback=0 resolve_fail=0 pool_exhausted=0 + refused=0`, with 503 ladder shadow copies also run; the guest smoke stayed + green (`ALL OK` 64/64) and release stayed latched (distribution driver + rebound, protected region down, exactly 5 power-domain locks intentionally + held, 0 rail cycles, no reboot). Shadow-mode limits: the software copy + already applied the same bytes, so the hard evidence is acceptance of the + translated-HPA submission, the semaphore release and host-side + data-consistency verification (`verify_ok`); a late hardware write can + theoretically race guest reuse inside the submit window. **Remaining:** + wave 2 (hardware-primary release relay) and P6c (real page-directory + shadowing, real guest channels and push forwarding with guest page tables + in the real MMU) - guest-submission forwarding through the real guest page + tables is not implemented yet. * **Scope:** map guest page-table pages/records so the physical GPU can DMA them; forward `SET_PAGE_DIRECTORY` (`gsp_rm_emulation.c:2975`) to the real server; allocate real memory objects for guest allocations (fn4 with real @@ -583,13 +612,16 @@ go-ahead, recovery plan, pstore, never unattended no object teardown (`:5123` comments); `UNLOADING_GUEST_DRIVER` + rmmod is the only recovery. 4. **Wrong-page-table / wrong-doorbell writes.** No forwarding seam may - submit engine work or program page tables until the P6 page-table - population path is proven end to end; guest-page reachability itself is - resolved on the reference host (P6a), so wrong-page-table writes remain - the top risk. Preserve: queue header validation in - `gsp_phys_queue_tx_submit()` (`booter:2983`), free-space check (`:3032`), - status-record validation (`booter:2554`), sequencer address validation - (`booter:1800`), stage-4 token/bounds guards (`booter:4969-4999`). + program guest-derived page tables into the real MMU until the P6c + page-table population path is proven end to end; the P6b wave-1 path + submits engine work only through module-built scratch page tables mapping + already-resolved host pages and never reuses a fetch line in a boot. + Guest-page reachability itself is resolved on the reference host (P6a), + so wrong-page-table writes remain the top risk. Preserve: queue-header + validation in `gsp_phys_queue_tx_submit()` (`booter:2983`), free-space + check (`:3032`), status-record validation (`booter:2554`), sequencer + address validation (`booter:1800`), stage-4 token/bounds guards + (`booter:4969-4999`). 5. **Guest status-queue invariants.** Strict sequence/wrap/checksum and multi-element records; `gsp_rm_send()` (`:452`) is the only writer and must not be called while holding `gsp_phys_rm_lock` or waiting on the |
