diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-21 18:01:55 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-21 18:01:55 -0400 |
| commit | 6aadb593750736f239fd54a0ccef4b3834c08fc4 (patch) | |
| tree | 5b3d39d82a09cdfd3ca8022cd9c0f83040f23229 /kernel/gsp_rm_emulation.h | |
| parent | c8249854284c3e8181587b96e3c5b4177d705e0c (diff) | |
| download | open-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.h | 151 |
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_ */ |
