summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_rm_emulation.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
-rw-r--r--kernel/gsp_rm_emulation.c146
1 files changed, 143 insertions, 3 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index b8a3e37..7b7e230 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -2665,6 +2665,20 @@ static void gsp_rm_handle_kgr_get_context_buffers_info(
* L2/LTC topology from here. Echo the requested indices and fill in the
* emulated TU104 values.
*/
+/*
+ * m113: FB_GET_INFO_V2 COMPRESSION_SIZE (index 0x01, bytes). The header:
+ * "A return value of 0 indicates the GPU does not support compression" -
+ * but the guest driver still attempts a COMPR-enabled, 64 KB-aligned
+ * comptag allocation (vendor VidHeap alloc, attr COMPR=2) and fails it
+ * NV_ERR_NO_MEMORY (0x51) when the comptag pool has no space, which
+ * libcuda maps to VK_ERROR_OUT_OF_DEVICE_MEMORY (the vkAllocateMemory -2
+ * gate). Report a comptag pool sized like the real Turing parts (~fb/16).
+ * 0 = the historic "no compression" reply.
+ */
+static uint gsp_rm_fb_compr_mb = 128;
+module_param_named(wall2_fb_compr_mb, gsp_rm_fb_compr_mb, uint, 0644);
+MODULE_PARM_DESC(wall2_fb_compr_mb, "FB_GET_INFO_V2 COMPRESSION_SIZE in MiB (default 128, 0 = none)");
+
static u32 tu104_fb_info_data(struct gsp_emu_context *ctx, u32 index)
{
u64 fb = nv_vgpu_fb_emul_size(ctx->vgpu);
@@ -2673,7 +2687,8 @@ static u32 tu104_fb_info_data(struct gsp_emu_context *ctx, u32 index)
case TU104_FB_INFO_IDX_TILE_REGION_COUNT:
return 0;
case TU104_FB_INFO_IDX_COMPRESSION_SIZE:
- return 0;
+ /* m113: non-zero comptag pool (bytes) - see gsp_rm_fb_compr_mb. */
+ return gsp_rm_fb_compr_mb << 20;
case TU104_FB_INFO_IDX_PARTITION_COUNT:
return 1;
case TU104_FB_INFO_IDX_BAR1_SIZE:
@@ -3037,8 +3052,21 @@ static bool gsp_rm_is_channel_class(u32 class_id)
case 0x906f: /* MAXWELL_CHANNEL_GPFIFO_A */
case 0xa06f: /* KEPLER_CHANNEL_GPFIFO_A */
case 0xb06f: /* PASCAL_CHANNEL_GPFIFO_A */
- case 0xc06f: /* VOLTA_CHANNEL_GPFIFO_A */
+ case 0xc06f: /* VOLTA_CHANNEL_GPFIFO_A (PRE-TURING NAME) */
+ case 0xc36f: /* VOLTA_CHANNEL_GPFIFO_A */
+ /*
+ * r828: the RC watchdog's channel allocates 0xc36f on this
+ * device (the driver's gpfifoMapping loop picks the first
+ * class the gpu reports supported) - without it in this set
+ * the channel never reaches the progress service, its class2d
+ * notifier cycle (SET_NOTIFY_A/B + NOTIFY) never executes and
+ * the guest's krcWatchdog declares the GPU locked after its
+ * 7 s timeout as soon as robust channels are in play.
+ */
case 0xc46f: /* TURING_CHANNEL_GPFIFO_A */
+ case 0xc56f: /* AMPERE_CHANNEL_GPFIFO_A */
+ case 0xc86f: /* HOPPER_CHANNEL_GPFIFO_A */
+ case 0xc96f: /* BLACKWELL_CHANNEL_GPFIFO_A */
return true;
default:
return false;
@@ -3060,8 +3088,18 @@ static void gsp_rm_register_channel(struct gsp_emu_context *ctx, u32 h_object,
{
struct sema_channel_desc desc;
- if (params_size < GSPRM_CHAN_NOTIFIER_MEM + 8)
+ if (params_size < GSPRM_CHAN_NOTIFIER_MEM + 8) {
+ /*
+ * r828 diag: a channel-class alloc whose params are shorter
+ * than the notifier field is not registered, silently. The
+ * RC watchdog channel (hObject 0x31415900) never appeared in
+ * the sema table; name every such skip with its size so the
+ * shape question is answered by a log, not inference.
+ */
+ pr_info("vgsp-rm: channel alloc hObject=0x%x params_size=%u too short (< %u); NOT registered\n",
+ h_object, params_size, GSPRM_CHAN_NOTIFIER_MEM + 8);
return;
+ }
memset(&desc, 0, sizeof(desc));
desc.vgpu = ctx->vgpu;
@@ -3082,6 +3120,20 @@ static void gsp_rm_register_channel(struct gsp_emu_context *ctx, u32 h_object,
*/
if (desc.engine_type >= 1 && desc.engine_type <= 8)
desc.engine_type = 0;
+ /*
+ * r835: the channel's own address space (NV_CHANNEL_ALLOC_PARAMS:
+ * hContextShare @24, hVASpace @28 - confirmed by this struct's own
+ * known offsets: engineType @128 = 32 + 8 handles + 8 subdevice
+ * handles + 8 u64 userd offsets). Two clients map different objects
+ * at overlapping VAs (everyone's RM window sits at 0x1200xxxxx), so
+ * the global VA-keyed translation maps conflate them: the X server's
+ * ring VA resolved through the GL client's page tables (walk-probe:
+ * vas h=0xcaf00005 answered 0x120090000 with a zero page) and its
+ * push stream decoded as empty, wedging X exactly like the RC
+ * watchdog's ring. The service resolves a channel's VAs through this
+ * VAS first.
+ */
+ memcpy(&desc.h_vaspace, params + 28, 4);
memcpy(&desc.cid, params + GSPRM_CHAN_CID, 4);
memcpy(&desc.instance_pa, params + GSPRM_CHAN_INSTANCE_MEM, 8);
memcpy(&desc.userd_pa, params + GSPRM_CHAN_USERD_MEM, 8);
@@ -3505,6 +3557,41 @@ MODULE_PARM_DESC(wall2_a097_rec6, "0x2080a097 reply word at params+0x1c (0xfffff
module_param_named(wall2_a097_rec7, gsp_rm_a097_rec7, uint, 0644);
MODULE_PARM_DESC(wall2_a097_rec7, "0x2080a097 reply word at params+0x20 (0xffffffff = echo)");
+/*
+ * m112b: the NV04_VID_HEAP_CONTROL enumeration pair 0x90960106/0x90960107
+ * (legacy NVOS32 VidHeap API, class 0x9096). libnvidia-eglcore (file offset
+ * 0x586d80) walks three heaps: per heap it queries 0x90960106 (12 bytes:
+ * {u32 firstIdx, u32 lastIdx}; the client then enumerates the heap's memory
+ * blocks by index via 0x90960107 (56 bytes) while firstIdx+1 <= idx <=
+ * lastIdx). The 56-byte block entry is read at +0x00/+0x08 (two u64s), +0x28
+ * (a u32 type compared against a table at eglcore 0x101b1c0) and +0x30 (a
+ * flag BYTE: when 0 the heap/block is skipped). The generic zero reply makes
+ * every heap look empty, the client concludes out-of-device-memory and
+ * vkAllocateMemory fails -2 WITHOUT any alloc reaching the emulation
+ * (dmesg-corroborated: only 0x9096* controls + a class 0xc5c0 alloc).
+ * Runtime-tunable so one boot can sweep reply variants (same pattern as the
+ * wall2_a097_* words).
+ */
+static uint gsp_rm_9096_lo; /* 0x90960106 firstIdx */
+static uint gsp_rm_9096_hi = 1; /* 0x90960106 lastIdx */
+module_param_named(wall2_9096_lo, gsp_rm_9096_lo, uint, 0644);
+MODULE_PARM_DESC(wall2_9096_lo, "0x90960106 reply firstIdx (default 0)");
+module_param_named(wall2_9096_hi, gsp_rm_9096_hi, uint, 0644);
+MODULE_PARM_DESC(wall2_9096_hi, "0x90960106 reply lastIdx (default 1)");
+static uint gsp_rm_9096_ent_addr; /* 0x90960107 entry +0x00 (u64) */
+module_param_named(wall2_9096_ent_addr, gsp_rm_9096_ent_addr, uint, 0644);
+MODULE_PARM_DESC(wall2_9096_ent_addr, "0x90960107 entry word at +0x00 (default 0)");
+static uint gsp_rm_9096_ent_size = 0x80000000u; /* entry +0x08 (u64) */
+module_param_named(wall2_9096_ent_size, gsp_rm_9096_ent_size, uint, 0644);
+MODULE_PARM_DESC(wall2_9096_ent_size, "0x90960107 entry word at +0x08 (default 0x80000000)");
+static uint gsp_rm_9096_ent_type = 3; /* entry +0x28 (u32) */
+module_param_named(wall2_9096_ent_type, gsp_rm_9096_ent_type, uint, 0644);
+MODULE_PARM_DESC(wall2_9096_ent_type, "0x90960107 entry word at +0x28 (default 3)");
+static uint gsp_rm_9096_ent_flag = 1; /* entry +0x30 (u8) */
+
+module_param_named(wall2_9096_ent_flag, gsp_rm_9096_ent_flag, uint, 0644);
+MODULE_PARM_DESC(wall2_9096_ent_flag, "0x90960107 entry flag byte at +0x30 (default 1)");
+
/*
* The live session's oracle client/object for the 0x20810107 experiment,
@@ -4217,6 +4304,18 @@ static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx,
"vgsp-rm: promote[%u] bufferId=%u bInitialize=%u bNonmapped=%u physAttr=0x%x pa=0x%llx va=0x%llx size=0x%llx",
i, bid, e[30], e[31], attr, pa,
eva, esz);
+ /*
+ * r820: register the driver's own statement
+ * of this kernel buffer's backing (r817
+ * Xorg GL init: the page-table walk answered
+ * a stale zero page for the pushbuffer VA
+ * while this entry named the real one; a
+ * userspace pin scanner can never cover
+ * kernel-owned buffers). See
+ * gsp_sema_service_promote_add().
+ */
+ gsp_sema_service_promote_add(eva, pa, esz,
+ attr, bid);
}
}
out_status = 0;
@@ -4348,6 +4447,47 @@ static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx,
break;
}
+ case 0x90960106: { /* NV04_VID_HEAP_CONTROL block-index range (m112b) */
+ u8 *rp = reply + GSP_RM_CTRL_HDR_SIZE;
+ const u8 *pp = req_data + GSP_RM_CTRL_HDR_SIZE;
+
+ if (req.paramsSize >= 12) {
+ memcpy(rp, pp, req.paramsSize);
+ *(u32 *)(rp + 0) = gsp_rm_9096_lo;
+ *(u32 *)(rp + 4) = gsp_rm_9096_hi;
+ if (gsp_sema_dbg)
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: ctrl 0x90960106 -> first=%u last=%u",
+ gsp_rm_9096_lo, gsp_rm_9096_hi);
+ }
+ out_status = 0;
+ out_params_size = req.paramsSize;
+ break;
+ }
+
+ case 0x90960107: { /* NV04_VID_HEAP_CONTROL block entry by index (m112b) */
+ u8 *rp = reply + GSP_RM_CTRL_HDR_SIZE;
+ const u8 *pp = req_data + GSP_RM_CTRL_HDR_SIZE;
+
+ if (req.paramsSize >= 56) {
+ memcpy(rp, pp, req.paramsSize);
+ *(u64 *)(rp + 0x00) = (u64)gsp_rm_9096_ent_addr;
+ *(u64 *)(rp + 0x08) = (u64)gsp_rm_9096_ent_size;
+ *(u32 *)(rp + 0x28) = gsp_rm_9096_ent_type;
+ *(u8 *)(rp + 0x30) = (u8)gsp_rm_9096_ent_flag;
+ if (gsp_sema_dbg)
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: ctrl 0x90960107 -> addr=0x%x size=0x%x type=%u flag=%u",
+ gsp_rm_9096_ent_addr,
+ gsp_rm_9096_ent_size,
+ gsp_rm_9096_ent_type,
+ gsp_rm_9096_ent_flag);
+ }
+ out_status = 0;
+ out_params_size = req.paramsSize;
+ break;
+ }
+
default:
/* Unknown control command - return success with zeroed params.
* Do NOT echo the request: pure queries pass uninitialized