summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-05 16:04:33 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-05 16:04:33 -0400
commitcc1028dffcbf9e028938555827f02b18ceba1665 (patch)
tree106cb12ed468d1df87725cbbcd965fb2f7cf9a1a /kernel
parent9a8a48b71ddc868f2c52e36e8e4e2f622236054d (diff)
downloadopen-iov-cc1028dffcbf9e028938555827f02b18ceba1665.tar.gz
open-iov-cc1028dffcbf9e028938555827f02b18ceba1665.zip
vgsp: FWCLIENT entry-selection mask and golden-replay hardening
- gsp_phys_rmcall_fwclient_mask (default 0x3f): per-entry selection for the mode-24 FWCLIENT promote set; bit6 selects the MAIN UVM VA-only shape. - golden replay: tolerate the client-local system-memory PB step and continue with hObjectBuffer=0; on-ladder TURING_A 3D object retained best-effort. Live bisection on the KMD channel: MAIN alone reaches the per-buffer commit and stops at the engine-context memdesc state; PM-only and PATCH-only are accepted; any multi-entry control containing MAIN is refused 0x1f. All cycles release clean.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_phys_booter.c115
-rw-r--r--kernel/gsp_phys_gpu.c19
-rw-r--r--kernel/gsp_phys_gpu.h7
3 files changed, 101 insertions, 40 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index e434910..b985541 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -7693,6 +7693,7 @@ static int gsp_phys_rmcall_golden_replay(void __iomem *bar0)
struct gsp_phys_rmcall_channel_params ch;
struct gsp_phys_rmcall_mem_obj_shape shape;
u32 rpc = 0, status = 0;
+ bool pb_ok = true;
int ret;
/* 1. Golden VAS: PTETABLE_HEAP_MANAGED only (kernel_graphics.c:2194-2200). */
@@ -7725,17 +7726,25 @@ static int gsp_phys_rmcall_golden_replay(void __iomem *bar0)
shape.attr = GSP_PHYS_RMCALL_OS32_ATTR_PCI;
shape.attr2 = GSP_PHYS_RMCALL_OS32_ATTR2_PROT_UNPROTECTED;
ret = gsp_phys_rmcall_golden_mem(bar0, &shape, "PB physical");
- if (ret)
- return ret;
+ if (ret) {
+ pr_warn("vgsp-boot: rm-call: GOLDEN PB physical unavailable (%d); continuing the golden replay with hObjectBuffer=0 (system memory is client-local on GSP; the class-0x3e server alloc is not available)\n",
+ ret);
+ pb_ok = false;
+ }
/* 3. Its virtual mapping on the golden VAS (kernel_graphics.c:2224-2235). */
- shape.handle = GSP_PHYS_RMCALL_HANDLE_GOLDEN_PB_VIRT;
- shape.h_class = GSP_PHYS_RMCALL_CLASS_MEMORY_VIRTUAL_50;
- shape.flags = GSP_PHYS_RMCALL_OS32_FLAG_VIRTUAL;
- shape.h_va_space = GSP_PHYS_RMCALL_HANDLE_GOLDEN_VAS;
- ret = gsp_phys_rmcall_golden_mem(bar0, &shape, "PB virtual");
- if (ret)
- return ret;
+ if (pb_ok) {
+ shape.handle = GSP_PHYS_RMCALL_HANDLE_GOLDEN_PB_VIRT;
+ shape.h_class = GSP_PHYS_RMCALL_CLASS_MEMORY_VIRTUAL_50;
+ shape.flags = GSP_PHYS_RMCALL_OS32_FLAG_VIRTUAL;
+ shape.h_va_space = GSP_PHYS_RMCALL_HANDLE_GOLDEN_VAS;
+ ret = gsp_phys_rmcall_golden_mem(bar0, &shape, "PB virtual");
+ if (ret) {
+ pr_warn("vgsp-boot: rm-call: GOLDEN PB virtual unavailable (%d); continuing with hObjectBuffer=0\n",
+ ret);
+ pb_ok = false;
+ }
+ }
/* 4. Client USERD, internal reserved-heap VIDMEM (kernel_graphics.c:2237-2313). */
shape.handle = GSP_PHYS_RMCALL_HANDLE_GOLDEN_USERD;
@@ -7757,7 +7766,8 @@ static int gsp_phys_rmcall_golden_replay(void __iomem *bar0)
*/
memset(&ch, 0, sizeof(ch));
ch.h_va_space = cpu_to_le32(GSP_PHYS_RMCALL_HANDLE_GOLDEN_VAS);
- ch.h_object_buffer = cpu_to_le32(GSP_PHYS_RMCALL_HANDLE_GOLDEN_PB_VIRT);
+ ch.h_object_buffer = cpu_to_le32(pb_ok ?
+ GSP_PHYS_RMCALL_HANDLE_GOLDEN_PB_VIRT : 0);
ch.gp_fifo_entries =
cpu_to_le32(GSP_PHYS_RMCALL_GOLDEN_GPFIFO_ENTRIES);
ch.gp_fifo_offset = cpu_to_le64(0);
@@ -9417,34 +9427,57 @@ static int gsp_phys_rmcall_gr_ctx_promote(void __iomem *bar0)
*/
u32 attr = GSP_PHYS_RMCALL_GR_CTX_PHYS_ATTR;
u64 bk = GSP_PHYS_RMCALL_VA_GR_CTX + 0x400000ULL;
+ u32 mask = gsp_phys_rmcall_fwclient_mask_value();
u32 n = 0;
+ pr_info("vgsp-boot: rm-call: PROMOTE_CTX fwclient: entry mask=0x%x (bit0 MAIN, bit1 PM, bit2 PATCH, bit3 FECS_EVENT, bit4 PRIV_ACCESS_MAP, bit5 UNRESTRICTED_PRIV_ACCESS_MAP)\n",
+ mask);
+
/*
* PATCH is always present in the reference set; a failed
- * prepare aborts before any control is sent.
+ * prepare aborts before any control is sent. The mask (mode-24
+ * bisection) may deselect it without preparing.
*/
- ret = gsp_phys_rmcall_gr_patch_prepare(bar0);
- if (ret) {
- pr_err("vgsp-boot: rm-call: PROMOTE_CTX fwclient aborted: PATCH prepare failed (%d); the reference set always carries PATCH, so no promote is sent and the ladder aborts with no retry\n",
- ret);
- kvfree(p);
- return ret;
+ if (mask & BIT(2)) {
+ ret = gsp_phys_rmcall_gr_patch_prepare(bar0);
+ if (ret) {
+ pr_err("vgsp-boot: rm-call: PROMOTE_CTX fwclient aborted: PATCH prepare failed (%d); the reference set always carries PATCH, so no promote is sent and the ladder aborts with no retry\n",
+ ret);
+ kvfree(p);
+ return ret;
+ }
}
if (gsp_phys_rmcall_gr_pm_prepare(bar0))
pr_warn("vgsp-boot: rm-call: PROMOTE_CTX fwclient: PM prepare failed; omitting the PM entry and continuing (mode 24 treats PM as best-effort; the reference set pre-allocates it for an externally-owned VAS)\n");
gsp_phys_rmcall_gr_fwclient_small_prepare();
/* Entry 0: MAIN - combined PA+VA, PDB-mapped ctx VA. */
- gsp_phys_rmcall_promote_entry_fill(p, n,
- GSP_PHYS_RMCALL_GR_CTX_BUFFER_ID_MAIN,
- boot_stage.rmcall_ctx_pa, boot_stage.rmcall_ctx_va,
- boot_stage.rmcall_ctx_size, attr, 1, 0);
- gsp_phys_rmcall_gr_promote_log_entry(n, &p->entry[n],
- "combined (PDB-mapped ctx VA)");
- n++;
+ if (mask & BIT(0)) {
+ if (mask & BIT(6)) {
+ gsp_phys_rmcall_promote_entry_fill(p, n,
+ GSP_PHYS_RMCALL_GR_CTX_BUFFER_ID_MAIN,
+ 0, boot_stage.rmcall_ctx_va, 0, 0,
+ 0, 0);
+ gsp_phys_rmcall_gr_promote_log_entry(n,
+ &p->entry[n],
+ "VA-only (UVM shape, mask bit6)");
+ } else {
+ gsp_phys_rmcall_promote_entry_fill(p, n,
+ GSP_PHYS_RMCALL_GR_CTX_BUFFER_ID_MAIN,
+ boot_stage.rmcall_ctx_pa,
+ boot_stage.rmcall_ctx_va,
+ boot_stage.rmcall_ctx_size, attr, 1, 0);
+ gsp_phys_rmcall_gr_promote_log_entry(n,
+ &p->entry[n],
+ "combined (PDB-mapped ctx VA)");
+ }
+ n++;
+ } else {
+ pr_warn("vgsp-boot: rm-call: PROMOTE_CTX fwclient: MAIN omitted by mask\n");
+ }
/* Entry 1: PM - init-only, no PM VA source in the ladder. */
- if (boot_stage.rmcall_pm_prepared &&
+ if ((mask & BIT(1)) && boot_stage.rmcall_pm_prepared &&
boot_stage.rmcall_pm_pa && boot_stage.rmcall_pm_size) {
gsp_phys_rmcall_promote_entry_fill(p, n,
GSP_PHYS_RMCALL_GR_CTX_BUFFER_ID_PM,
@@ -9453,22 +9486,24 @@ static int gsp_phys_rmcall_gr_ctx_promote(void __iomem *bar0)
gsp_phys_rmcall_gr_promote_log_entry(n, &p->entry[n],
"init-only, no PM VA source (reference external-VAS shape)");
n++;
- } else {
+ } else if (mask & BIT(1)) {
pr_warn("vgsp-boot: rm-call: PROMOTE_CTX fwclient: PM omitted (no queried buffer; the reference external-VAS client pre-allocates it)\n");
}
/* Entry 2: PATCH - combined, booking-only VA. */
- gsp_phys_rmcall_promote_entry_fill(p, n,
- GSP_PHYS_RMCALL_GR_CTX_BUFFER_ID_PATCH,
- boot_stage.rmcall_patch_pa,
- GSP_PHYS_RMCALL_VA_GR_PATCH,
- boot_stage.rmcall_patch_size, attr, 1, 0);
- gsp_phys_rmcall_gr_promote_log_entry(n, &p->entry[n],
- "combined (booking-only VA, not PDB-mapped)");
- n++;
+ if (mask & BIT(2)) {
+ gsp_phys_rmcall_promote_entry_fill(p, n,
+ GSP_PHYS_RMCALL_GR_CTX_BUFFER_ID_PATCH,
+ boot_stage.rmcall_patch_pa,
+ GSP_PHYS_RMCALL_VA_GR_PATCH,
+ boot_stage.rmcall_patch_size, attr, 1, 0);
+ gsp_phys_rmcall_gr_promote_log_entry(n, &p->entry[n],
+ "combined (booking-only VA, not PDB-mapped)");
+ n++;
+ }
/* Entry 3: FECS_EVENT - combined, booking-only VA. */
- if (boot_stage.rmcall_fecs_pa) {
+ if ((mask & BIT(3)) && boot_stage.rmcall_fecs_pa) {
gsp_phys_rmcall_promote_entry_fill(p, n,
GSP_PHYS_RMCALL_GR_CTX_BUFFER_ID_FECS_EVENT,
boot_stage.rmcall_fecs_pa, bk + 0x6000ULL,
@@ -9476,12 +9511,12 @@ static int gsp_phys_rmcall_gr_ctx_promote(void __iomem *bar0)
gsp_phys_rmcall_gr_promote_log_entry(n, &p->entry[n],
"combined (booking-only VA, not PDB-mapped)");
n++;
- } else {
+ } else if (mask & BIT(3)) {
pr_warn("vgsp-boot: rm-call: PROMOTE_CTX fwclient: FECS_EVENT omitted (allocation unavailable)\n");
}
/* Entry 4: PRIV_ACCESS_MAP - init-only, captured stock shape. */
- if (boot_stage.rmcall_priv_pa) {
+ if ((mask & BIT(4)) && boot_stage.rmcall_priv_pa) {
gsp_phys_rmcall_promote_entry_fill(p, n,
GSP_PHYS_RMCALL_GR_CTX_BUFFER_ID_PRIV_MAP,
boot_stage.rmcall_priv_pa, 0, 0x1000u, attr,
@@ -9489,12 +9524,12 @@ static int gsp_phys_rmcall_gr_ctx_promote(void __iomem *bar0)
gsp_phys_rmcall_gr_promote_log_entry(n, &p->entry[n],
"init-only (captured stock shape; sysmem attr 0x6, reference FB uncached 0x4)");
n++;
- } else {
+ } else if (mask & BIT(4)) {
pr_warn("vgsp-boot: rm-call: PROMOTE_CTX fwclient: PRIV_ACCESS_MAP omitted (allocation unavailable)\n");
}
/* Entry 5: UNRESTRICTED_PRIV_ACCESS_MAP - combined. */
- if (boot_stage.rmcall_unrestricted_pa) {
+ if ((mask & BIT(5)) && boot_stage.rmcall_unrestricted_pa) {
gsp_phys_rmcall_promote_entry_fill(p, n,
GSP_PHYS_RMCALL_GR_CTX_BUFFER_ID_UNR_PRIV_MAP,
boot_stage.rmcall_unrestricted_pa,
@@ -9502,7 +9537,7 @@ static int gsp_phys_rmcall_gr_ctx_promote(void __iomem *bar0)
gsp_phys_rmcall_gr_promote_log_entry(n, &p->entry[n],
"combined (booking-only VA, not PDB-mapped)");
n++;
- } else {
+ } else if (mask & BIT(5)) {
pr_warn("vgsp-boot: rm-call: PROMOTE_CTX fwclient: UNRESTRICTED_PRIV_ACCESS_MAP omitted (allocation unavailable)\n");
}
diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c
index cd04007..5e6b264 100644
--- a/kernel/gsp_phys_gpu.c
+++ b/kernel/gsp_phys_gpu.c
@@ -228,6 +228,25 @@ int gsp_phys_rmcall_channel_value(void)
EXPORT_SYMBOL_GPL(gsp_phys_rmcall_channel_value);
/*
+ * FWCLIENT promote entry-selection mask (mode 24 bisection; default 0x3f =
+ * all six reference non-3D buffers). Bit i selects emitted entry i:
+ * 0 MAIN, 1 PM, 2 PATCH, 3 FECS_EVENT, 4 PRIV_ACCESS_MAP,
+ * 5 UNRESTRICTED_PRIV_ACCESS_MAP. Lets a bisection isolate which entry the
+ * server refuses without a rebuild.
+ */
+static u32 gsp_phys_rmcall_fwclient_mask_param = 0x3fu;
+module_param_named(gsp_phys_rmcall_fwclient_mask,
+ gsp_phys_rmcall_fwclient_mask_param, uint, 0644);
+MODULE_PARM_DESC(gsp_phys_rmcall_fwclient_mask,
+ "Bitmask (default 0x3f) selecting the mode-24 FWCLIENT promote entries to emit: bit0 MAIN, bit1 PM, bit2 PATCH, bit3 FECS_EVENT, bit4 PRIV_ACCESS_MAP, bit5 UNRESTRICTED_PRIV_ACCESS_MAP");
+
+u32 gsp_phys_rmcall_fwclient_mask_value(void)
+{
+ return gsp_phys_rmcall_fwclient_mask_param;
+}
+EXPORT_SYMBOL_GPL(gsp_phys_rmcall_fwclient_mask_value);
+
+/*
* Golden-image replay (default 0). When set (and gsp_phys_gpu=1), the rm-call
* ladder's stage 3 replays the stock client's post-load golden-image channel
* allocations (kgraphicsCreateGoldenImageChannel: a separate
diff --git a/kernel/gsp_phys_gpu.h b/kernel/gsp_phys_gpu.h
index 8322725..9e809e3 100644
--- a/kernel/gsp_phys_gpu.h
+++ b/kernel/gsp_phys_gpu.h
@@ -99,6 +99,13 @@ int gsp_phys_srv_ctxcommit_mode(void);
int gsp_phys_rmcall_channel_value(void);
/*
+ * gsp_phys_rmcall_fwclient_mask (default 0x3f): bitmask selecting the mode-24
+ * FWCLIENT promote entries to emit (bit0 MAIN, bit1 PM, bit2 PATCH,
+ * bit3 FECS_EVENT, bit4 PRIV_ACCESS_MAP, bit5 UNRESTRICTED_PRIV_ACCESS_MAP).
+ */
+u32 gsp_phys_rmcall_fwclient_mask_value(void);
+
+/*
* gsp_phys_rmcall_golden (default 0): replay the stock client's golden-image
* channel allocations in stage 3 before the ladder's own channel when set and
* gsp_phys_gpu=1. With 0, the ladder is byte-identical to before.