diff options
| -rw-r--r-- | kernel/gsp_phys_booter.c | 58 | ||||
| -rw-r--r-- | kernel/gsp_phys_gpu.c | 22 | ||||
| -rw-r--r-- | kernel/gsp_phys_gpu.h | 4 |
3 files changed, 81 insertions, 3 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 67ade76..40dfca3 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -15090,6 +15090,12 @@ EXPORT_SYMBOL_GPL(gsp_phys_backend_guest_ce_copy); /* PCAS(4) + REPORT_SEM(8). */ #define GSP_PHYS_RMCALL_GR_TAIL_WORDS 12u #define GSP_PHYS_RMCALL_GR_QMD_REL_PAYLOAD GSP_PHYS_RMCALL_SEM_PAYLOAD +/* + * m64: the forced module-sem release needs a payload distinct from the + * stage-4 sem value (GSP_PHYS_RMCALL_SEM_PAYLOAD = 0xc0ffee01), otherwise + * the poll would match the pre-existing word without an engine write. + */ +#define GSP_PHYS_RMCALL_GR_QMD_REL_MOD_PAYLOAD 0x600df00du #define GSP_PHYS_RMCALL_GR_SEM_PAYLOAD 0xc0ffee02u /* * PCAS launcher (bisect): the driver's non-IQ2M path schedules a QMD with @@ -15722,8 +15728,9 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, if (((qmd[4] >> 10) & 1)) { u32 red_en = (qmd[24] >> 26) & 1; u32 one_word = (qmd[24] >> 31) & 1; + bool rel_mod = gsp_phys_rmcall_gr_rel_mod_value() != 0; - if (req->rel_hpa && one_word && !red_en && + if (!rel_mod && req->rel_hpa && one_word && !red_en && n_shadow < GSP_PHYS_RMCALL_GR_SHADOW_PAGES) { u64 sh_va = 0; @@ -15750,9 +15757,20 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, qmd[24] = (qmd[24] & 0xffffff00u) | ((u32)(GSP_PHYS_RMCALL_VA_SEM >> 32) & 0xffu); - qmd[25] = GSP_PHYS_RMCALL_GR_QMD_REL_PAYLOAD; - want_qmd = GSP_PHYS_RMCALL_GR_QMD_REL_PAYLOAD; + qmd[25] = rel_mod ? + GSP_PHYS_RMCALL_GR_QMD_REL_MOD_PAYLOAD : + GSP_PHYS_RMCALL_GR_QMD_REL_PAYLOAD; + want_qmd = qmd[25]; qmd_rel = true; + /* + * m64: the module-sem fallback must poll the SEM chunk, + * otherwise a completed QMD is unobservable (the poll + * only reads qmd_rel_hpa). + */ + qmd_rel_hpa = (u64)gsp_phys_chunk_page_dma( + &boot_stage.rmcall_chunks + [GSP_PHYS_RMCALL_BUF_SEM], 0); + qmd_rel_off = 0; } } @@ -16259,6 +16277,40 @@ gr_page_unmapped: "not-run (sentinel intact)" : "ran (page overwritten)", qmdwin_note); + { + u8 *qp = qmd_dst_mem ? qmd_dst_mem : + (req->qmd_hpa ? + (u8 *)__va(req->qmd_hpa) : + NULL); + + if (qp) + pr_info("vgsp-gr: post-mortem qmd w2..w15 = %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", + get_unaligned_le32(qp + 8), + get_unaligned_le32(qp + 12), + get_unaligned_le32(qp + 16), + get_unaligned_le32(qp + 20), + get_unaligned_le32(qp + 24), + get_unaligned_le32(qp + 28), + get_unaligned_le32(qp + 32), + get_unaligned_le32(qp + 36), + get_unaligned_le32(qp + 40), + get_unaligned_le32(qp + 44), + get_unaligned_le32(qp + 48), + get_unaligned_le32(qp + 52), + get_unaligned_le32(qp + 56), + get_unaligned_le32(qp + 60)); + } + if (req->rel_hpa) + pr_info("vgsp-gr: post-mortem release page hpa=0x%llx off=0x%x w0..7 = %08x %08x %08x %08x %08x %08x %08x %08x\n", + req->rel_hpa, req->rel_off, + get_unaligned_le32((u8 *)__va(req->rel_hpa)), + get_unaligned_le32((u8 *)__va(req->rel_hpa) + 4), + get_unaligned_le32((u8 *)__va(req->rel_hpa) + 8), + get_unaligned_le32((u8 *)__va(req->rel_hpa) + 12), + get_unaligned_le32((u8 *)__va(req->rel_hpa) + 16), + get_unaligned_le32((u8 *)__va(req->rel_hpa) + 20), + get_unaligned_le32((u8 *)__va(req->rel_hpa) + 24), + get_unaligned_le32((u8 *)__va(req->rel_hpa) + 28)); if (bar0) pr_info("vgsp-gr: FE readback raw 0x40a500..0x40a50c = %08x %08x %08x %08x (subctx-1 control at 0x40a504)\n", ioread32(bar0 + 0x0040a500u), diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c index 974100a..f323c6c 100644 --- a/kernel/gsp_phys_gpu.c +++ b/kernel/gsp_phys_gpu.c @@ -704,6 +704,28 @@ int gsp_phys_rmcall_gr_qmdwin_value(void) EXPORT_SYMBOL_GPL(gsp_phys_rmcall_gr_qmdwin_value); /* + * m64 forced module-semaphore release (gsp_phys_rmcall_gr_rel_mod; default 0). + * When set, a forwarded GR launch ignores the resolved guest release page and + * points QMD release0 at the module window-0 semaphore VA + * (GSP_PHYS_RMCALL_VA_SEM), which the host polls at the SEM chunk's host VA. + * Discriminant for "engine completed but the shadow release write was lost" + * vs "engine never completed": with the module release, a completed QMD is + * always observable. Also makes the existing module-release fallback + * observable (it previously set no poll source, so it could never complete). + */ +static int gsp_phys_rmcall_gr_rel_mod_param; +module_param_named(gsp_phys_rmcall_gr_rel_mod, + gsp_phys_rmcall_gr_rel_mod_param, int, 0644); +MODULE_PARM_DESC(gsp_phys_rmcall_gr_rel_mod, + "Force the forwarded GR QMD release0 to the module semaphore (default 0; 1 = m64 engine-completion discriminant)"); + +int gsp_phys_rmcall_gr_rel_mod_value(void) +{ + return gsp_phys_rmcall_gr_rel_mod_param; +} +EXPORT_SYMBOL_GPL(gsp_phys_rmcall_gr_rel_mod_value); + +/* * Ladder VAS ownership selector (gsp_phys_rmcall_vas_shared; default 0). * The H1 GR promote wall is a direct consequence of the ladder's * externally-owned FERMI_VASPACE_A: with IS_EXTERNALLY_OWNED the RM treats diff --git a/kernel/gsp_phys_gpu.h b/kernel/gsp_phys_gpu.h index 2087e33..84461e8 100644 --- a/kernel/gsp_phys_gpu.h +++ b/kernel/gsp_phys_gpu.h @@ -325,6 +325,10 @@ int gsp_phys_rmcall_gr_pcas_two_step_value(void); */ int gsp_phys_rmcall_gr_qmdwin_value(void); +/* m64 discriminant: force the forwarded GR QMD release0 to the module + * semaphore so engine completion is always observable (default 0). */ +int gsp_phys_rmcall_gr_rel_mod_value(void); + /* * Ladder VAS ownership selector (gsp_phys_rmcall_vas_shared; default 0). * 0 = FERMI_VASPACE_A is allocated IS_EXTERNALLY_OWNED (historical ladder |
