1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
|
#ifndef GSP_PHYS_GPU_H
#define GSP_PHYS_GPU_H
#include <linux/types.h>
/*
* Physical GPU ownership (real-GSP execution backend, bring-up rung 1).
* Claim is disabled unless the gsp_phys_gpu module parameter is set.
*/
bool gsp_phys_gpu_claimed(void);
int gsp_phys_gpu_claim(void);
void gsp_phys_gpu_release(void);
void __iomem *gsp_phys_gpu_bar0(void);
u32 gsp_phys_gpu_fw_crc32(void);
/*
* Read by the backend session to enforce the mdev-owned start gate; the
* gsp_phys_gpu module parameter itself is owned by main.c.
*/
bool gsp_phys_gpu_enabled(void);
/*
* Backend session state (P0 skeleton + P1 lifecycle; one physical GPU, one
* live claim). OFF until a start claims the device; READY is the only state
* in which live RPC forwarding is legal. The refcount and owner flag decide
* who releases: the load-time module-owned claim is joined, never released,
* by a stop(); an mdev-owned claim is released by the last stop().
*/
enum gsp_phys_backend_state {
GSP_PHYS_BACKEND_OFF = 0,
GSP_PHYS_BACKEND_CLAIMING,
GSP_PHYS_BACKEND_BOOTING,
GSP_PHYS_BACKEND_READY,
GSP_PHYS_BACKEND_STOPPING,
};
/*
* Refcounted session start/stop around gsp_phys_gpu_claim()/_release(); safe
* (and idempotent) in any state. gsp_phys_backend_start() never blocks on the
* claim/boot: an mdev-owned start schedules a work item and returns, and a
* failed claim leaves the session OFF (fail-open: the caller keeps using the
* emulation path). The generation counter is bumped when the session leaves
* READY; a forward that captured the previous value re-checks it under
* gsp_phys_rm_lock and refuses, so a stop cannot race an in-flight forward.
* The lock itself stays private to gsp_phys_gpu.c; the state and generation
* accessors are lock-free reads for use from the RPC path.
*
* Module exit uses the two-phase form so the §1.4 ordering can be kept:
* begin_stop() gates the session (STOPPING + generation bump) before the
* caller drains the emulation threads, then end_stop() runs the release.
*/
int gsp_phys_backend_start(void);
void gsp_phys_backend_stop(void);
void gsp_phys_backend_begin_stop(void);
void gsp_phys_backend_end_stop(void);
int gsp_phys_backend_state(void);
u32 gsp_phys_backend_generation(void);
/*
* True when the gsp_phys_mdev_owned module parameter is set (default 0:
* load-time module-owned claim/boot, today's behavior).
*/
bool gsp_phys_mdev_owned_enabled(void);
/*
* True when the gsp_phys_static_live module parameter is set (default 0:
* the guest GET_GSP_STATIC_INFO reply is the emulated model unchanged). When
* set, the handler overlays the live GPU name/short-name/VBIOS identity from
* the backend snapshot, failing open to the emulated reply on any miss.
*/
bool gsp_phys_static_live_enabled(void);
/*
* True when the gsp_phys_ctrl_forward module parameter is set (default 0:
* guest GSP_RM_CONTROL replies are the emulated answers unchanged). When set,
* a whitelist of side-effect-free control queries is forwarded to the live
* backend with the snapshot's adopted internal handles, falling back to the
* emulated per-command handler on any miss.
*/
bool gsp_phys_ctrl_forward_enabled(void);
/*
* True when the gsp_phys_work_forward module parameter is set (default 0: the
* guest's CE pushes stay software-emulated exactly as before). When set, the
* sema service shadows each decoded CE push as one copy on the debugfs ladder's
* real channel using only module-owned ladder buffers; the software release
* remains authoritative and is applied unchanged either way, unless
* gsp_phys_work_defer_release moves a forwarded push's release after its
* hardware copy (see below).
*/
bool gsp_phys_work_forward_enabled(void);
/*
* True when the gsp_phys_guest_mem module parameter is set (default 0: the
* debugfs rm-call ladder stays entirely on module-owned buffers, exactly as
* before). When set, ladder triggers 6 (W2G) and 7 (G2H) may point the real
* CE engine at one pinned guest RAM page identified by GPA, proving the
* translation path and both copy directions.
*/
bool gsp_phys_guest_mem_enabled(void);
/*
* True when the gsp_phys_work_defer_release module parameter is set (default
* 0: a forwarded guest CE push's release is applied inline with the software
* copy, byte-identical to wave 1). When set with gsp_phys_work_forward and
* gsp_phys_guest_mem, the release(s) a forwarded push decoded are held on the
* service thread until the hardware copy completes, its bounded timeout
* expires, or the forwarding is aborted; they are then applied from the
* service thread. One-line rollback: gsp_phys_work_defer_release=0.
*/
bool gsp_phys_work_defer_release_enabled(void);
/*
* True when the gsp_phys_work_hw_primary module parameter is set (default
* 0: byte-identical to wave 1.5, the software copy always runs inline). When
* set with gsp_phys_work_forward, gsp_phys_guest_mem and
* gsp_phys_work_defer_release, a forwarded guest CE copy skips the software
* copy (the hardware authors the data) and the release still lands only
* after hardware completion through the wave-1.5 hold. Any hardware failure,
* timeout, abort or failed guest queue falls back to exactly one software
* copy in the service thread before the releases are applied, so the guest
* always reads correct data. One-line rollback: gsp_phys_work_hw_primary=0.
*/
bool gsp_phys_work_hw_primary_enabled(void);
/*
* True when the gsp_phys_relay module parameter is set (default 0: a
* forwarded guest CE copy polls the module-owned ladder semaphore and the
* software release path stays the sole author of the guest-visible release).
* When set with gsp_phys_work_forward, gsp_phys_guest_mem and
* gsp_phys_work_defer_release, one selected one-word release of a forwarded
* guest push is authored by the real CE engine directly into the
* guest-visible semaphore page (a third scratch PTE maps that page) and the
* service thread skips the software apply of that record once the guest word
* carries the payload; every failure, timeout, abort or failed verification
* falls back to the unchanged software apply, so a release is never lost or
* duplicated. One-line rollback: gsp_phys_relay=0.
*/
bool gsp_phys_relay_enabled(void);
/*
* True when the gsp_phys_fault_relay module parameter is set (default 0:
* a relayed forwarded CE copy that times out is abandoned to the unchanged
* software release fallback, exactly as in P6c C0+C1). When set together
* with gsp_phys_relay, gsp_phys_work_forward, gsp_phys_guest_mem and
* gsp_phys_work_defer_release, the relay-timeout path drains the GSP-RM
* status queue, decodes an engine fault (function 0x1006, corroborated by a
* 0x1020 NOCAT record) and delivers it to the guest only when its
* runlistId/chid match the ladder channel: the guest channel notifier is
* written (info32=exceptType, info16=Nv2080 engine type, status=0xffff) and
* the channel event posted (MSI-X). The software releases still run; a fault
* is never delivered for a mismatch, a late release or a stale record.
* One-line rollback: gsp_phys_fault_relay=0.
*/
bool gsp_phys_fault_relay_enabled(void);
/*
* True when the gsp_phys_fault_inject module parameter is set (default 0:
* forwarded guest CE copies program the real source PTE, byte-identical
* behavior). When set, the relayed pair's source PTE is written as an
* invalid (zero) entry on the next relay submission, so the engine faults
* and the C3 fault path can be exercised end to end. It only ever changes
* the source PTE of a relayed pair (a nonzero sem_hpa); every other copy and
* every non-relay submission is untouched.
*/
bool gsp_phys_fault_inject_enabled(void);
/*
* RM-client ladder engine selector (gsp_phys_rmcall_engine; default 0):
* returns the raw module-parameter value, where 0 = COPY0 (the existing CE
* ladder) and 1 = GR0 (the TURING_COMPUTE_A engine object plus a GR
* semaphore release). The booter snapshots this when the rm-call ladder's
* stage 3 starts and ignores later changes, so this accessor is for the
* snapshot and diagnostics only.
*/
int gsp_phys_rmcall_engine_value(void);
/*
* Translate a guest GPA to the pinned host PA (gsp_phys_guest_mem ladder
* support). The mdev is registered with vfio_register_emulated_iommu_dev():
* its VFIO type-1 container keeps the guest DMA mappings privately, so
* iommu_get_domain_for_dev() returns NULL there and the original
* IOMMU-domain path cannot resolve a GPA at runtime. The authoritative
* translation is the guest RAM backing file configured through debugfs
* gsp-phys-guest-ram (QEMU memory-backend-file, share=yes): the range's
* file page is pinned with read_cache_page() and page_to_phys() gives the
* host PA. Returns 0 and stores the PA on success; -ENODEV with no active
* mdev, -ENOENT when the file page cannot be read or the GPA is not mapped
* by the fallback IOMMU path, -ERANGE when the result is not a valid RAM
* PFN (so a caller never treats MMIO/dead space as RAM), and -EINVAL for a
* NULL output. The caller must hold no guest or rm lock; this helper takes
* nv_vgpu_driver.lock only for the mdev lookup and guest_ram_lock across
* the range walk/read.
*/
int gsp_phys_gpa_to_hpa(u64 gpa, u64 *hpa_out);
/*
* Guest RAM backing-file configuration (debugfs gsp-phys-guest-ram). One
* shared file per module cycle, up to four GPA->file-offset ranges keyed by
* gpa_base. The first configure opens the file; the same path adds/replaces
* ranges, a different path is refused -EBUSY, and the ranges are dropped and
* the file closed by gsp_phys_guest_ram_clear() on physical-GPU release. The
* state accessor is lock-safe and writes "active=0" or the active path,
* range count and per-range gpa/off/size into the caller's buffer.
*/
int gsp_phys_guest_ram_configure(const char *path, u64 gpa_base,
u64 file_offset, u64 size);
void gsp_phys_guest_ram_clear(void);
bool gsp_phys_guest_ram_active(void);
void gsp_phys_guest_ram_state(char *buf, size_t len);
/*
* Domain shape of the physical (claimed) device, as the P6a engine path
* needs it: the module programs raw host PAs into the CE page tables, so the
* engine may only run when the physical device's DMA addresses ARE host PAs.
* Returns 1 when the claimed device's IOMMU domain is
* IOMMU_DOMAIN_IDENTITY, 0 when another domain type, and -1 when the device
* is not claimed or has no domain (either way the caller must refuse).
*/
int gsp_phys_dma_domain_identity(void);
#endif /* GSP_PHYS_GPU_H */
|