From 5367ffa2108fd9204d98f1cb23bb718a9143a25d Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 23 Sep 2026 01:26:25 -0400 Subject: kernel: serve CE caps + CE->PCE masks (unblocks UVM channel manager) kceGetDeviceCaps (kernel_ce.c) copies the caps the client hands to UVM from NV2080_CTRL_CMD_CE_GET_PHYSICAL_CAPS (0x20802a07), which reaches GSP-RM and was answered with zeros. With capsTbl = {0,0} no CE had the SYSMEM bit, so UVM's channel manager found no usable CE and UVM_REGISTER_GPU failed with NV_ERR_NOT_SUPPORTED ("Failed to initialize the channel manager", uvm_gpu.c:1574 - visible with uvm_debug_prints=1). New handlers: - CE_GET_PHYSICAL_CAPS (0x20802a07): {ceEngineType, capsTbl[2]} with SYSMEM_READ|SYSMEM_WRITE|SYSMEM|P2P|BL_GT_64K (0xEC) for COPY0..COPY4, NOT_SUPPORTED otherwise (matches subdeviceCtrlCmdCeGetCaps_IMPL). - CE_GET_ALL_CAPS (0x20802a0a) / CE_GET_ALL_PHYSICAL_CAPS (0x20802a0b): capsTbl[64][2] + present bitmap with the five CEs. - CE_GET_CE_PCE_MASK (0x20802a02): pceMask = BIT(ceIdx) (one PCE per LCE). Verified in-guest progress: UVM now gets past the channel manager and creates channels; the register path's new blocker is the first channel push (channel_init, uvm_channel.c:2535) whose semaphore release the emulated GPU must complete ("Tracker entry ... stuck waiting for 90s", sema VA 0x121000000 on channel 1:3 CE 0). --- kernel/gsp_rm_emulation.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/gsp_rm_tu104.h | 21 ++++++++ 2 files changed, 147 insertions(+) (limited to 'kernel') diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index c2b306a..e5c79f1 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -1064,6 +1064,111 @@ static void gsp_rm_handle_ce_get_fault_method_buffer_size( nv_vgpu_info(ctx->vgpu, "GSPRM: CE_GET_FAULT_METHOD_BUFFER_SIZE -> %u", val32); } +/* + * CE_GET_PHYSICAL_CAPS (0x20802a07) and friends + * + * kceGetDeviceCaps (kernel_ce.c) fills the CE caps the client hands to UVM + * from NV2080_CTRL_CMD_CE_GET_PHYSICAL_CAPS, which reaches GSP-RM. UVM's + * channel manager rejects any CE without the SYSMEM cap for its + * CPU_TO_GPU/GPU_TO_CPU channels ("Failed to initialize the channel manager: + * NV_ERR_NOT_SUPPORTED" in uvm_gpu.c) -- with the previous zeroed reply every + * CE was unusable and UVM_REGISTER_GPU failed with 0x56. + * + * params: { ceEngineType(4), capsTbl[2] } (NV2080_CTRL_CE_GET_CAPS_V2_PARAMS + * layout). Turing LCEs are sysmem-capable, P2P-capable and not GRCE. + */ +static void gsp_rm_handle_ce_physical_caps(struct gsp_emu_context *ctx, + const u8 *req_params, u32 req_size, + u32 *out_status, u8 *out_params, + u32 *out_params_size) +{ + u32 ce_type = 0; + + if (req_size >= 4) + memcpy(&ce_type, req_params, 4); + + memset(out_params, 0, 8); + memcpy(out_params + 0, &ce_type, 4); + + if (ce_type >= TU104_ENGINE_TYPE_COPY0 && + ce_type < TU104_ENGINE_TYPE_COPY0 + TU104_NUM_CES) { + out_params[4] = TU104_CE_CAPS0; + out_params[5] = TU104_CE_CAPS1; + } else { + *out_status = 0x56; /* NV_ERR_NOT_SUPPORTED */ + *out_params_size = req_size; + nv_vgpu_info(ctx->vgpu, "GSPRM: CE_GET_PHYSICAL_CAPS type=0x%x -> NOT_SUPPORTED", + ce_type); + return; + } + + *out_params_size = req_size ? req_size : 8; + *out_status = 0; + + nv_vgpu_info(ctx->vgpu, "GSPRM: CE_GET_PHYSICAL_CAPS type=0x%x -> caps=%02x %02x", + ce_type, out_params[4], out_params[5]); +} + +/* + * CE_GET_ALL_PHYSICAL_CAPS (0x20802a0b) / CE_GET_ALL_CAPS (0x20802a0a) + * + * params: NvU8 capsTbl[64][2] + NvU64 present (136 bytes). Report the five + * Turing CEs as present with the same caps as the per-CE query. + */ +static void gsp_rm_handle_ce_all_caps(struct gsp_emu_context *ctx, + u32 *out_status, u8 *out_params, + u32 *out_params_size) +{ + u64 present = 0; + u32 i; + + memset(out_params, 0, 136); + for (i = 0; i < TU104_NUM_CES; i++) { + out_params[i * 2 + 0] = TU104_CE_CAPS0; + out_params[i * 2 + 1] = TU104_CE_CAPS1; + present |= 1ULL << i; + } + memcpy(out_params + 128, &present, 8); + + *out_params_size = 136; + *out_status = 0; + + nv_vgpu_info(ctx->vgpu, "GSPRM: CE_GET_ALL(_PHYSICAL)_CAPS -> %u CEs present=0x%llx", + TU104_NUM_CES, present); +} + +/* + * CE_GET_CE_PCE_MASK (0x20802a02) + * + * params: { ceEngineType(4), pceMask(4) }. Each Turing LCE has its own PCE, + * so every CE maps to exactly one PCE bit. UVM's queryCopyEngines stores this + * in UvmGpuCopyEngineCaps.cePceMask. + */ +static void gsp_rm_handle_ce_pce_mask(struct gsp_emu_context *ctx, + const u8 *req_params, u32 req_size, + u32 *out_status, u8 *out_params, + u32 *out_params_size) +{ + u32 ce_type = 0, mask = 0; + + if (req_size >= 4) + memcpy(&ce_type, req_params, 4); + + if (ce_type >= TU104_ENGINE_TYPE_COPY0 && + ce_type < TU104_ENGINE_TYPE_COPY0 + TU104_NUM_CES) + mask = 1u << (ce_type - TU104_ENGINE_TYPE_COPY0); + + memset(out_params, 0, 8); + memcpy(out_params + 0, &ce_type, 4); + memcpy(out_params + 4, &mask, 4); + + *out_params_size = req_size ? req_size : 8; + *out_status = 0; + + nv_vgpu_info(ctx->vgpu, "GSPRM: CE_GET_CE_PCE_MASK type=0x%x -> 0x%x", + ce_type, mask); +} + /* * INTERNAL_GMMU_GET_STATIC_INFO (0x20800a59) * @@ -1582,6 +1687,27 @@ 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_CE_GET_PHYSICAL_CAPS: + gsp_rm_handle_ce_physical_caps(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_CE_GET_CE_PCE_MASK: + gsp_rm_handle_ce_pce_mask(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_CE_GET_ALL_CAPS: + case TU104_CTRL_CE_GET_ALL_PHYSICAL_CAPS: + gsp_rm_handle_ce_all_caps(ctx, + &out_status, + reply + GSP_RM_CTRL_HDR_SIZE, &out_params_size); + break; + case TU104_CTRL_INTERNAL_GMMU_GET_STATIC_INFO: gsp_rm_handle_gmmu_get_static_info(ctx, sequence, &out_status, diff --git a/kernel/gsp_rm_tu104.h b/kernel/gsp_rm_tu104.h index ab97307..9fd0443 100644 --- a/kernel/gsp_rm_tu104.h +++ b/kernel/gsp_rm_tu104.h @@ -700,6 +700,27 @@ static const struct tu104_internal_device_info tu104_internal_device_table[] = { #define TU104_CTRL_INTERNAL_DISPLAY_GET_IP_VERSION 0x20800a4b #define TU104_CTRL_I2C_TRANSACTION 0x402c0105 #define TU104_CTRL_CE_GET_FAULT_METHOD_BUFFER_SIZE 0x20802a08 +#define TU104_CTRL_CE_GET_PHYSICAL_CAPS 0x20802a07 +#define TU104_CTRL_CE_GET_ALL_PHYSICAL_CAPS 0x20802a0b +#define TU104_CTRL_CE_GET_ALL_CAPS 0x20802a0a +#define TU104_CTRL_CE_GET_CE_PCE_MASK 0x20802a02 + +/* CE capability bits (NV2080_CTRL_CE_CAPS_*, ctrl2080ce.h: byte:bit) */ +#define TU104_CE_CAPS0_SYSMEM_READ 0x04 +#define TU104_CE_CAPS0_SYSMEM_WRITE 0x08 +#define TU104_CE_CAPS0_SYSMEM 0x20 +#define TU104_CE_CAPS0_P2P 0x40 +#define TU104_CE_CAPS0_BL_GT_64K 0x80 +#define TU104_CE_CAPS0 (TU104_CE_CAPS0_SYSMEM_READ | \ + TU104_CE_CAPS0_SYSMEM_WRITE | \ + TU104_CE_CAPS0_SYSMEM | \ + TU104_CE_CAPS0_P2P | \ + TU104_CE_CAPS0_BL_GT_64K) +#define TU104_CE_CAPS1 0x00 + +/* ENGINE_TYPE_COPY0 = 0x9, COPY(i) = COPY0 + i (cl2080_notification.h) */ +#define TU104_ENGINE_TYPE_COPY0 0x00000009 +#define TU104_NUM_CES 5 #define TU104_CTRL_INTERNAL_GMMU_GET_STATIC_INFO 0x20800a59 #define TU104_CTRL_STATIC_KGR_GET_GLOBAL_SM_ORDER 0x20800a22 #define TU104_CTRL_STATIC_KGR_GET_INFO 0x20800a2a -- cgit v1.2.3