summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_rm_emulation.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-30 14:40:01 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-30 14:40:01 -0400
commit50e54ed1ee3cd7827d01458f8b3b2b22eff833b8 (patch)
tree7bda7aa848a15790eafb3fa7e856093d6f7b9f57 /kernel/gsp_rm_emulation.c
parent62407c334edfb47cf69bf660c7c0d5f06999d10c (diff)
downloadopen-iov-50e54ed1ee3cd7827d01458f8b3b2b22eff833b8.tar.gz
open-iov-50e54ed1ee3cd7827d01458f8b3b2b22eff833b8.zip
GSPRM CLK legacy controls: populate the domain queries the runtime clock helper gates on
The static CUDA runtime's device init failed with cudaErrorInitializationError even though every kernel ioctl returned 0: cuInit succeeded and then cuDeviceGetAttribute(ECC_ENABLED=36) returned CUDA_ERROR_NOT_FOUND (500). Tracing libcuda's clock-domain helper (libcuda+0xe8c410) shows it issues the CLK legacy controls 0x20809009/0x20809064/0x20809001 and bails with 500 when the replies do not carry the expected domain bits/entries; the dependent attribute getters (ECC_ENABLED, TOTAL_CONSTANT_MEMORY) then abort init. Reply to the three queries with the minimal fields the helper checks: bits 32|34 present in 0x20809009, non-zero domain entries at offsets 12/20/28/36 of 0x20809064, and a matching selector in 0x20809001. No frequencies are fabricated (all other fields stay zero). Verified in the guest with the stock 570.144 static-cudart vectorAdd client: cudaGetDeviceCount -> rc=0 (ndev=1), cudaSetDevice, cudaFree, three cudaMallocs and both HtoD copies all return rc=0; the client then parks in cudaDeviceSynchronize waiting for the (not yet forwarded) kernel launch.
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
-rw-r--r--kernel/gsp_rm_emulation.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index ff65275..d6aef9e 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -2031,6 +2031,60 @@ static void gsp_rm_handle_fb_get_info_v2(struct gsp_emu_context *ctx,
}
/*
+ * CLK legacy domain queries (0x20809001 / 0x20809009 / 0x20809064)
+ *
+ * libcuda's clock-domain helper (libcuda+0xe8c410) walks these three queries
+ * before it will report clock/ECC/perf data. It requires:
+ * - 0x20809009: bits 32 and 34 set in the 8-byte reply (domain presence);
+ * - 0x20809064: non-zero domain entries at reply offsets 12, 20, 28, 36;
+ * - 0x20809001: a selector mask overlapping those entries.
+ * With the generic zero reply the helper returns CUDA_ERROR_NOT_FOUND, which
+ * makes the dependent device-attribute queries (ECC_ENABLED = attr 36,
+ * TOTAL_CONSTANT_MEMORY = attr 13) abort device initialization with
+ * cudaErrorInitializationError. Populate only the fields the checks read;
+ * clock rates stay zero (no fabricated frequencies).
+ */
+static void gsp_rm_handle_clk_domain_info(struct gsp_emu_context *ctx, u32 cmd,
+ u32 req_size,
+ u32 *out_status,
+ u8 *out_params,
+ u32 *out_params_size)
+{
+ u32 n = req_size ? req_size : 8;
+ u32 one = 1;
+
+ if (n > 4096)
+ n = 4096;
+ memset(out_params, 0, n);
+
+ if (cmd == TU104_CTRL_CLK_DOMAIN_MASK) {
+ u64 mask = (1ULL << 32) | (1ULL << 34);
+
+ if (n >= sizeof(mask))
+ memcpy(out_params, &mask, sizeof(mask));
+ } else if (cmd == TU104_CTRL_CLK_DOMAIN_DATA) {
+ if (n >= 16)
+ memcpy(out_params + 12, &one, sizeof(one));
+ if (n >= 24)
+ memcpy(out_params + 20, &one, sizeof(one));
+ if (n >= 32)
+ memcpy(out_params + 28, &one, sizeof(one));
+ if (n >= 40)
+ memcpy(out_params + 36, &one, sizeof(one));
+ } else { /* TU104_CTRL_CLK_DOMAIN_SEL */
+ if (n >= sizeof(one))
+ memcpy(out_params, &one, sizeof(one));
+ }
+
+ *out_params_size = n;
+ *out_status = 0;
+
+ if (gsp_sema_dbg)
+ nv_vgpu_info(ctx->vgpu, "GSPRM: CLK domain info cmd=0x%x size=%u",
+ cmd, n);
+}
+
+/*
* BUS_GET_INFO_V2 (0x20801823)
*
* Same flat index/data list pattern as FB_GET_INFO_V2. UVM's
@@ -2641,6 +2695,14 @@ 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_CLK_DOMAIN_MASK:
+ case TU104_CTRL_CLK_DOMAIN_DATA:
+ case TU104_CTRL_CLK_DOMAIN_SEL:
+ gsp_rm_handle_clk_domain_info(ctx, req.cmd, req.paramsSize,
+ &out_status,
+ reply + GSP_RM_CTRL_HDR_SIZE, &out_params_size);
+ break;
+
case TU104_CTRL_INTERNAL_DISPLAY_GET_STATIC_INFO:
gsp_rm_handle_display_get_static_info(ctx, sequence,
&out_status,