summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-01 13:49:50 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-01 13:49:50 -0400
commit97e2d46daf7e26aface861bce24b767eaccc967c (patch)
treec45c2beaf9e941fb164d8a363ed6069d9ba48e4c /kernel/gsp_phys_booter.c
parent4254b221f393e5262083e5d7158110b934a52e57 (diff)
downloadopen-iov-97e2d46daf7e26aface861bce24b767eaccc967c.tar.gz
open-iov-97e2d46daf7e26aface861bce24b767eaccc967c.zip
gsp-phys: send the host default registry profile with RmDisableDisplay for GSP-RM init
The pre-boot SET_REGISTRY (function 73) submitted an empty PACKED_REGISTRY_TABLE. Replace it with the default registry profile the host driver sends before boot: the 35 default dword parameters from its parameter table plus RmDisableDisplay=1. The display key makes the GSP-RM display-presence check treat display as absent, so the display engine is removed during pre-init instead of being brought up on a headless boot. The payload is generated into kernel/gsp_phys_registry_img.h as a PACKED_REGISTRY_TABLE blob (8-byte header, 36 16-byte dword entries, NUL-terminated names after the array; values inline; no value bytes in the name blob, matching the reference packer): size 1342, numEntries 36, rpc.length 1374, one 4 KB element. fn72 is unchanged. The payload length is not 8-byte aligned (record 1390 -> 1392); the TX producer already zero-pads the kvzalloc'd staging record and folds the XOR checksum over the padded length, exactly like the reference producer zero-pads before _checkSum32, so no producer change is needed. The blob is static const data: no heap, no new stack frame, and a submit failure still aborts the boot. The prepared log line now prints the payload size and entry count.
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c48
1 files changed, 23 insertions, 25 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index d59da78..9a170c9 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -51,6 +51,7 @@
#include "gsp_phys_gpu.h"
#include "gsp_phys_booter_load_img.h"
#include "gsp_phys_gsp_rm_boot_img.h"
+#include "gsp_phys_registry_img.h"
static bool gsp_phys_boot_param;
module_param_named(gsp_phys_boot, gsp_phys_boot_param, bool, 0644);
@@ -504,10 +505,9 @@ struct gsp_phys_gsp_system_info {
* (g_os_nvoc.h:217-230; ABI checks gsp_abi_check.c:2126-2136). The header is
* 8 bytes: `size` is the total table size (header + entry array + name/value
* blob, entries[] = 16 bytes each) and `numEntries` the number of entries.
- * An empty table is size = 8, numEntries = 0 and is explicitly accepted by
- * the GSP-RM server: _rpcSetRegistry maps osUnpackageRegistry()'s
- * NV_WARN_NOTHING_TO_DO to "Registry is empty." and continues (the Nouveau
- * client is documented to send no keys). Payload 8 bytes, rpc.length = 40.
+ * The submitted payload is gsp_phys_registry_image[] (generated): 36 dword
+ * entries (the host driver's default profile plus RmDisableDisplay=1) with
+ * the NUL-terminated names and inline dword values after the entry array.
*/
struct gsp_phys_packed_registry_entry {
__le32 name_offset; /* offset from table base to the NUL-terminated name */
@@ -2984,17 +2984,15 @@ static void gsp_phys_preinit_fill_system_info(
* Queue the two pre-boot async init RPCs the reference calls
* kgspQueueAsyncInitRpcs (kernel_gsp.c:3358-3381): GSP_SET_SYSTEM_INFO (72,
* rpcGspSetSystemInfo_v17_00, 928-byte payload) then SET_REGISTRY (73,
- * rpcSetRegistry_v17_00, empty PACKED_REGISTRY_TABLE: size 8/numEntries 0,
- * which the GSP-RM server accepts and continues on). Both are fire-and-forget
- * (no rpc_result wait): the GSP-RM server's function table entries return
- * "nothing" and no reply is expected. The existing TX producer already has
- * submit-only semantics, so both records go through gsp_phys_queue_tx_submit
- * with increasing seqNum.
+ * rpcSetRegistry_v17_00, the host driver's default registry profile plus
+ * RmDisableDisplay=1). Both are fire-and-forget (no rpc_result wait): the
+ * GSP-RM server's function table entries return "nothing" and no reply is
+ * expected. The existing TX producer already has submit-only semantics, so
+ * both records go through gsp_phys_queue_tx_submit with increasing seqNum.
*/
static int gsp_phys_preinit_rpcs(void __iomem *bar0, struct pci_dev *pdev)
{
struct gsp_phys_gsp_system_info *info;
- struct gsp_phys_packed_registry_table *reg;
int ret;
info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -3029,23 +3027,23 @@ static int gsp_phys_preinit_rpcs(void __iomem *bar0, struct pci_dev *pdev)
}
/*
- * Empty registry table (size 8, numEntries 0): the reference CPU-RM
- * treats an empty local table as a warning, but the GSP-RM server
- * explicitly maps osUnpackageRegistry()'s NV_WARN_NOTHING_TO_DO to
- * "Registry is empty." and answers success, so the header-only form
- * is the minimal valid payload.
+ * Host default registry profile (36 dword entries, 1342 bytes): the
+ * host driver's default parameter table plus RmDisableDisplay=1. The
+ * display key makes the GSP-RM display-presence check treat display as
+ * absent so the display engine is removed during pre-init; the rest
+ * reproduces the stock host environment. The payload is the generated
+ * PACKED_REGISTRY_TABLE blob (header + entries + names), not aligned
+ * to 8 bytes; the TX producer zero-pads the staging copy and folds the
+ * checksum over the padded length, matching the reference checksum.
*/
- reg = kzalloc(sizeof(*reg), GFP_KERNEL);
- if (!reg)
- return -ENOMEM;
- reg->size = cpu_to_le32(sizeof(*reg));
- reg->num_entries = cpu_to_le32(0);
- pr_info("gsp-phys-boot: pre-boot SET_REGISTRY (fn%u) prepared: size=%u numEntries=0 (header-only table; GSP-RM accepts the empty case)\n",
- GSP_PHYS_RPC_FUNC_SET_REGISTRY, (unsigned int)sizeof(*reg));
+ pr_info("gsp-phys-boot: pre-boot SET_REGISTRY (fn%u) prepared: size=%u numEntries=%u (host default profile + RmDisableDisplay=1)\n",
+ GSP_PHYS_RPC_FUNC_SET_REGISTRY,
+ (unsigned int)GSP_PHYS_REGISTRY_IMAGE_SIZE,
+ get_unaligned_le32(gsp_phys_registry_image + 4));
ret = gsp_phys_queue_tx_submit(bar0,
GSP_PHYS_RPC_FUNC_SET_REGISTRY,
- reg, sizeof(*reg));
- kfree(reg);
+ gsp_phys_registry_image,
+ GSP_PHYS_REGISTRY_IMAGE_SIZE);
if (ret) {
pr_err("gsp-phys-boot: pre-boot SET_REGISTRY (fn%u) submit failed: %d\n",
GSP_PHYS_RPC_FUNC_SET_REGISTRY, ret);