/* SPDX-License-Identifier: BSD-3-Clause */ /* Copyright (c) 2026 Open-IOV contributors */ /* rm_api.h - minimal self-contained NVIDIA RM userspace client. * * ABI and control IDs mirror the NV570 SDK (nvos.h, ctrl2080*.h) but the * definitions live here so the tools build with no external SDK dependency. * This is the shared layer used by rmtool and rmtop; it is read-only by * design: it only allocates an RM client/device/subdevice and issues * read-only NV2080/NV0080 control queries. */ #ifndef RM_API_H #define RM_API_H #include typedef uint8_t NvU8; typedef uint16_t NvU16; typedef uint32_t NvU32; typedef uint64_t NvU64; typedef uint32_t NvHandle; typedef uint64_t NvP64; typedef uint32_t NvV32; /* NVIDIA escape encoding: _IOWR('F', nr, type) */ #define NV_IOCTL_MAGIC 'F' #define NV_IOCTL_BASE 200 #define NV_ESC_RM_ALLOC 0x2B #define NV_ESC_RM_CONTROL 0x2A #define NV_ESC_CHECK_VERSION_STR (NV_IOCTL_BASE + 10) #define NV_ESC_WAIT_OPEN_COMPLETE (NV_IOCTL_BASE + 18) /* RM classes used by the client ladder */ #define NV01_ROOT 0x00000000U #define NV01_ROOT_CLIENT 0x00000041U #define NV01_DEVICE_0 0x00000080U #define NV20_SUBDEVICE_0 0x00002080U /* NVOS21/NVOS64 match the running driver ABI (NV570 kernel nvos.h): both * carry paramsSize. The userspace SDK snapshot in-tree has an older layout; * using it results in the kernel rejecting the ioctl with EINVAL. */ typedef struct { NvHandle hRoot; NvHandle hObjectParent; NvHandle hObjectNew; NvV32 hClass; NvP64 pAllocParms __attribute__((aligned(8))); NvU32 paramsSize; NvV32 status; } NVOS21_PARAMETERS; #define NVOS64_FLAGS_NONE 0x00000000U #define NVOS64_FLAGS_FINN_SERIALIZED 0x00000001U typedef struct { NvHandle hRoot; NvHandle hObjectParent; NvHandle hObjectNew; NvV32 hClass; NvP64 pAllocParms __attribute__((aligned(8))); NvP64 pRightsRequested __attribute__((aligned(8))); NvU32 paramsSize; NvU32 flags; NvV32 status; } NVOS64_PARAMETERS; /* NVOS54 (NV04_CONTROL), standard nvos.h layout: sizeof = 32 */ typedef struct { NvHandle hClient; NvHandle hObject; NvV32 cmd; NvU32 flags; NvP64 params __attribute__((aligned(8))); NvU32 paramsSize; NvV32 status; } NVOS54_PARAMETERS; #define NV_RM_API_VERSION_STRING_LENGTH 64 #define NV_RM_API_VERSION_CMD_QUERY '2' #define NV_RM_API_VERSION_REPLY_RECOGNIZED 1U typedef struct { NvU32 cmd; NvU32 reply; char versionString[NV_RM_API_VERSION_STRING_LENGTH]; } nv_ioctl_rm_api_version_t; typedef struct { int rc; NvU32 adapterStatus; } nv_ioctl_wait_open_complete_t; typedef struct { NvU32 deviceId; NvHandle hClientShare; NvHandle hTargetClient; NvHandle hTargetDevice; NvV32 flags; NvU64 vaSpaceSize __attribute__((aligned(8))); NvU64 vaStartInternal __attribute__((aligned(8))); NvU64 vaLimitInternal __attribute__((aligned(8))); NvV32 vaMode; } NV0080_ALLOC_PARAMETERS; typedef struct { NvU32 subDeviceId; } NV2080_ALLOC_PARAMETERS; #define NV_IOCTL_RM_ALLOC21 \ _IOWR(NV_IOCTL_MAGIC, NV_ESC_RM_ALLOC, NVOS21_PARAMETERS) #define NV_IOCTL_RM_ALLOC64 \ _IOWR(NV_IOCTL_MAGIC, NV_ESC_RM_ALLOC, NVOS64_PARAMETERS) #define NV_IOCTL_RM_CONTROL \ _IOWR(NV_IOCTL_MAGIC, NV_ESC_RM_CONTROL, NVOS54_PARAMETERS) #define NV_IOCTL_CHECK_VERSION \ _IOWR(NV_IOCTL_MAGIC, NV_ESC_CHECK_VERSION_STR, \ nv_ioctl_rm_api_version_t) #define NV_IOCTL_WAIT_OPEN_COMPLETE \ _IOWR(NV_IOCTL_MAGIC, NV_ESC_WAIT_OPEN_COMPLETE, \ nv_ioctl_wait_open_complete_t) /* ------------------------------------------------------------------ */ /* Read-only NV2080/NV0080 controls used by the tools. */ /* ------------------------------------------------------------------ */ /* NV2080_CTRL_CMD_GPU_GET_INFO_V2 (subdevice, no embedded pointers) */ #define NV2080_CTRL_CMD_GPU_GET_INFO_V2 0x20800102U #define NV2080_CTRL_CMD_GPU_GET_NAME_STRING 0x20800110U #define NV2080_CTRL_CMD_GPU_QUERY_MODE 0x20800128U #define NV2080_CTRL_CMD_GPU_GET_ID 0x20800142U #define NV2080_CTRL_CMD_GPU_GET_ENGINES_V2 0x20800170U #define NV2080_CTRL_CMD_MC_GET_ARCH_INFO 0x20801701U #define NV2080_CTRL_CMD_FB_GET_INFO_V2 0x20801303U #define NV2080_CTRL_CMD_BUS_GET_PCI_INFO 0x20801801U #define NV2080_CTRL_CMD_TIMER_GET_TIME 0x20800403U #define NV2080_CTRL_CMD_FIFO_GET_DEVICE_INFO_TABLE 0x20801112U #define NV0080_CTRL_CMD_GPU_GET_CLASSLIST_V2 0x00000292U #define NV2080_CTRL_GPU_INFO_MAX_LIST_SIZE 0x41U #define NV2080_CTRL_GPU_INFO_INDEX_SYSMEM_ACCESS 0x1fU #define NV2080_CTRL_GPU_INFO_INDEX_GPU_SM_VERSION 0x2cU #define NV2080_CTRL_GPU_INFO_INDEX_GPU_FLA_CAPABILITY 0x2dU #define NV2080_CTRL_GPU_INFO_INDEX_4K_PAGE_ISOLATION_REQUIRED 0x33U #define NV2080_CTRL_GPU_INFO_INDEX_DISPLAY_ENABLED 0x34U #define NV2080_CTRL_GPU_INFO_INDEX_GPU_PROFILING_CAPABILITY 0x36U #define NV2080_CTRL_GPU_INFO_INDEX_GPU_DEBUGGING_CAPABILITY 0x37U #define NV2080_CTRL_GPU_INFO_INDEX_CMP_SKU 0x3cU #define NV2080_CTRL_GPU_INFO_INDEX_DMABUF_CAPABILITY 0x3dU typedef struct { NvU32 index; NvU32 data; } NV2080_CTRL_GPU_INFO; typedef struct { NvU32 gpuInfoListSize; NV2080_CTRL_GPU_INFO gpuInfoList[NV2080_CTRL_GPU_INFO_MAX_LIST_SIZE]; } NV2080_CTRL_GPU_GET_INFO_V2_PARAMS; #define NV2080_GPU_MAX_NAME_STRING_LENGTH 0x40U typedef struct { NvU32 gpuNameStringFlags; union { NvU8 ascii[NV2080_GPU_MAX_NAME_STRING_LENGTH]; NvU16 unicode[NV2080_GPU_MAX_NAME_STRING_LENGTH]; } gpuNameString; } NV2080_CTRL_GPU_GET_NAME_STRING_PARAMS; typedef struct { NvU32 gpuId; } NV2080_CTRL_GPU_GET_ID_PARAMS; typedef struct { NvU32 mode; } NV2080_CTRL_GPU_QUERY_MODE_PARAMS; #define NV2080_GPU_MAX_ENGINES_LIST_SIZE 0x54U typedef struct { NvU32 engineCount; NvU32 engineList[NV2080_GPU_MAX_ENGINES_LIST_SIZE]; } NV2080_CTRL_GPU_GET_ENGINES_V2_PARAMS; typedef struct { NvU32 architecture; NvU32 implementation; NvU32 revision; NvU8 subRevision; } NV2080_CTRL_MC_ARCH_INFO_PARAMS; #define NV2080_CTRL_FB_INFO_MAX_LIST_SIZE 0x39U #define NV2080_CTRL_FB_INFO_INDEX_TOTAL_RAM_SIZE 0x08U #define NV2080_CTRL_FB_INFO_INDEX_HEAP_SIZE 0x09U #define NV2080_CTRL_FB_INFO_INDEX_LARGEST_FREE_REGION_SIZE_KB 0x12U #define NV2080_CTRL_FB_INFO_INDEX_HEAP_FREE 0x16U #define NV2080_CTRL_FB_INFO_INDEX_BAR1_SIZE 0x05U #define NV2080_CTRL_FB_INFO_INDEX_BAR1_AVAIL_SIZE 0x1dU #define NV2080_CTRL_FB_INFO_INDEX_USABLE_RAM_SIZE 0x20U typedef struct { NvU32 index; NvU32 data; } NV2080_CTRL_FB_INFO; typedef struct { NvU32 fbInfoListSize; NV2080_CTRL_FB_INFO fbInfoList[NV2080_CTRL_FB_INFO_MAX_LIST_SIZE]; } NV2080_CTRL_FB_GET_INFO_V2_PARAMS; typedef struct { NvU32 pciDeviceId; NvU32 pciSubSystemId; NvU32 pciRevisionId; NvU32 pciExtDeviceId; } NV2080_CTRL_BUS_GET_PCI_INFO_PARAMS; typedef struct { NvU64 time_nsec __attribute__((aligned(8))); } NV2080_CTRL_TIMER_GET_TIME_PARAMS; /* NV2080_CTRL_FIFO_GET_DEVICE_INFO_TABLE: static engine table with names. * Sizes match tools/rmq/rmq.c, which has produced ground-truth on TU104. */ typedef struct { NvU32 engineData[16]; NvU32 pbdmaIds[2]; NvU32 pbdmaFaultIds[2]; NvU32 numPbdmas; char engineName[16]; } NV2080_FIFO_DEVICE_ENTRY; typedef struct { NvU32 baseIndex; NvU32 numEntries; NvU32 bMore; NV2080_FIFO_DEVICE_ENTRY entries[32]; } NV2080_CTRL_FIFO_GET_DEVICE_INFO_TABLE_PARAMS; #define NV0080_CTRL_GPU_CLASSLIST_MAX_SIZE 100U typedef struct { NvU32 numClasses; NvU32 classList[NV0080_CTRL_GPU_CLASSLIST_MAX_SIZE]; } NV0080_CTRL_GPU_GET_CLASSLIST_V2_PARAMS; /* ------------------------------------------------------------------ */ /* Client + GPU discovery */ /* ------------------------------------------------------------------ */ struct rm_client { int fd; /* /dev/nvidiactl control fd */ int gpu_fd; /* /dev/nvidiaN device fd (open-complete) */ NvU32 hClient; NvU32 hDevice; NvU32 hSubdevice; int gpu_minor; }; #define RM_MAX_GPUS 32 #define RM_BDF_LEN 32 #define RM_NAME_LEN 128 #define RM_UUID_LEN 96 #define RM_VBIOS_LEN 64 struct rm_gpu_desc { int minor; char bdf[RM_BDF_LEN]; char model[RM_NAME_LEN]; char uuid[RM_UUID_LEN]; char vbios[RM_VBIOS_LEN]; int irq; }; /* Open /dev/nvidiactl, bind a GPU (gpu_minor; <0 means 0), alloc the * root-client -> device -> subdevice ladder, and keep the matching * /dev/nvidiaN device fd open for the lifetime of the client. * dev_path (may be NULL) overrides the GPU device node. * Returns 0 on success, negative errno, or an RM status. */ int rm_client_open(struct rm_client *c, int gpu_minor, const char *dev_path); void rm_client_close(struct rm_client *c); /* Issue a control on hObject; returns the raw NV_STATUS (0 = NV_OK) and * stores -1 in *ioctl_ret on transport failure (NULL allowed). */ NvU32 rm_control(struct rm_client *c, NvU32 hObject, NvU32 cmd, void *params, NvU32 size, int *ioctl_ret); /* Scan the per-GPU information files under /proc/driver/nvidia (read-only, * no device access). */ int rm_scan_gpus(struct rm_gpu_desc *out, int max); /* True if cmd is on the read-only allowlist (see nv2080.c). */ int rm_control_is_readonly(NvU32 cmd); const char *rm_status_str(NvU32 status); #endif /* RM_API_H */