summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/03-architecture/11-physical-backend-guest-wiring.md106
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