From c8ae334bcdf53976205f81bacf88926659052ff5 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Mon, 28 Sep 2026 15:50:57 -0400 Subject: gsp_rm: keep and log the CE fault method buffer memdescs (0xa06c010a) NVA06C_CTRL_CMD_INTERNAL_PROMOTE_FAULT_METHOD_BUFFERS is sent at channel-group allocation; it hands the GSP each runqueue's 12 KB CE fault method buffer as {base (GPU physical), size, alignment, addressSpace, cpuCacheAttrib} plus a bar2Addr. Parse and log them, and keep the last set per channel-group object so the addresses (guest structures we cannot otherwise enumerate) are available to the engine emulation. Live: two 12 KB buffers per group, base = guest PA, addressSpace = 1, buffers zeroed (no faults posted yet). --- kernel/gsp_rm_emulation.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'kernel') diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index 706bd81..d1d87e9 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -2463,6 +2463,77 @@ static void gsp_rm_handle_system_map_shared_data(struct gsp_emu_context *ctx, *out_params_size = 0; } +/* + * NVA06C_CTRL_CMD_INTERNAL_PROMOTE_FAULT_METHOD_BUFFERS (0xa06c010a) + * + * Sent at channel-group allocation: each runqueue's CE fault method buffer + * is handed to the GSP as a memdesc {base (GPU physical address), size, + * alignment, addressSpace, cpuCacheAttrib} plus a bar2Addr, so the GSP can + * bind them into the engine context. Keep the addresses (guest structures + * we otherwise cannot enumerate) and log them once. + * + * Params layout (88 bytes): memdesc[0] @0, memdesc[1] @32 (each = u64 base, + * u64 size, u64 alignment, u32 addressSpace, u32 cpuCacheAttrib), + * bar2Addr[2] @64, numValidEntries @80. + */ +#define GSPRM_CTRL_PROMOTE_FAULT_METHOD_BUFFERS 0xa06c010a +#define GSPRM_FAULT_MBUFS_MAX 8 +#define GSPRM_FAULT_MBUFS_PER 2 + +struct gsp_rm_fault_mbuf { + u32 h_object; + u32 h_client; + u32 n; + struct { + u64 base; + u64 size; + u32 address_space; + } e[GSPRM_FAULT_MBUFS_PER]; +}; + +static struct gsp_rm_fault_mbuf gsp_rm_fault_mbufs[GSPRM_FAULT_MBUFS_MAX]; +static u32 gsp_rm_fault_mbufs_n; + +static void +gsp_rm_handle_promote_fault_method_buffers(struct gsp_emu_context *ctx, + const struct gsp_rm_control_req *req, + const u8 *p, u32 len) +{ + struct gsp_rm_fault_mbuf *m = NULL; + u32 i, n = 0; + + if (len < 84) + return; + + memcpy(&n, p + 80, 4); + if (n > GSPRM_FAULT_MBUFS_PER) + n = GSPRM_FAULT_MBUFS_PER; + + for (i = 0; i < gsp_rm_fault_mbufs_n; i++) { + if (gsp_rm_fault_mbufs[i].h_object == req->hObject) { + m = &gsp_rm_fault_mbufs[i]; + break; + } + } + if (!m && gsp_rm_fault_mbufs_n < GSPRM_FAULT_MBUFS_MAX) + m = &gsp_rm_fault_mbufs[gsp_rm_fault_mbufs_n++]; + if (!m) + return; + + m->h_object = req->hObject; + m->h_client = req->hClient; + m->n = n; + for (i = 0; i < n; i++) { + memcpy(&m->e[i].base, p + 32 * i, 8); + memcpy(&m->e[i].size, p + 32 * i + 8, 8); + memcpy(&m->e[i].address_space, p + 32 * i + 24, 4); + nv_vgpu_info(ctx->vgpu, + "GSPRM: FAULT_METHOD_BUFFER hObject=0x%x hClient=0x%x buf[%u] base=0x%llx size=%llu ap=%u", + req->hObject, req->hClient, i, m->e[i].base, + m->e[i].size, m->e[i].address_space); + } +} + static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx, const u8 *elem, u32 sequence) { @@ -2504,6 +2575,14 @@ static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx, out_params_size = 0; break; + case GSPRM_CTRL_PROMOTE_FAULT_METHOD_BUFFERS: + gsp_rm_handle_promote_fault_method_buffers( + ctx, &req, req_data + GSP_RM_CTRL_HDR_SIZE, + req.paramsSize); + out_status = 0; + out_params_size = req.paramsSize; + break; + case TU104_CTRL_INTERNAL_INTR_GET_KERNEL_TABLE: gsp_rm_handle_intr_kernel_table(ctx, sequence, &out_status, -- cgit v1.2.3