diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-05 16:04:33 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-05 16:04:33 -0400 |
| commit | cc1028dffcbf9e028938555827f02b18ceba1665 (patch) | |
| tree | 106cb12ed468d1df87725cbbcd965fb2f7cf9a1a | |
| parent | 9a8a48b71ddc868f2c52e36e8e4e2f622236054d (diff) | |
| download | open-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.
| -rw-r--r-- | kernel/gsp_phys_booter.c | 115 | ||||
| -rw-r--r-- | kernel/gsp_phys_gpu.c | 19 | ||||
| -rw-r--r-- | kernel/gsp_phys_gpu.h | 7 |
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. |
