From 7c4e2defb82c4f9848fb218f88a9f42b6bcea185 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Mon, 5 Oct 2026 16:37:50 -0400 Subject: vgsp: fix host crash in FWCLIENT promote order (MAIN first, non-MAIN after) The 2026-10-05 16:05 crasher sent an accepted non-MAIN PROMOTE_CTX (PM/PATCH/FECS/PRIV/UNR) before a MAIN control that failed 0x40; the writing task then Oopsed in vma_interval_tree_remove with a corrupted VMA rbtree and module list (host kernel memory corruption). Restore the reference order (kgrobjGetPromoteIds_FWCLIENT: MAIN first) and make MAIN-alone the abort point: GPU_INITIALIZE_CTX (mask bit7) then the single-entry MAIN promote; build and send the non-MAIN entries only after MAIN commits (or when MAIN is deselected). The previous accepted-non-MAIN-before-failing-MAIN order is forbidden. Build is unchanged otherwise; mask 0xbf now reproduces the proven-clean mask-0x81 shape when MAIN hits the memdesc gate. --- kernel/gsp_phys_booter.c | 142 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 110 insertions(+), 32 deletions(-) (limited to 'kernel') diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index b985541..0c2e75a 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -9430,7 +9430,7 @@ static int gsp_phys_rmcall_gr_ctx_promote(void __iomem *bar0) 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", + 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, bit6 MAIN VA-only UVM shape, bit7 INITIALIZE_CTX first)\n", mask); /* @@ -9451,32 +9451,103 @@ static int gsp_phys_rmcall_gr_ctx_promote(void __iomem *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. */ + /* + * Mask bit7 (bisection): send the old-interface + * GPU_INITIALIZE_CTX with the client MAIN PA/size before the + * MAIN promote, installing the engine-context memdesc the MAIN + * commit requires on the V6 client-buffer channel. + */ + if (mask & BIT(7)) { + struct gsp_phys_rmcall_init_ctx_params *ic; + u32 ic_rpc = 0, ic_status = 0; + + ic = kvzalloc(sizeof(*ic), GFP_KERNEL); + if (!ic) { + kvfree(p); + return -ENOMEM; + } + ic->engine_type = cpu_to_le32(GSP_PHYS_RMCALL_ENGINE_GR0); + ic->h_client = cpu_to_le32(0); + ic->ch_id = cpu_to_le32(0); + ic->h_chan_client = cpu_to_le32(boot_stage.rmcall_client); + ic->h_object = cpu_to_le32(boot_stage.rmcall_channel); + ic->h_virt_memory = cpu_to_le32(0); + ic->phys_address = cpu_to_le64(boot_stage.rmcall_ctx_pa); + ic->phys_attr = cpu_to_le32(attr); + ic->h_dma_handle = cpu_to_le32(0); + ic->index = cpu_to_le32(0); + ic->size = cpu_to_le64(boot_stage.rmcall_ctx_size); + ret = gsp_phys_rmcall_control(bar0, + boot_stage.rmcall_subdevice, + GSP_PHYS_RMCALL_CTRL_GPU_INITIALIZE_CTX, + ic, sizeof(*ic), 24, NULL, 0, + &ic_rpc, &ic_status, + "GPU_INITIALIZE_CTX (fwclient mask bit7, before MAIN)"); + kvfree(ic); + pr_info("vgsp-boot: rm-call: PROMOTE_CTX fwclient INITIALIZE_CTX (before MAIN): pa=0x%llx size=0x%x physAttr=0x%x status=0x%x rpc_result=0x%x\n", + boot_stage.rmcall_ctx_pa, + boot_stage.rmcall_ctx_size, attr, ic_status, + ic_rpc); + if (ret) { + kvfree(p); + return ret; + } + } + if (mask & BIT(0)) { if (mask & BIT(6)) { - gsp_phys_rmcall_promote_entry_fill(p, n, + gsp_phys_rmcall_promote_entry_fill(p, 0, 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], + gsp_phys_rmcall_gr_promote_log_entry(0, + &p->entry[0], "VA-only (UVM shape, mask bit6)"); } else { - gsp_phys_rmcall_promote_entry_fill(p, n, + gsp_phys_rmcall_promote_entry_fill(p, 0, 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], + gsp_phys_rmcall_gr_promote_log_entry(0, + &p->entry[0], "combined (PDB-mapped ctx VA)"); } - n++; - } else { - pr_warn("vgsp-boot: rm-call: PROMOTE_CTX fwclient: MAIN omitted by mask\n"); + p->entry_count = cpu_to_le32(1); + rpc_result = 0; + status = 0; + ret = gsp_phys_rmcall_control(bar0, + boot_stage.rmcall_subdevice, + GSP_PHYS_RMCALL_CTRL_GPU_PROMOTE_CTX, + p, sizeof(*p), 24, NULL, 0, + &rpc_result, &status, + "GPU_PROMOTE_CTX (FWCLIENT MAIN)"); + pr_info("vgsp-boot: rm-call: PROMOTE_CTX fwclient MAIN: entryCount=1 status=0x%x rpc_result=0x%x (hObject=0x%x hChanClient=0x%x engineType=0x%x gr_promote_param=%u)\n", + status, rpc_result, + boot_stage.rmcall_channel, + boot_stage.rmcall_client, + GSP_PHYS_RMCALL_ENGINE_GR0, mode); + if (ret) { + pr_err("vgsp-boot: rm-call: PROMOTE_CTX fwclient MAIN failed (status=0x%x rpc_result=0x%x, %s, ret=%d); the GR context is not committed and the ladder aborts before BIND with no retry\n", + status, rpc_result, + gsp_phys_rmcall_status_str(status), ret); + kvfree(p); + return ret; + } + boot_stage.rmcall_gr_promote_step = 1; } - /* Entry 1: PM - init-only, no PM VA source in the ladder. */ + /* + * Host-safety rule from the 2026-10-05 crash: the non-MAIN + * entries are built only after MAIN has consumed entry[0], and + * are sent ONLY when MAIN was not selected or MAIN committed. + * Sending an accepted non-MAIN control before a failing MAIN + * control (the previous order) corrupted host kernel memory and + * Oopsed the writing task; that order must not return. + */ + n = 0; + + /* Entry 0: PM - init-only, no PM VA source in the ladder. */ 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, @@ -9541,27 +9612,34 @@ static int gsp_phys_rmcall_gr_ctx_promote(void __iomem *bar0) pr_warn("vgsp-boot: rm-call: PROMOTE_CTX fwclient: UNRESTRICTED_PRIV_ACCESS_MAP omitted (allocation unavailable)\n"); } - p->entry_count = cpu_to_le32(n); - rpc_result = 0; - status = 0; - ret = gsp_phys_rmcall_control(bar0, - boot_stage.rmcall_subdevice, - GSP_PHYS_RMCALL_CTRL_GPU_PROMOTE_CTX, - p, sizeof(*p), 24, NULL, 0, - &rpc_result, &status, - "GPU_PROMOTE_CTX (FWCLIENT set)"); - pr_info("vgsp-boot: rm-call: PROMOTE_CTX fwclient: entryCount=%u status=0x%x rpc_result=0x%x (hObject=0x%x hChanClient=0x%x engineType=0x%x gr_promote_param=%u)\n", - n, status, rpc_result, boot_stage.rmcall_channel, - boot_stage.rmcall_client, - GSP_PHYS_RMCALL_ENGINE_GR0, mode); - if (ret) { - pr_err("vgsp-boot: rm-call: PROMOTE_CTX fwclient failed (status=0x%x rpc_result=0x%x, %s, ret=%d); entries emitted=%u; the GR context is not committed and the ladder aborts before BIND with no retry\n", - status, rpc_result, - gsp_phys_rmcall_status_str(status), ret, n); - kvfree(p); - return ret; + if (n > 0) { + p->entry_count = cpu_to_le32(n); + rpc_result = 0; + status = 0; + ret = gsp_phys_rmcall_control(bar0, + boot_stage.rmcall_subdevice, + GSP_PHYS_RMCALL_CTRL_GPU_PROMOTE_CTX, + p, sizeof(*p), 24, NULL, 0, + &rpc_result, &status, + "GPU_PROMOTE_CTX (FWCLIENT non-MAIN, after MAIN)"); + pr_info("vgsp-boot: rm-call: PROMOTE_CTX fwclient non-MAIN (after MAIN): entryCount=%u status=0x%x rpc_result=0x%x (hObject=0x%x hChanClient=0x%x engineType=0x%x gr_promote_param=%u)\n", + n, status, rpc_result, + boot_stage.rmcall_channel, + boot_stage.rmcall_client, + GSP_PHYS_RMCALL_ENGINE_GR0, mode); + if (ret) { + pr_err("vgsp-boot: rm-call: PROMOTE_CTX fwclient non-MAIN failed (status=0x%x rpc_result=0x%x, %s, ret=%d); entries emitted=%u; the GR context commit is incomplete and the ladder aborts before BIND with no retry\n", + status, rpc_result, + gsp_phys_rmcall_status_str(status), ret, + n); + kvfree(p); + return ret; + } + boot_stage.rmcall_gr_promote_step = + (mask & BIT(0)) ? 2 : 1; + } else if (!(mask & BIT(0))) { + pr_warn("vgsp-boot: rm-call: PROMOTE_CTX fwclient: MAIN omitted by mask\n"); } - boot_stage.rmcall_gr_promote_step = 1; } else { pr_err("vgsp-boot: rm-call: unknown gr_promote_param=%u reached the promote step; no PROMOTE_CTX is sent and the ladder aborts with no retry\n", mode); -- cgit v1.2.3