summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_rm_emulation.h
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-21 18:01:55 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-21 18:01:55 -0400
commit6aadb593750736f239fd54a0ccef4b3834c08fc4 (patch)
tree5b3d39d82a09cdfd3ca8022cd9c0f83040f23229 /kernel/gsp_rm_emulation.h
parentc8249854284c3e8181587b96e3c5b4177d705e0c (diff)
downloadopen-iov-6aadb593750736f239fd54a0ccef4b3834c08fc4.tar.gz
open-iov-6aadb593750736f239fd54a0ccef4b3834c08fc4.zip
kernel: GSP-RM msgq emulation + TU104 hardware tables (GET_GSP_STATIC_INFO, GSP_RM_CONTROL)
Implements the GSP-RM reply content layer for the msgq RPC channel: - kernel/gsp_rm_emulation.c/h: GSP-RM msgq emulation engine - Queue chain discovery (libos args → RMARGS → GSP_ARGUMENTS_CACHED) - Status queue link + GSP_INIT_DONE emission - Command queue polling + RPC dispatch - SET_GUEST_SYSTEM_INFO version negotiation (VGX 41.12) - GET_GSP_STATIC_INFO(65) with 1656-byte GspStaticConfigInfo - GSP_RM_CONTROL(76) sub-command dispatch: - FIFO_GET_DEVICE_INFO_TABLE (0x20801112) - INTERNAL_INTR_GET_KERNEL_TABLE (0x20800a5c) - GPU_GET_CONSTRUCTED_FALCON_INFO (0x208001b0) - INTERNAL_GET_DEVICE_INFO_TABLE (0x20800a40) - kernel/gsp_rm_tu104.h: TU104 hardware tables - 12-entry FIFO engine table (GR0, CE0-4, NVDEC0-1, NVENC0, SEC2, NVJPG, SW) - 8-entry interrupt table (from intr_phys_tu102.c) - 1-entry constructed falcon table (FBFLCN) - 11-entry internal device info table - GspStaticConfigInfo layout (1656 bytes, ABI-verified offsets) - Data from NVIDIA driver material (ext-tree) + hwref/turing/tu104 - tools/rmq/: Userspace RM API client (oracle for ground-truth tables) KNOWN ISSUE: gsp_rm_send crashes (fortify_panic) on multi-element messages when reply data exceeds one 4096-byte queue element. Affects cmd 0x20800a41 (paramsSize=8204). Multi-element splitting is the next fix.
Diffstat (limited to 'kernel/gsp_rm_emulation.h')
-rw-r--r--kernel/gsp_rm_emulation.h151
1 files changed, 151 insertions, 0 deletions
diff --git a/kernel/gsp_rm_emulation.h b/kernel/gsp_rm_emulation.h
new file mode 100644
index 0000000..b1a7259
--- /dev/null
+++ b/kernel/gsp_rm_emulation.h
@@ -0,0 +1,151 @@
+/*
+ * GSP-RM Emulation (physical-path) for Host-Side vGPU
+ *
+ * Emulates the GSP-RM firmware's msgq-based RPC channel for a guest driver
+ * that believes it is driving a real physical GPU. The guest driver:
+ * - boots the "GSP" (falcon stages emulated in gsp_emulation.c)
+ * - programs libos init args address into GSP MAILBOX0/1
+ * - expects GSP-RM to msgqInit the status queue in *guest system memory*
+ * (shared command/status queue buffer described by GSP_ARGUMENTS_CACHED)
+ * - polls the status queue for NV_VGPU_MSG_EVENT_GSP_INIT_DONE and then
+ * issues the RM RPC sequence on the command queue.
+ *
+ * Since there is no real GSP engine, this module performs the "virtual DMA"
+ * on behalf of the device using vfio_dma_rw() (CPU copies through the VFIO
+ * container's IOMMU mappings, IOVA == guest physical address).
+ */
+
+#ifndef _GSP_RM_EMULATION_H_
+#define _GSP_RM_EMULATION_H_
+
+#include <linux/types.h>
+
+#include "nvidia-vgpu-vfio.h"
+
+struct gsp_emu_context;
+
+/* Wire constants (from NVIDIA OpenRM 570.144 msgq/rpc headers - the guest
+ * driver is the 570.144 stock runfile, whose GSP_MSG_QUEUE_ELEMENT has NO
+ * MCTP/NVDM transport headers: authTag[16]+aad[16]+checkSum+seqNum+elemCount
+ * +rpc@0x30). */
+#define GSPRM_MSGQ_VERSION 0
+#define GSPRM_MSGQ_FLAGS_SWAP_RX 1
+#define GSPRM_RPC_SIGNATURE 0x43505256 /* NV_VGPU_MSG_SIGNATURE_VALID */
+#define GSPRM_RPC_HEADER_VERSION 0x03000000 /* MAJOR_TOT(3)<<24|MINOR_TOT(0)<<16 */
+
+/* RPC function/event numbers (rpc_global_enums.h) */
+#define GSPRM_RPC_FUNC_SET_GUEST_SYSTEM_INFO 1
+#define GSPRM_RPC_FUNC_ALLOC_ROOT 2
+#define GSPRM_RPC_FUNC_GET_GSP_STATIC_INFO 65
+#define GSPRM_RPC_FUNC_GSP_SET_SYSTEM_INFO 72
+#define GSPRM_RPC_FUNC_SET_REGISTRY 73
+#define GSPRM_RPC_FUNC_CONTINUATION_RECORD 71
+#define GSPRM_RPC_FUNC_GSP_RM_CONTROL 76
+#define GSPRM_RPC_EVENT_GSP_INIT_DONE 0x1001
+
+/* rpc_set_guest_system_info_v03_00: version fields the driver reads back
+ * from the reply to negotiate the RPC interface version (ipVersion). */
+#define GSPRM_SET_GUEST_INFO_SIZE 0x324
+#define GSPRM_VGX_VERSION_MAJOR 0x29
+#define GSPRM_VGX_VERSION_MINOR 0x0C
+
+/* "RMARGS" packed big-endian into u64 by _kgspGenerateInitArgId() */
+#define GSPRM_LIBOS_ID_RMARGS 0x524D41524753ULL
+
+#define GSPRM_MAX_LIBOS_REGIONS 32
+#define GSPRM_QUEUE_ELEMENT_SIZE 0x1000
+#define GSPRM_STATUS_QUEUE_SIZE 0x40000
+
+/* msgqTxHeader (msgq_priv.h) */
+struct gsprm_msgq_tx_header {
+ u32 version;
+ u32 size;
+ u32 msgSize;
+ u32 msgCount;
+ u32 writePtr;
+ u32 flags;
+ u32 rxHdrOff;
+ u32 entryOff;
+};
+
+/* rpc_message_header_v03_00 (g_rpc-message-header.h) */
+struct gsprm_rpc_header {
+ u32 header_version;
+ u32 signature;
+ u32 length;
+ u32 function;
+ u32 rpc_result;
+ u32 rpc_result_private;
+ u32 sequence;
+ u32 spare; /* rpc_message_rpc_union_field_v (spare/cpuRmGfid) */
+};
+
+/* LibosMemoryRegionInitArgument (libos_init_args.h) - natural alignment, 32B */
+struct gsprm_libos_region {
+ u64 id8;
+ u64 pa;
+ u64 size;
+ u8 kind;
+ u8 loc;
+ u8 pad[6];
+};
+
+/* MESSAGE_QUEUE_INIT_ARGUMENTS (gsp_init_args.h), x86_64 NvLength=u64 */
+struct gsprm_mq_init_args {
+ u64 sharedMemPhysAddr;
+ u32 pageTableEntryCount;
+ u32 pad0;
+ u64 cmdQueueOffset;
+ u64 statQueueOffset;
+ u64 queueElementHdrSize;
+ u64 queueElementSizeMin;
+ u64 queueElementSizeMax;
+ u32 queueHeaderAlign;
+ u32 queueElementAlign;
+};
+
+struct gsp_rm_emu {
+ struct nv_vgpu_device *vgpu;
+
+ bool parsed; /* queue chain parsed + status queue linked */
+ bool active;
+
+ u64 libos_args_gpa; /* from GSP MAILBOX0/1 */
+ u64 gsp_args_gpa; /* RMARGS region pa */
+
+ /* queue buffer description (from GSP_ARGUMENTS_CACHED) */
+ struct gsprm_mq_init_args mq;
+ u64 *ptes; /* pageTableEntryCount guest-phys addrs */
+
+ /* computed queue geometry. cmd_off/stat_off are offsets into the shared
+ * buffer (linear); GPAs must be computed per-access via the page table
+ * (buffer is NV_MEMORY_NONCONTIGUOUS). */
+ u64 cmd_off;
+ u64 stat_off;
+ u64 cmd_gpa; /* GPA of command queue base (diagnostic) */
+ u64 stat_gpa; /* GPA of status queue base (diagnostic) */
+ u32 cmd_size; /* bytes */
+ u32 stat_size; /* bytes */
+ u32 cmd_msgcount;
+ u32 stat_msgcount;
+ u32 entry_off; /* 0x1000 (msgq entryOff, both queues) */
+
+ /* GSP-side cursors */
+ u32 cmd_read; /* elements consumed from command queue */
+ u32 stat_write; /* elements written to status queue */
+ u32 stat_seq; /* status record sequence numbers */
+ bool init_done_sent;
+
+ /* stats */
+ u64 rpcs_seen;
+ u64 rpcs_replied;
+ u64 unknown_rpcs;
+};
+
+int gsp_rm_emu_init(struct nv_vgpu_device *vgpu, struct gsp_emu_context *ctx);
+void gsp_rm_emu_fini(struct gsp_emu_context *ctx);
+void gsp_rm_emu_reset(struct gsp_emu_context *ctx);
+void gsp_rm_emu_on_booter_done(struct gsp_emu_context *ctx);
+void gsp_rm_emu_poll(struct gsp_emu_context *ctx);
+
+#endif /* _GSP_RM_EMULATION_H_ */