diff options
Diffstat (limited to 'kernel/gsp_phys_booter.c')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index b95bd81..7113663 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -13024,6 +13024,7 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, bool qmd_rel = false, ch_rel = false; u64 qmd_rel_hpa = 0, ch_rel_hpa = 0; u64 ch_sem_va = GSP_PHYS_RMCALL_VA_SEM + 4; + u64 qmd_dst = GSP_PHYS_RMCALL_VA_SRC; u32 qmd_rel_off = 0, ch_rel_off = 0; u32 poll = 0, w0 = 0, w1 = 0; int ret = 0; @@ -13351,6 +13352,38 @@ gr_page_unmapped: } /* + * Inline-QMD destination: the CUDA driver points ADDRESS_A/B at its + * own QMD buffer (turing_launch.c:1629) and the IQ2M copies the 64 + * inline words there before scheduling. Map the guest QMD page and + * use it as the destination when the caller resolved it; a Tier-1 + * install keeps the guest VA (the guest sees its own QMD), a Tier-2 + * alias keeps the launch runnable, and an unresolved page keeps the + * module scratch VA. + */ + if (req->qmd_hpa) { + u64 qmd_page = req->qmd_va & ~(u64)(GSP_PHYS_PAGE_SIZE - 1); + + if (qmd_page && + !gsp_phys_rmcall_gr_map_va_locked(bar0, qmd_page, + req->qmd_hpa, epoch)) { + qmd_dst = qmd_page; + } else { + u64 sh_va = 0; + + if (n_shadow < GSP_PHYS_RMCALL_GR_SHADOW_PAGES && + !gsp_phys_rmcall_gr_map_shadow_locked( + n_shadow, req->qmd_hpa, &sh_va)) { + n_shadow++; + qmd_dst = sh_va + + (req->qmd_va & + (GSP_PHYS_PAGE_SIZE - 1)); + } + } + pr_info("vgsp-gr: inline-QMD dest va=0x%llx hpa=0x%llx -> 0x%llx (shadow=%u)\n", + req->qmd_va, req->qmd_hpa, qmd_dst, n_shadow); + } + + /* * Channel release: author it into the guest semaphore page when the * caller resolved one, else into the module semaphore's second word. */ @@ -13380,9 +13413,12 @@ gr_page_unmapped: wmb(); words = gsp_phys_rmcall_build_gr_launch(methods, qmd, - GSP_PHYS_RMCALL_VA_SRC, + qmd_dst, ch_sem_va, want_ch); memcpy(gsp_phys_chunk_page_va(pb, 0), methods, words * 4); + pr_info("vgsp-gr: qmd w0..3=%08x %08x %08x %08x w4..7=%08x %08x %08x %08x w23..25=%08x %08x %08x w32/33=%08x %08x w48/49=%08x %08x\n", + qmd[0], qmd[1], qmd[2], qmd[3], qmd[4], qmd[5], qmd[6], qmd[7], + qmd[23], qmd[24], qmd[25], qmd[32], qmd[33], qmd[48], qmd[49]); ret = gsp_phys_rmcall_publish_locked(bar0, boot_stage.rmcall_va_pb, words, &sub); @@ -13436,6 +13472,41 @@ gr_page_unmapped: } } } + /* + * Post-mortem: if the IQ2M landed the QMD in the guest + * buffer, the inline window was processed; GP_GET shows + * the front-end consumed the entry; the release word is + * re-read one last time. + */ + { + u8 *ud = gsp_phys_chunk_page_va( + &boot_stage.rmcall_chunks + [GSP_PHYS_RMCALL_BUF_USERD], + 0); + u32 gpget_post = ud ? + get_unaligned_le32( + ud + GSP_PHYS_RMCALL_USERD_GPGET_OFF) + : 0; + u32 q0 = 0, q1 = 0, q23 = 0, q24 = 0, q25 = 0; + u32 relw = 0; + + if (req->qmd_hpa) { + u8 *qp = (u8 *)__va(req->qmd_hpa); + + q0 = get_unaligned_le32(qp); + q1 = get_unaligned_le32(qp + 4); + q23 = get_unaligned_le32(qp + 92); + q24 = get_unaligned_le32(qp + 96); + q25 = get_unaligned_le32(qp + 100); + } + if (qmd_rel_hpa) + relw = READ_ONCE( + *(u32 *)((u8 *)__va(qmd_rel_hpa) + + qmd_rel_off)); + pr_info("vgsp-gr: post-mortem gpget=%u->%u qmd_page w0=%08x w1=%08x w23..25=%08x %08x %08x relw=%08x\n", + sub.gpget, gpget_post, q0, q1, q23, q24, + q25, relw); + } poll = w1; ret = -ETIMEDOUT; goto out; |
