diff options
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 126 |
1 files changed, 126 insertions, 0 deletions
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 @@ -1065,6 +1065,111 @@ static void gsp_rm_handle_ce_get_fault_method_buffer_size( } /* + * 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) * * The guest asks GSP-RM (us) for the GMMU static info; kgmmu. pStaticInfo-> @@ -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, |
