diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-02 02:07:52 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-02 02:07:52 -0400 |
| commit | c886760efda836b060fee03bfce852f16f04b5b8 (patch) | |
| tree | dd9016dac7ffa33a383505d68d46af4df2b4bbf7 /kernel/gsp_phys_booter.h | |
| parent | 3293b014abac3e7bf492c50aba9b28a9adbb458e (diff) | |
| download | open-iov-c886760efda836b060fee03bfce852f16f04b5b8.tar.gz open-iov-c886760efda836b060fee03bfce852f16f04b5b8.zip | |
gsp-phys: freeze-safe release, boot-proof READY, and guest-wiring P2/P3/P5-wave1
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.
Diffstat (limited to 'kernel/gsp_phys_booter.h')
| -rw-r--r-- | kernel/gsp_phys_booter.h | 76 |
1 files changed, 72 insertions, 4 deletions
diff --git a/kernel/gsp_phys_booter.h b/kernel/gsp_phys_booter.h index 15068ff..2c24524 100644 --- a/kernel/gsp_phys_booter.h +++ b/kernel/gsp_phys_booter.h @@ -26,6 +26,15 @@ bool gsp_phys_boot_dryrun_enabled(void); /* True when either boot parameter is set (forces the stage-3b layout). */ bool gsp_phys_boot_requested(void); +/* + * Live-session accessor: true only when the real GSP-RM session is usable + * (stage 3e saw init-done and the UNLOADING_GUEST_DRIVER RPC has not been + * submitted in this claim). The backend marks itself READY only when this is + * true; gsp_phys_boot_rm_flags() exposes the underlying bits for logging. + */ +bool gsp_phys_boot_rm_ready(void); +void gsp_phys_boot_rm_flags(u32 *init_done, u32 *unload_submitted); + /* Views into the staged GSP firmware ELF (set by gsp_phys_gpu.c). */ struct gsp_phys_boot_sources { const u8 *fw_image; /* .fwimage section of the GSP-RM ELF */ @@ -102,14 +111,22 @@ void gsp_phys_boot_staging_free(struct pci_dev *pdev); * not live. On success *reply owns a kmalloc'd copy of the reply payload * (*reply_len bytes, NULL/0 for an empty payload, caller frees). * - * gsp_phys_backend_static_snapshot() returns the cached static-config fields - * decoded from the function-65 reply; the cache is filled at READY in a - * later phase, so it currently reports -ENODATA. + * gsp_phys_backend_static_get() returns the cached static-config fields + * decoded from the function-65 reply; the cache is filled by the READY-time + * probe (gsp_phys_backend_static_probe() on the backend work item) and is + * invalidated whenever the backend session leaves READY. It returns -ENODATA + * while no valid cache exists and -EAGAIN when the session is not READY or + * the cache's generation key no longer matches the backend's. + * + * gsp_phys_backend_static_wait() polls the same getter in bounded sleeps + * (never holding gsp_phys_rm_lock) and fails open with -ENODATA/-EAGAIN so a + * caller can fall back to the emulated model. */ #define GSP_PHYS_BACKEND_GPU_NAME_LEN 64 struct gsp_phys_backend_static_config { bool valid; /* cache holds a decoded function-65 reply */ + u32 generation; /* backend session generation the fill saw */ u32 fw_crc32; /* cache key: loaded firmware image */ u32 payload_len; /* decoded reply payload bytes */ u32 h_internal_client; @@ -141,7 +158,58 @@ struct gsp_phys_backend_static_config { int gsp_phys_backend_rpc(u32 function, const void *req, u32 req_len, void **reply, u32 *reply_len, u32 timeout_ms); -int gsp_phys_backend_static_snapshot(struct gsp_phys_backend_static_config *out); +int gsp_phys_backend_static_get(struct gsp_phys_backend_static_config *out); +int gsp_phys_backend_static_wait(struct gsp_phys_backend_static_config *out, + u32 timeout_ms); +void gsp_phys_backend_static_invalidate(void); + +/* + * Run one fn1+fn65 probe on a READY backend to fill the static snapshot + * cache. Takes gsp_phys_rm_lock inside (via gsp_phys_rm_probe), so it must + * run on a work item, never inline under a caller-held rm lock or on the mdev + * create path. Non-fatal: a failed probe leaves the cache as it was and the + * caller keeps the emulation path. + */ +int gsp_phys_backend_static_probe(void); + +/* + * P5 wave-1 shadow work forwarding (gsp_phys_work_forward=1; default off). + * + * gsp_phys_backend_work_ready() is a lock-free readiness gate: the + * gsp_phys_work_forward parameter is set, the backend session is READY, the + * claim is live with GSP-RM init-done and no unload submitted, and the debugfs + * ladder has a usable client-memory channel (channel handle, work-submit + * token, non-server memory, PDB window and all ladder VAs present). It never + * waits on gsp_phys_rm_lock; every submit re-checks the same state under the + * lock before touching the device. + * + * gsp_phys_backend_work_operands() reports the ladder's module-owned CE + * operand VAs (src/dst/semaphore) and the fixed shadow copy size, or false + * while the ladder window is not usable. + * + * gsp_phys_backend_ce_copy_submit() submits one bytes-long CE copy on the + * ladder channel: it clears the module semaphore, encodes the method block, + * publishes the GPFIFO entry and USERD GP_PUT and rings the PF doorbell under + * gsp_phys_rm_lock, then releases the lock and polls the module semaphore for + * up to poll_ms (clamped to 200 ms) without the lock. Returns 0 when the + * release is observed, -ETIMEDOUT on the poll bound, -EAGAIN when the backend + * is not ready (including a release that committed before the lock), -EIO for + * a structural guard failure (BAR0/token/GP_PUT bounds/verify) and + * -EOPNOTSUPP for the server-allocated-memory channel variant. No guest + * memory or guest VA is ever touched; counters are maintained for all paths. + * + * gsp_phys_backend_work_counters() reads the shadow counters (attempts, + * observed releases, timeouts, refusals) for logging or the state file. + */ +#define GSP_PHYS_BACKEND_WORK_POLL_MS 50u /* submit clamps to 200 ms */ + +bool gsp_phys_backend_work_ready(void); +bool gsp_phys_backend_work_operands(u64 *src_va, u64 *dst_va, u64 *sem_va, + u32 *bytes); +int gsp_phys_backend_ce_copy_submit(u64 src_va, u64 dst_va, u64 sem_va, + u32 bytes, u32 poll_ms); +void gsp_phys_backend_work_counters(u64 *submitted, u64 *released, + u64 *timed_out, u64 *refused); /* * Command-queue TX: build a msgq record with the 570.144 element/rpc header |
