summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-23 03:30:27 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-23 03:30:27 -0400
commitcba06da506d8e7a3f92d90f55d247ce870e76ee3 (patch)
treec7186702178b767e212be451d783ef141a7b64fd /kernel
parenta1d27eef42b8232e309eca7ecad5141026ee07db (diff)
downloadopen-iov-cba06da506d8e7a3f92d90f55d247ce870e76ee3.tar.gz
open-iov-cba06da506d8e7a3f92d90f55d247ce870e76ee3.zip
r524 the BINAPI-07 oracle client: build the captured real-client sequence on the live session (root -> device 0xcaf00000 -> subdevice 0xcaf00004 -> class-0x2081 child 0xcaf00099) and send the query as that client, so the server dispatches from a genuine BINAPI object
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_rm_emulation.c166
1 files changed, 122 insertions, 44 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index 2054086..37f7054 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -2967,13 +2967,126 @@ MODULE_PARM_DESC(gsp_rm_binapi07_fwd,
"Forward only the guest GL core's BINAPI 0x20810107 query to the live GSP session (default 0; diagnostic/experiment)");
/*
- * The live session's BINAPI object (class 0x2081) created on demand by the
- * 0x20810107 experiment; 0 until the first query allocates it. One device per
- * module load, so a file-static is enough; reset by unload.
+ * The live session's oracle client/object for the 0x20810107 experiment,
+ * created on demand; 0 until the first query builds it. One device per module
+ * load, so file-statics are enough; reset by unload.
*/
+static u32 gsp_rm_binapi07_be_client;
static u32 gsp_rm_binapi07_be_object;
/*
+ * One GSP_RM_ALLOC (fn 103) against the live backend, built exactly like the
+ * rm-call ladder's helper (rpc_gsp_rm_alloc_v03_00: hClient, hParent,
+ * hObject, hClass, status, paramsSize, flags, reserved[4] + params).
+ * object_is_out selects the reply read: a ROOT alloc returns the
+ * server-chosen client handle in params[0] (payload +32), anything else
+ * echoes the client-chosen hObject at +8; status is at +16 in both cases.
+ */
+static int gsp_rm_binapi07_backend_alloc(u32 h_client, u32 h_parent,
+ u32 h_object, u32 h_class,
+ const void *params, u32 params_len,
+ bool object_is_out,
+ u32 *out_object, u32 *out_status)
+{
+ u8 *areq;
+ void *arsp = NULL;
+ u32 arsp_len = 0, st = 0xffffffff, ho = 0;
+ int ret;
+
+ areq = kzalloc(32 + params_len, GFP_KERNEL);
+ if (!areq)
+ return -ENOMEM;
+ memcpy(areq + 0, &h_client, 4);
+ memcpy(areq + 4, &h_parent, 4);
+ memcpy(areq + 8, &h_object, 4);
+ memcpy(areq + 12, &h_class, 4);
+ memcpy(areq + 20, &params_len, 4);
+ if (params_len)
+ memcpy(areq + 32, params, params_len);
+
+ ret = gsp_phys_backend_rpc(GSPRM_RPC_FUNC_GSP_RM_ALLOC, areq,
+ 32 + params_len, &arsp, &arsp_len, 500);
+ kfree(areq);
+ if (!ret && arsp) {
+ if (arsp_len >= 20)
+ memcpy(&st, (u8 *)arsp + 16, 4);
+ if (object_is_out) {
+ if (arsp_len >= 36)
+ memcpy(&ho, (u8 *)arsp + 32, 4);
+ } else if (arsp_len >= 12) {
+ memcpy(&ho, (u8 *)arsp + 8, 4);
+ }
+ }
+ kfree(arsp);
+ if (out_object)
+ *out_object = ho;
+ if (out_status)
+ *out_status = st;
+ return ret;
+}
+
+/*
+ * Build the oracle client on the live session: the captured real-client
+ * sequence for a class-0x2081 consumer (root -> device 0xcaf00000 ->
+ * subdevice 0xcaf00004 -> class-0x2081 child). The subdevice attempt alone
+ * had answered NV_ERR_NOT_SUPPORTED (0x56) because the server dispatches the
+ * method from the OBJECT's class, so a real class-0x2081 object is needed.
+ * Returns 0 with *out_client/*out_object set on success.
+ */
+static int gsp_rm_binapi07_backend_setup(struct gsp_emu_context *ctx,
+ u32 *out_client, u32 *out_object)
+{
+ u8 p120[120], p56[56], p4[4];
+ u32 st = 0xffffffff, cli = 0, dev = 0xcaf00000u;
+ u32 sub = 0xcaf00004u, bin = 0xcaf00099u;
+ int ret;
+
+ /* 1. Root: hClient=0, the server picks and returns the handle. */
+ memset(p120, 0, sizeof(p120));
+ ret = gsp_rm_binapi07_backend_alloc(0, 0, 0, 0x0, p120, 120, true,
+ &cli, &st);
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: BINAPI-EXPERIMENT oracle root alloc: ret=%d status=0x%x hClient=0x%x",
+ ret, st, cli);
+ if (ret || st != 0 || !cli)
+ return -EIO;
+
+ /* 2. Device (class 0x80): deviceId 0, hClientShare = hClient. */
+ memset(p56, 0, sizeof(p56));
+ memcpy(p56 + 4, &cli, 4);
+ ret = gsp_rm_binapi07_backend_alloc(cli, cli, dev, 0x80, p56, 56,
+ false, &dev, &st);
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: BINAPI-EXPERIMENT oracle device alloc: ret=%d status=0x%x hDevice=0x%x",
+ ret, st, dev);
+ if (ret || st != 0 || !dev)
+ return -EIO;
+
+ /* 3. Subdevice (class 0x2080): subDeviceId 0. */
+ memset(p4, 0, sizeof(p4));
+ ret = gsp_rm_binapi07_backend_alloc(cli, dev, sub, 0x2080, p4, 4,
+ false, &sub, &st);
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: BINAPI-EXPERIMENT oracle subdevice alloc: ret=%d status=0x%x hSubdevice=0x%x",
+ ret, st, sub);
+ if (ret || st != 0 || !sub)
+ return -EIO;
+
+ /* 4. BINAPI (class 0x2081) under the subdevice, 4 zero params. */
+ ret = gsp_rm_binapi07_backend_alloc(cli, sub, bin, 0x2081, p4, 4,
+ false, &bin, &st);
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: BINAPI-EXPERIMENT oracle BINAPI alloc: ret=%d status=0x%x hObject=0x%x",
+ ret, st, bin);
+ if (ret || st != 0 || !bin)
+ return -EIO;
+
+ *out_client = cli;
+ *out_object = bin;
+ return 0;
+}
+
+/*
* Bounded logging for the P3 forward counters: the first four fallbacks (so a
* session that cannot forward is visible) and every 64th event. Never called
* when the parameter is off.
@@ -3073,48 +3186,12 @@ static bool gsp_rm_ctrl_forward(struct gsp_emu_context *ctx,
goto fallback;
if (guest_handles && !gsp_rm_binapi07_be_object) {
- /*
- * Allocate the backend's BINAPI object: rpc_gsp_rm_alloc_v03_00
- * { hClient, hParent, hObject=0, hClass, status, paramsSize=0,
- * flags, reserved[4] }. The guest's own alloc used the
- * SUBDEVICE as parent (hParent=0xbeef0004 where 0xbeef0004 is
- * the class-0x2080 child 0xbeef0003; the first attempt with the
- * device parent came back NV_ERR_INVALID_OBJECT_PARENT, 0x36),
- * so mirror that. The reply carries status at +16 and the
- * chosen handle at +32.
- */
- u8 *areq;
- void *arsp = NULL;
- u32 arsp_len = 0, ast = 0xffffffff, ah = 0;
- u32 acls = 0x2081;
+ u32 cli = 0, obj = 0;
- areq = kzalloc(32, GFP_KERNEL);
- if (!areq)
- goto fallback;
- memcpy(areq + 0, &snap.h_internal_client, 4);
- memcpy(areq + 4, &snap.h_internal_subdevice, 4);
- memcpy(areq + 12, &acls, 4);
- ret = gsp_phys_backend_rpc(GSPRM_RPC_FUNC_GSP_RM_ALLOC, areq,
- 32, &arsp, &arsp_len, 500);
- kfree(areq);
- if (!ret && arsp && arsp_len >= 32) {
- /*
- * An alloc with paramsSize=0 echoes the 32-byte
- * rpc_gsp_rm_alloc_v03_00: hObject (the chosen
- * handle) at +8, status at +16. (The rm-call ladder
- * reads +32 for ROOT allocs, whose params carry the
- * handle; with no params the reply is 32 B.)
- */
- memcpy(&ast, (u8 *)arsp + 16, 4);
- memcpy(&ah, (u8 *)arsp + 8, 4);
- }
- kfree(arsp);
- nv_vgpu_info(ctx->vgpu,
- "vgsp-rm: BINAPI-EXPERIMENT backend alloc class=0x2081 (ret=%d len=%u): status=0x%x hObject=0x%x",
- ret, arsp_len, ast, ah);
- if (ret || ast != 0 || !ah)
+ if (gsp_rm_binapi07_backend_setup(ctx, &cli, &obj))
goto fallback;
- gsp_rm_binapi07_be_object = ah;
+ gsp_rm_binapi07_be_client = cli;
+ gsp_rm_binapi07_be_object = obj;
}
/* Translate the guest's emulated internal handles; any other handle
@@ -3129,7 +3206,8 @@ static bool gsp_rm_ctrl_forward(struct gsp_emu_context *ctx,
if (!fwd_req)
goto fallback;
memset(&fwd_hdr, 0, sizeof(fwd_hdr));
- fwd_hdr.hClient = snap.h_internal_client;
+ fwd_hdr.hClient = guest_handles ? gsp_rm_binapi07_be_client :
+ snap.h_internal_client;
fwd_hdr.hObject = guest_handles ? gsp_rm_binapi07_be_object :
(req->hObject == TU104_H_INTERNAL_DEVICE ?
snap.h_internal_device : snap.h_internal_subdevice);