From b968c287865b8860e7938f56db3fa358c5bef66e Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 25 Sep 2026 02:53:50 -0400 Subject: 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. --- kernel/gsp_rm_emulation.c | 163 +++++++++++++++++++++++++++++++++++++++++----- kernel/gsp_rm_emulation.h | 2 + kernel/gsp_rm_tu104.h | 7 ++ 3 files changed, 156 insertions(+), 16 deletions(-) (limited to 'kernel') 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 diff --git a/kernel/gsp_rm_emulation.h b/kernel/gsp_rm_emulation.h index 9ff74e9..8b9612b 100644 --- a/kernel/gsp_rm_emulation.h +++ b/kernel/gsp_rm_emulation.h @@ -45,6 +45,8 @@ struct gsp_emu_context; #define GSPRM_RPC_FUNC_GSP_RM_CONTROL 76 #define GSPRM_RPC_FUNC_GSP_RM_ALLOC 103 #define GSPRM_RPC_FUNC_FREE 10 +#define GSPRM_RPC_FUNC_UNLOADING_GUEST_DRIVER 47 +#define GSPRM_RPC_FUNC_UPDATE_BAR_PDE 70 #define GSPRM_RPC_EVENT_POST_EVENT 0x1003 #define GSPRM_MAX_EVENTS 128 #define GSPRM_RPC_EVENT_GSP_INIT_DONE 0x1001 diff --git a/kernel/gsp_rm_tu104.h b/kernel/gsp_rm_tu104.h index 3ac01b7..593dfb3 100644 --- a/kernel/gsp_rm_tu104.h +++ b/kernel/gsp_rm_tu104.h @@ -971,6 +971,13 @@ struct tu104_gr_static_info { * Driver computes numGpcs from floorsweepingMasks.gpcMask - zero kills * krcWatchdogInit ("numGpcs > 0" assert -> RmInitAdapter bails). */ #define TU104_CTRL_STATIC_KGR_GET_FLOORSWEEPING_MASKS 0x20800a26 + +/* Missing RM_CONTROL commands observed in guest driver (570.144) */ +#define TU104_CTRL_INTERNAL_MEMSYS_L2_INVALIDATE_EVICT 0x20800a6c +#define TU104_CTRL_INTERNAL_GR_GET_FECS_TRACE_HW_ENABLE 0x20800a38 + +/* NV0073 (SYSTEM) interface */ +#define TU104_CTRL_SYSTEM_MAP_SHARED_DATA 0x730151 #define TU104_GR_MAX_GPC 12 #define TU104_GR_MAX_TPC_PER_GPC_COUNT 10 -- cgit v1.2.3