summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_rm_emulation.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-25 02:53:50 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-25 02:53:50 -0400
commit0abc562e1124d7a3b93f710b8552ec18a1993941 (patch)
tree9a81c5a6596eff17aa4d732612f83be6c1cdd18a /kernel/gsp_rm_emulation.c
parent93769b1e19b4ce2cf1738d72e600adc5a9ef315b (diff)
downloadopen-iov-0abc562e1124d7a3b93f710b8552ec18a1993941.tar.gz
open-iov-0abc562e1124d7a3b93f710b8552ec18a1993941.zip
gsp_rm: implement missing RM_CONTROL handlers for 570.144 guest driver
- Added TU104_CTRL_INTERNAL_MEMSYS_L2_INVALIDATE_EVICT (0x20800a6c) - Added TU104_CTRL_INTERNAL_GR_GET_FECS_TRACE_HW_ENABLE (0x20800a38) - Added TU104_CTRL_SYSTEM_MAP_SHARED_DATA (0x730151) - Fixed async RPCs (72 GSP_SET_SYSTEM_INFO, 73 SET_REGISTRY, 71 CONTINUATION_RECORD) to send SUCCESS replies instead of silent consume - Added explicit handlers for RPC 47 (UNLOADING_GUEST_DRIVER) and 70 (UPDATE_BAR_PDE) with proper reply semantics Guest driver was failing at GSP-RM level with unknown RPCs 47, 70, 72, 73. Channels registered then immediately unregistered. Now they should stay registered and complete initialization.
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
-rw-r--r--kernel/gsp_rm_emulation.c163
1 files changed, 147 insertions, 16 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index 5120d4e..eaa2ff5 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -940,6 +940,8 @@ static const char *gsp_rm_rpc_name(u32 function)
case GSPRM_RPC_FUNC_SET_PAGE_DIRECTORY: return "SET_PAGE_DIRECTORY";
case GSPRM_RPC_FUNC_UNSET_PAGE_DIRECTORY: return "UNSET_PAGE_DIRECTORY";
case GSPRM_RPC_FUNC_GSP_RM_CONTROL: return "GSP_RM_CONTROL";
+ case GSPRM_RPC_FUNC_UNLOADING_GUEST_DRIVER: return "UNLOADING_GUEST_DRIVER";
+ case GSPRM_RPC_FUNC_UPDATE_BAR_PDE: return "UPDATE_BAR_PDE";
default: return "UNKNOWN";
}
}
@@ -2341,6 +2343,99 @@ static void gsp_rm_handle_rm_alloc(struct gsp_emu_context *ctx,
kfree(reply);
}
+/* ============================================================
+ * Missing RM_CONTROL handlers for 570.144 guest driver
+ * ============================================================ */
+
+static void gsp_rm_handle_memsys_l2_invalidate_evict(struct gsp_emu_context *ctx,
+ const u8 *req_params, u32 params_size,
+ u32 *out_status,
+ u8 *out_params, u32 *out_params_size)
+{
+ /* NV2080_CTRL_INTERNAL_MEMSYS_L2_INVALIDATE_EVICT (0x20800a6c)
+ * Input: flags (NvU32)
+ * Output: none (just status)
+ * The guest driver invalidates/evicts L2 cache lines.
+ * For vGPU, we just acknowledge success - no actual L2 to invalidate.
+ */
+ const u32 *flags = (const u32 *)req_params;
+
+ nv_vgpu_info(ctx->vgpu, "GSPRM: MEMSYS_L2_INVALIDATE_EVICT flags=0x%x",
+ params_size >= 4 ? *flags : 0);
+
+ *out_status = 0; /* NV_OK */
+ *out_params_size = 0;
+}
+
+static void gsp_rm_handle_gr_get_fecs_trace_hw_enable(struct gsp_emu_context *ctx,
+ u32 sequence,
+ const u8 *req_params, u32 params_size,
+ u32 *out_status,
+ u8 *out_params, u32 *out_params_size)
+{
+ /* NV2080_CTRL_INTERNAL_GR_GET_FECS_TRACE_HW_ENABLE (0x20800a38)
+ * Input: grRouteInfo (aligned 8), bEnable (NvBool) - actually input is route info only
+ * Output: bEnable (NvBool) - returns current enable state
+ * The guest queries whether FECS context switch tracing is enabled.
+ * For vGPU, tracing is not supported, return disabled (0).
+ */
+ struct {
+ u64 grRouteInfo_base;
+ u64 grRouteInfo_size;
+ u64 grRouteInfo_alignment;
+ u32 grRouteInfo_addressSpace;
+ u32 grRouteInfo_cpuCacheAttrib;
+ u8 bEnable;
+ } *out = (void *)out_params;
+
+ /* Input parsing (optional) - grRouteInfo is 28 bytes aligned to 8 = 32 bytes */
+ /* struct NV2080_CTRL_INTERNAL_GR_FECS_TRACE_HW_ENABLE_PARAMS {
+ * NV_DECLARE_ALIGNED(NV2080_CTRL_GR_ROUTE_INFO grRouteInfo, 8);
+ * NvBool bEnable;
+ * };
+ * NV2080_CTRL_GR_ROUTE_INFO = { NvU64 base, size, alignment; NvU32 addressSpace, cpuCacheAttrib; }
+ */
+
+ nv_vgpu_info(ctx->vgpu, "GSPRM: GR_GET_FECS_TRACE_HW_ENABLE params_size=%u", params_size);
+
+ /* Return disabled (0) - no FECS tracing on vGPU */
+ memset(out, 0, sizeof(*out));
+ out->bEnable = 0;
+
+ *out_status = 0; /* NV_OK */
+ *out_params_size = sizeof(*out);
+}
+
+static void gsp_rm_handle_system_map_shared_data(struct gsp_emu_context *ctx,
+ u32 sequence,
+ const u8 *req_params, u32 params_size,
+ u32 *out_status,
+ u8 *out_params, u32 *out_params_size)
+{
+ /* NV0073_CTRL_CMD_SYSTEM_MAP_SHARED_DATA (0x730151)
+ * Input: memDescInfo (base, size, alignment, addressSpace, cpuCacheAttrib), subDeviceInstance, bMap
+ * Output: none (just status)
+ * The guest maps/unmaps shared system memory.
+ * For vGPU, we acknowledge success - no actual mapping needed.
+ */
+ struct {
+ u64 base;
+ u64 size;
+ u64 alignment;
+ u32 addressSpace;
+ u32 cpuCacheAttrib;
+ u32 subDeviceInstance;
+ u8 bMap;
+ } __attribute__((packed)) *in = (void *)req_params;
+
+ nv_vgpu_info(ctx->vgpu, "GSPRM: SYSTEM_MAP_SHARED_DATA base=0x%llx size=0x%llx subDev=%u bMap=%u",
+ in ? in->base : 0, in ? in->size : 0,
+ in ? in->subDeviceInstance : 0, in ? in->bMap : 0);
+
+ *out_status = 0; /* NV_OK */
+ *out_params_size = 0;
+}
+
static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx,
const u8 *elem, u32 sequence)
{
@@ -2501,6 +2596,24 @@ static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx,
reply + GSP_RM_CTRL_HDR_SIZE, &out_params_size);
break;
+ case TU104_CTRL_INTERNAL_MEMSYS_L2_INVALIDATE_EVICT:
+ gsp_rm_handle_memsys_l2_invalidate_evict(ctx,
+ req_data + GSP_RM_CTRL_HDR_SIZE, req.paramsSize,
+ &out_status, reply + GSP_RM_CTRL_HDR_SIZE, &out_params_size);
+ break;
+
+ case TU104_CTRL_INTERNAL_GR_GET_FECS_TRACE_HW_ENABLE:
+ gsp_rm_handle_gr_get_fecs_trace_hw_enable(ctx, sequence,
+ req_data + GSP_RM_CTRL_HDR_SIZE, req.paramsSize,
+ &out_status, reply + GSP_RM_CTRL_HDR_SIZE, &out_params_size);
+ break;
+
+ case TU104_CTRL_SYSTEM_MAP_SHARED_DATA:
+ gsp_rm_handle_system_map_shared_data(ctx, sequence,
+ req_data + GSP_RM_CTRL_HDR_SIZE, req.paramsSize,
+ &out_status, reply + GSP_RM_CTRL_HDR_SIZE, &out_params_size);
+ break;
+
default:
/* Unknown control command - return success with zeroed params.
* Do NOT echo the request: pure queries pass uninitialized
@@ -2754,10 +2867,14 @@ static void gsp_rm_handle_element(struct gsp_emu_context *ctx, const u8 *elem)
case GSPRM_RPC_FUNC_GSP_SET_SYSTEM_INFO:
case GSPRM_RPC_FUNC_SET_REGISTRY:
case GSPRM_RPC_FUNC_CONTINUATION_RECORD:
- /* Async init RPCs - fire and forget, just consume. */
- nv_vgpu_info(ctx->vgpu, "GSPRM: async RPC %s(%u) seq=%u len=%u consumed",
+ /* Async init RPCs - but driver expects a reply. Send SUCCESS. */
+ nv_vgpu_info(ctx->vgpu, "GSPRM: async RPC %s(%u) seq=%u len=%u -> SUCCESS reply",
gsp_rm_rpc_name(function), function, sequence,
hdr->length);
+ if (gsp_rm_send(ctx, function, sequence, 0, NULL, 0))
+ nv_vgpu_err(ctx->vgpu, "GSPRM: reply send failed fn=%u", function);
+ else
+ rm->rpcs_replied++;
return;
case GSPRM_RPC_FUNC_SET_GUEST_SYSTEM_INFO:
@@ -2788,24 +2905,38 @@ static void gsp_rm_handle_element(struct gsp_emu_context *ctx, const u8 *elem)
gsp_rm_handle_unset_page_directory(ctx, elem, sequence, hdr->length);
return;
+ case GSPRM_RPC_FUNC_UPDATE_BAR_PDE:
+ /* UPDATE_BAR_PDE: guest updates BAR page directory entries.
+ * For vGPU, we just acknowledge success. */
+ nv_vgpu_info(ctx->vgpu, "GSPRM: RPC UPDATE_BAR_PDE(%u) seq=%u len=%u -> SUCCESS",
+ function, sequence, hdr->length);
+ if (gsp_rm_send(ctx, function, sequence, 0, NULL, 0))
+ nv_vgpu_err(ctx->vgpu, "GSPRM: UPDATE_BAR_PDE reply send failed");
+ else
+ rm->rpcs_replied++;
+ return;
+
+ case GSPRM_RPC_FUNC_UNLOADING_GUEST_DRIVER:
+ /* UNLOADING_GUEST_DRIVER: log for unload-cycle debugging */
+ nv_vgpu_info(ctx->vgpu, "GSPRM: RPC UNLOADING_GUEST_DRIVER(%u) seq=%u cmd_read=%u stat_write=%u stat_seq=%u",
+ function, sequence,
+ rm->cmd_read, rm->stat_write, rm->stat_seq);
+ /* Small delay before UNLOADING replies: mitigates an intermittent
+ * driver-side reply-matching race in the cleanup path. */
+ udelay(2000);
+ if (gsp_rm_send(ctx, function, sequence, 0, NULL, 0))
+ nv_vgpu_err(ctx->vgpu, "GSPRM: UNLOADING reply send failed");
+ else
+ rm->rpcs_replied++;
+ return;
+
default:
/* Synchronous RPC: echo function+sequence with success so the
* driver's rpcRecvPoll completes. */
rm->unknown_rpcs++;
- if (function == 47) {
- /* UNLOADING_GUEST_DRIVER: log for unload-cycle debugging */
- nv_vgpu_info(ctx->vgpu, "GSPRM: RPC %s(%u) seq=%u cmd_read=%u stat_write=%u stat_seq=%u",
- gsp_rm_rpc_name(function), function, sequence,
- rm->cmd_read, rm->stat_write, rm->stat_seq);
- } else {
- nv_vgpu_info(ctx->vgpu, "GSPRM: RPC %s(%u) seq=%u len=%u -> generic SUCCESS reply (unknown #%llu)",
- gsp_rm_rpc_name(function), function, sequence,
- hdr->length, rm->unknown_rpcs);
- }
- /* Small delay before UNLOADING replies: mitigates an intermittent
- * driver-side reply-matching race in the cleanup path. */
- if (function == 47)
- udelay(2000);
+ nv_vgpu_info(ctx->vgpu, "GSPRM: RPC %s(%u) seq=%u len=%u -> generic SUCCESS reply (unknown #%llu)",
+ gsp_rm_rpc_name(function), function, sequence,
+ hdr->length, rm->unknown_rpcs);
if (gsp_rm_send(ctx, function, sequence, 0, NULL, 0))
nv_vgpu_err(ctx->vgpu, "GSPRM: reply send failed fn=%u", function);
else