summaryrefslogtreecommitdiffstats
path: root/kernel/include
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-13 18:36:21 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-13 18:36:21 -0400
commit00e54c13c7c9030c4d5f7151467f2d85a3730e29 (patch)
tree17a45239df8d2e4912ff3697ed06e85a10b969de /kernel/include
downloadopen-iov-00e54c13c7c9030c4d5f7151467f2d85a3730e29.tar.gz
open-iov-00e54c13c7c9030c4d5f7151467f2d85a3730e29.zip
Initial commit: Open-IOV vGPU-IO complete stack
- Firmware decompilation: GSP 570.144W (28.5MB ELF, RV64IMAC), 132 decompiled C files - Kernel modules: nvidia.ko (34MB, OpenRM), open-iov-vfio.ko (2.8MB, VFIO mdev), gsp-vgpu.ko (1.8MB, guest driver) - Userspace: libiov.so/libvgpu.so (76KB), example_vgpu (28KB), rpc_emulator.c - PCI config space emulation (256B with PM, MSI, MSI-X, PCIe caps) - 12 RPC types fully mapped from firmware decompilation - BAR trap, WPR, scheduling, notification, migration emulation - Helper scripts: load_vgpu_stack, create_mdev, launch_qemu_vgpu, test_vgpu_stack, setup_guest_driver, unload_vgpu_stack - Architecture documentation - Wiki: 10 technical documents - Git LFS for large binaries (.ko, .bin, .iso, .img, .o, ghidra repos) - nvidia-open-gpu-kernel-modules as submodule
Diffstat (limited to 'kernel/include')
-rw-r--r--kernel/include/bar_emulation.h57
-rw-r--r--kernel/include/gsp_comm.h155
-rw-r--r--kernel/include/gsp_rpc_client.h313
-rw-r--r--kernel/include/gsp_rpc_integration.h97
-rw-r--r--kernel/include/ioctl.h105
-rw-r--r--kernel/include/irq.h45
-rw-r--r--kernel/include/memory.h45
-rw-r--r--kernel/include/migration.h75
-rw-r--r--kernel/include/nv-hypervisor.h93
-rw-r--r--kernel/include/nv-vgpu-vfio-interface.h83
-rw-r--r--kernel/include/nvidia-vgpu-vfio.h194
-rw-r--r--kernel/include/nvstatus.h123
-rw-r--r--kernel/include/nvtypes.h830
13 files changed, 2215 insertions, 0 deletions
diff --git a/kernel/include/bar_emulation.h b/kernel/include/bar_emulation.h
new file mode 100644
index 0000000..759fa25
--- /dev/null
+++ b/kernel/include/bar_emulation.h
@@ -0,0 +1,57 @@
+#ifndef _NV_VGPU_BAR_EMULATION_H_
+#define _NV_VGPU_BAR_EMULATION_H_
+
+#include "nvidia-vgpu-vfio.h"
+
+struct nv_vgpu_bar_emul_ctx {
+ struct nv_vgpu_device *vgpu;
+ void *bar0_shadow;
+ size_t bar0_shadow_size;
+ spinlock_t shadow_lock;
+
+ struct {
+ u32 offset;
+ u32 value;
+ bool is_write;
+ bool trapped;
+ } trap_regs[256];
+ int trap_count;
+};
+
+int nv_vgpu_bar_emul_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_bar_emul_cleanup(struct nv_vgpu_device *vgpu);
+
+int nv_vgpu_bar_trap_register(struct nv_vgpu_device *vgpu, int bar_idx,
+ u32 offset, u32 size);
+int nv_vgpu_bar_untrap_register(struct nv_vgpu_device *vgpu, int bar_idx,
+ u32 offset);
+
+int nv_vgpu_bar_emul_read(struct nv_vgpu_device *vgpu, int bar_idx,
+ u64 offset, void *val, size_t size);
+int nv_vgpu_bar_emul_write(struct nv_vgpu_device *vgpu, int bar_idx,
+ u64 offset, void *val, size_t size);
+
+int nv_vgpu_bar_emul_handle_fault(struct nv_vgpu_device *vgpu,
+ unsigned long addr, bool write);
+
+static inline u32 nv_vgpu_read_reg(void __iomem *base, u32 offset)
+{
+ return readl(base + offset);
+}
+
+static inline void nv_vgpu_write_reg(void __iomem *base, u32 offset, u32 val)
+{
+ writel(val, base + offset);
+}
+
+static inline u64 nv_vgpu_read_reg64(void __iomem *base, u32 offset)
+{
+ return readq(base + offset);
+}
+
+static inline void nv_vgpu_write_reg64(void __iomem *base, u32 offset, u64 val)
+{
+ writeq(val, base + offset);
+}
+
+#endif \ No newline at end of file
diff --git a/kernel/include/gsp_comm.h b/kernel/include/gsp_comm.h
new file mode 100644
index 0000000..622f298
--- /dev/null
+++ b/kernel/include/gsp_comm.h
@@ -0,0 +1,155 @@
+#ifndef _NV_VGPU_GSP_COMM_H_
+#define _NV_VGPU_GSP_COMM_H_
+
+#include "nvidia-vgpu-vfio.h"
+
+#define NV_VGPU_GSP_RPC_MAX_SIZE 4096
+#define NV_VGPU_GSP_RPC_TIMEOUT_MS 5000
+#define NV_VGPU_GSP_QUEUE_DEPTH 256
+
+#define NV_VGPU_GSP_DOORBELL_OFFSET 0x100000
+#define NV_VGPU_GSP_SHARED_MEM_OFFSET 0x200000
+#define NV_VGPU_GSP_SHARED_MEM_SIZE (64 * 1024)
+
+#define NV_VGPU_GSP_FIRMWARE_PATH "/lib/firmware/nvidia/tu102/gsp/"
+
+enum nv_vgpu_gsp_rpc_type {
+ NV_GSP_RPC_TYPE_ALLOC = 0x01,
+ NV_GSP_RPC_TYPE_FREE = 0x02,
+ NV_GSP_RPC_TYPE_MAP = 0x03,
+ NV_GSP_RPC_TYPE_UNMAP = 0x04,
+ NV_GSP_RPC_TYPE_PIN = 0x05,
+ NV_GSP_RPC_TYPE_UNPIN = 0x06,
+ NV_GSP_RPC_TYPE_SCHEDULE = 0x07,
+ NV_GSP_RPC_TYPE_YIELD = 0x08,
+ NV_GSP_RPC_TYPE_NOTIFY = 0x09,
+ NV_GSP_RPC_TYPE_BAR_TRAP = 0x0A,
+ NV_GSP_RPC_TYPE_MIGRATE = 0x0B,
+ NV_GSP_RPC_TYPE_DEBUG = 0xFF,
+};
+
+struct nv_vgpu_gsp_rpc_header {
+ u32 type;
+ u32 sequence;
+ u32 size;
+ u32 flags;
+ u64 timestamp;
+};
+
+struct nv_vgpu_gsp_rpc_msg {
+ struct nv_vgpu_gsp_rpc_header hdr;
+ u8 data[];
+};
+
+struct nv_vgpu_gsp_firmware {
+ void *bootloader;
+ size_t bootloader_size;
+ void *booter_load;
+ size_t booter_load_size;
+ void *gsp;
+ size_t gsp_size;
+};
+
+struct nv_vgpu_gsp_comm_ctx {
+ struct nv_vgpu_device *vgpu;
+
+ void __iomem *gsp_doorbell;
+ void __iomem *gsp_shared_mem;
+ size_t shared_mem_size;
+
+ struct mutex queue_lock;
+ struct list_head pending_queue;
+ struct list_head complete_queue;
+ atomic_t sequence_counter;
+
+ wait_queue_head_t wait_queue;
+
+ struct workqueue_struct *rpc_wq;
+ struct work_struct rpc_work;
+
+ struct delayed_work poll_work;
+ bool poll_active;
+
+ spinlock_t irq_lock;
+ bool irq_enabled;
+
+ struct nv_vgpu_gsp_firmware firmware;
+ bool firmware_loaded;
+};
+
+struct nv_vgpu_gsp_rpc_entry {
+ struct list_head list;
+ struct nv_vgpu_gsp_rpc_msg *msg;
+ struct completion done;
+ int result;
+};
+
+int nv_vgpu_gsp_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_gsp_cleanup(struct nv_vgpu_device *vgpu);
+
+int nv_vgpu_gsp_send_rpc(struct nv_vgpu_device *vgpu, void *msg, size_t size);
+int nv_vgpu_gsp_recv_rpc(struct nv_vgpu_device *vgpu, void *msg, size_t size, int timeout_ms);
+
+int nv_vgpu_gsp_alloc(struct nv_vgpu_device *vgpu, u64 size, u32 align, u64 *handle);
+int nv_vgpu_gsp_free(struct nv_vgpu_device *vgpu, u64 handle);
+int nv_vgpu_gsp_map(struct nv_vgpu_device *vgpu, u64 handle, u64 iova, u64 size, u32 flags);
+int nv_vgpu_gsp_unmap(struct nv_vgpu_device *vgpu, u64 handle, u64 iova, u64 size);
+int nv_vgpu_gsp_schedule(struct nv_vgpu_device *vgpu, u32 runlist_id, u32 channel_id);
+int nv_vgpu_gsp_notify_bar_trap(struct nv_vgpu_device *vgpu, u64 offset, u32 size, void *val);
+
+int nv_vgpu_gsp_load_firmware(struct nv_vgpu_device *vgpu);
+void nv_vgpu_gsp_release_firmware(struct nv_vgpu_device *vgpu);
+int nv_vgpu_gsp_boot(struct nv_vgpu_device *vgpu);
+
+/* ============================================================
+ * New Firmware-Decompiled RPC Operations (enhanced APIs)
+ * ============================================================ */
+
+int nv_vgpu_gsp_rpc_alloc(struct nv_vgpu_device *vgpu,
+ u64 size, u64 alignment, u32 mem_type,
+ u32 flags, u64 addr_hint, u32 pid,
+ u64 *gpu_va, u64 *handle, u64 *actual_size);
+
+int nv_vgpu_gsp_rpc_free(struct nv_vgpu_device *vgpu, u64 handle);
+
+int nv_vgpu_gsp_rpc_map(struct nv_vgpu_device *vgpu,
+ u64 handle, u64 gpu_va, u64 size,
+ u32 prot, u32 flags, u64 offset,
+ u64 *mapped_va);
+
+int nv_vgpu_gsp_rpc_unmap(struct nv_vgpu_device *vgpu,
+ u64 handle, u64 gpu_va, u64 size);
+
+int nv_vgpu_gsp_rpc_pin(struct nv_vgpu_device *vgpu,
+ u64 handle, u64 offset, u64 size,
+ u32 flags, u64 *dma_addr, u32 *num_pages);
+
+int nv_vgpu_gsp_rpc_unpin(struct nv_vgpu_device *vgpu,
+ u64 handle, u64 offset, u64 size);
+
+int nv_vgpu_gsp_rpc_schedule(struct nv_vgpu_device *vgpu,
+ u64 work_handle, u64 callback, u64 arg,
+ u32 priority, u32 flags);
+
+int nv_vgpu_gsp_rpc_yield(struct nv_vgpu_device *vgpu);
+
+int nv_vgpu_gsp_rpc_bar_trap(struct nv_vgpu_device *vgpu,
+ u64 bar_addr, u32 access_type, u32 size,
+ u64 value, u32 bar_num, u64 *ret_value);
+
+int nv_vgpu_gsp_rpc_migrate_save(struct nv_vgpu_device *vgpu,
+ u64 src_gpu_id, u64 dst_gpu_id,
+ u64 memory_bitmap, u64 page_table_ptr,
+ u64 *checkpoint);
+
+int nv_vgpu_gsp_rpc_migrate_restore(struct nv_vgpu_device *vgpu,
+ u64 src_gpu_id, u64 dst_gpu_id,
+ u64 memory_bitmap, u64 page_table_ptr,
+ u64 checkpoint);
+
+static inline u32 nv_vgpu_gsp_next_sequence(struct nv_vgpu_gsp_comm_ctx *ctx)
+{
+ return atomic_inc_return(&ctx->sequence_counter);
+}
+
+#endif \ No newline at end of file
diff --git a/kernel/include/gsp_rpc_client.h b/kernel/include/gsp_rpc_client.h
new file mode 100644
index 0000000..4b48953
--- /dev/null
+++ b/kernel/include/gsp_rpc_client.h
@@ -0,0 +1,313 @@
+/*
+ * GSP 570.144W RPC Client Header
+ * Auto-generated from firmware decompilation
+ */
+
+#ifndef _GSP_RPC_CLIENT_H_
+#define _GSP_RPC_CLIENT_H_
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include "nvidia-vgpu-vfio.h"
+
+/* ============================================================
+ * FIRMWARE BASE ADDRESS
+ * ============================================================ */
+#define GSP_FW_BASE 0x04000000UL
+
+/* ============================================================
+ * RPC DISPATCHER ADDRESSES
+ * ============================================================ */
+
+/* Primary Dispatcher - Jump table switch for 6 RPC types */
+#define GSP_RPC_DISPATCH_PRIMARY (GSP_FW_BASE + 0x17A1AC0) /* 0x057a1ac0 */
+#define GSP_RPC_JUMP_TABLE (GSP_FW_BASE + 0x17A3AD8) /* 0x057a3ad8 - 32 sub-commands */
+
+/* Secondary Dispatcher - Full implementation for all 11 RPC types */
+#define GSP_RPC_DISPATCH_SECONDARY (GSP_FW_BASE + 0x0ED39DC) /* 0x04ed39dc */
+
+/* Tertiary Dispatcher - Stack=160 bytes */
+#define GSP_RPC_DISPATCH_TERTIARY (GSP_FW_BASE + 0x0CC58F8) /* 0x04cc58f8 */
+
+/* Quaternary Dispatcher - Stack=96 bytes */
+#define GSP_RPC_DISPATCH_QUATERNARY (GSP_FW_BASE + 0x1723EF4) /* 0x05723ef4 */
+
+/* ============================================================
+ * SPECIALIZED HANDLER ADDRESSES
+ * ============================================================ */
+
+#define GSP_ALLOC_MAIN (GSP_FW_BASE + 0x17E94EC) /* 0x057e94ec */
+#define GSP_SCHEDULE_MAIN (GSP_FW_BASE + 0x11EFBF4) /* 0x051efbf4 */
+#define GSP_BAR_TRAP_HANDLER_JT (GSP_FW_BASE + 0x17675B7) /* 0x057675b7 */
+#define GSP_BAR_TRAP_HANDLER_PRIM (GSP_FW_BASE + 0x0CB8189) /* 0x04cb8189 */
+#define GSP_PIN_HANDLER_SEC (GSP_FW_BASE + 0x0ED34B8) /* 0x04ed34b8 */
+
+/* Jump Table Handlers (from decoded table at 0x059bfeb0) */
+#define GSP_MAP_HANDLER_A (GSP_FW_BASE + 0x1766AB7) /* 0x05766ab7 */
+#define GSP_MAP_HANDLER_B (GSP_FW_BASE + 0x1778A37) /* 0x05778a37 */
+#define GSP_UNMAP_HANDLER_A (GSP_FW_BASE + 0x17669B7) /* 0x057669b7 */
+#define GSP_UNMAP_HANDLER_B (GSP_FW_BASE + 0x1779937) /* 0x05779937 */
+#define GSP_PIN_HANDLER_A (GSP_FW_BASE + 0x17664B7) /* 0x057664b7 */
+#define GSP_PIN_HANDLER_B (GSP_FW_BASE + 0x177A3B7) /* 0x0577a3b7 */
+#define GSP_UNPIN_HANDLER_A (GSP_FW_BASE + 0x17682B7) /* 0x057682b7 */
+#define GSP_UNPIN_HANDLER_B (GSP_FW_BASE + 0x1779FB7) /* 0x05779fb7 */
+#define GSP_SCHEDULE_HANDLER_A (GSP_FW_BASE + 0x1767F37) /* 0x05767f37 */
+#define GSP_SCHEDULE_HANDLER_B (GSP_FW_BASE + 0x175AEB7) /* 0x0575aeb7 */
+#define GSP_YIELD_HANDLER_A (GSP_FW_BASE + 0x175AE37) /* 0x0575ae37 */
+#define GSP_YIELD_HANDLER_B (GSP_FW_BASE + 0x1767337) /* 0x05767337 */
+#define GSP_NOTIFY_HANDLER_A (GSP_FW_BASE + 0x177C8B7) /* 0x0577c8b7 */
+#define GSP_NOTIFY_HANDLER_B (GSP_FW_BASE + 0x1767837) /* 0x05767837 */
+
+/* Entry Point */
+#define GSP_ENTRY_POINT (GSP_FW_BASE + 0x0009000) /* 0x04009000 */
+
+/* ============================================================
+ * RPC TYPE DEFINITIONS (match existing nv_vgpu_gsp_rpc_type)
+ * ============================================================ */
+enum gsp_rpc_type {
+ GSP_RPC_ALLOC = 0x01,
+ GSP_RPC_FREE = 0x02,
+ GSP_RPC_MAP = 0x03,
+ GSP_RPC_UNMAP = 0x04,
+ GSP_RPC_PIN = 0x05,
+ GSP_RPC_UNPIN = 0x06,
+ GSP_RPC_SCHEDULE = 0x07,
+ GSP_RPC_YIELD = 0x08,
+ GSP_RPC_NOTIFY = 0x09,
+ GSP_RPC_BAR_TRAP = 0x0A,
+ GSP_RPC_MIGRATE = 0x0B,
+ GSP_RPC_DEBUG = 0xFF,
+};
+
+/* ============================================================
+ * ALLOC SUB-COMMANDS (Primary Dispatcher Jump Table Indices)
+ * ============================================================ */
+enum gsp_alloc_subcmd {
+ GSP_ALLOC_SUBCMD_DEFAULT = 0,
+ GSP_ALLOC_SUBCMD_TYPE1 = 1,
+ GSP_ALLOC_SUBCMD_TYPE2 = 3,
+ GSP_ALLOC_SUBCMD_TYPE3 = 4,
+ GSP_ALLOC_SUBCMD_TYPE4 = 5,
+ GSP_ALLOC_SUBCMD_TYPE5 = 8,
+ GSP_ALLOC_SUBCMD_TYPE6 = 10,
+ GSP_ALLOC_SUBCMD_TYPE7 = 12,
+ GSP_ALLOC_SUBCMD_TYPE8 = 17,
+ GSP_ALLOC_SUBCMD_TYPE9 = 19,
+ GSP_ALLOC_SUBCMD_TYPE10 = 20,
+ GSP_ALLOC_SUBCMD_TYPE11 = 21,
+ GSP_ALLOC_SUBCMD_TYPE12 = 22,
+ GSP_ALLOC_SUBCMD_TYPE13 = 23,
+ GSP_ALLOC_SUBCMD_TYPE14 = 24,
+ GSP_ALLOC_SUBCMD_TYPE15 = 25,
+ GSP_ALLOC_SUBCMD_TYPE16 = 26,
+ GSP_ALLOC_SUBCMD_TYPE17 = 27,
+ GSP_ALLOC_SUBCMD_TYPE18 = 28,
+ GSP_ALLOC_SUBCMD_TYPE19 = 29,
+ GSP_ALLOC_SUBCMD_TYPE20 = 30,
+ GSP_ALLOC_SUBCMD_TYPE21 = 31,
+};
+
+/* ============================================================
+ * MIGRATE SUB-COMMANDS
+ * ============================================================ */
+enum gsp_migrate_subcmd {
+ GSP_MIGRATE_SUBCMD_SAVE = 0x04,
+ GSP_MIGRATE_SUBCMD_RESTORE = 0x05,
+};
+
+/* ============================================================
+ * PIN SUB-COMMANDS
+ * ============================================================ */
+enum gsp_pin_subcmd {
+ GSP_PIN_SUBCMD_DEFAULT = 0x05,
+};
+
+/* ============================================================
+ * SCHEDULE SUB-COMMANDS
+ * ============================================================ */
+enum gsp_sched_subcmd {
+ GSP_SCHED_SUBCMD_DEFAULT = 0x07,
+};
+
+/* ============================================================
+ * BAR TRAP SUB-COMMANDS
+ * ============================================================ */
+enum gsp_bar_trap_subcmd {
+ GSP_BAR_TRAP_SUBCMD_DEFAULT = 0x0A,
+};
+
+/* ============================================================
+ * RPC MESSAGE STRUCTURES
+ * ============================================================ */
+
+struct gsp_rpc_msg {
+ __le32 type;
+ __le32 subcmd;
+ __le64 payload[6];
+ __le32 seq_id;
+ __le32 flags;
+ __le32 reserved;
+} __attribute__((packed, aligned(8)));
+
+struct gsp_rpc_response {
+ __le32 status;
+ __le32 type;
+ __le64 result[6];
+ __le32 seq_id;
+} __attribute__((packed, aligned(8)));
+
+/* ALLOC request/response */
+struct gsp_alloc_req {
+ __le64 size;
+ __le64 alignment;
+ __le32 mem_type;
+ __le32 flags;
+ __le64 addr_hint;
+ __le32 pid;
+ __le32 reserved;
+} __attribute__((packed, aligned(8)));
+
+struct gsp_alloc_rsp {
+ __le64 gpu_va;
+ __le64 handle;
+ __le64 size;
+} __attribute__((packed, aligned(8)));
+
+/* MAP request/response */
+struct gsp_map_req {
+ __le64 handle;
+ __le64 gpu_va;
+ __le64 size;
+ __le32 prot;
+ __le32 flags;
+ __le64 offset;
+ __le32 reserved;
+} __attribute__((packed, aligned(8)));
+
+struct gsp_map_rsp {
+ __le64 gpu_va;
+} __attribute__((packed, aligned(8)));
+
+/* PIN/UNPIN request/response */
+struct gsp_pin_req {
+ __le64 handle;
+ __le64 offset;
+ __le64 size;
+ __le32 flags;
+ __le32 reserved[2];
+} __attribute__((packed, aligned(8)));
+
+struct gsp_pin_rsp {
+ __le64 dma_addr;
+ __le32 num_pages;
+ __le32 reserved;
+} __attribute__((packed, aligned(8)));
+
+/* SCHEDULE request */
+struct gsp_sched_req {
+ __le64 work_handle;
+ __le64 callback;
+ __le64 arg;
+ __le32 priority;
+ __le32 flags;
+ __le32 reserved[2];
+} __attribute__((packed, aligned(8)));
+
+/* BAR TRAP request/response */
+struct gsp_bar_trap_req {
+ __le64 bar_addr;
+ __le32 access_type;
+ __le32 size;
+ __le64 value;
+ __le32 bar_num;
+} __attribute__((packed, aligned(8)));
+
+struct gsp_bar_trap_rsp {
+ __le64 value;
+ __le32 handled;
+ __le32 reserved;
+} __attribute__((packed, aligned(8)));
+
+/* MIGRATE request/response */
+struct gsp_migrate_req {
+ __le64 src_gpu_id;
+ __le64 dst_gpu_id;
+ __le64 memory_bitmap;
+ __le64 page_table_ptr;
+ __le32 state;
+ __le32 flags;
+ __le64 context;
+ __le32 reserved;
+} __attribute__((packed, aligned(8)));
+
+struct gsp_migrate_rsp {
+ __le32 status;
+ __le32 progress;
+ __le64 checkpoint;
+} __attribute__((packed, aligned(8)));
+
+/* ============================================================
+ * CLIENT OPAQUE STRUCT
+ * ============================================================ */
+struct gsp_client;
+
+/* ============================================================
+ * PUBLIC API
+ * ============================================================ */
+
+/* Client lifecycle */
+struct gsp_client *gsp_client_init(struct device *dev, phys_addr_t fw_base, phys_addr_t doorbell);
+void gsp_client_fini(struct gsp_client *client);
+
+/* Memory management */
+int gsp_rpc_alloc(struct gsp_client *client,
+ u64 size, u64 alignment, u32 mem_type,
+ u32 flags, u64 addr_hint, u32 pid,
+ u64 *gpu_va, u64 *handle, u64 *actual_size);
+
+int gsp_rpc_free(struct gsp_client *client, u64 handle);
+
+int gsp_rpc_map(struct gsp_client *client,
+ u64 handle, u64 gpu_va, u64 size,
+ u32 prot, u32 flags, u64 offset,
+ u64 *mapped_va);
+
+int gsp_rpc_unmap(struct gsp_client *client, u64 handle, u64 gpu_va, u64 size);
+
+/* Page pinning */
+int gsp_rpc_pin(struct gsp_client *client,
+ u64 handle, u64 offset, u64 size,
+ u32 flags, u64 *dma_addr, u32 *num_pages);
+
+int gsp_rpc_unpin(struct gsp_client *client, u64 handle, u64 offset, u64 size);
+
+/* Scheduling */
+int gsp_rpc_schedule(struct gsp_client *client,
+ u64 work_handle, u64 callback, u64 arg,
+ u32 priority, u32 flags);
+
+int gsp_rpc_yield(struct gsp_client *client);
+
+/* BAR trap emulation */
+int gsp_rpc_bar_trap(struct gsp_client *client,
+ u64 bar_addr, u32 access_type, u32 size,
+ u64 value, u32 bar_num, u64 *ret_value);
+
+/* Migration */
+int gsp_rpc_migrate_save(struct gsp_client *client,
+ u64 src_gpu_id, u64 dst_gpu_id,
+ u64 memory_bitmap, u64 page_table_ptr,
+ u64 *checkpoint);
+
+int gsp_rpc_migrate_restore(struct gsp_client *client,
+ u64 src_gpu_id, u64 dst_gpu_id,
+ u64 memory_bitmap, u64 page_table_ptr,
+ u64 checkpoint);
+
+/* WPR Management */
+int gsp_wpr_write_mutex_acquire(struct gsp_client *client, u32 wpr_id);
+int gsp_wpr_write_mutex_release(struct gsp_client *client, u32 wpr_id);
+int gsp_wpr_scratch_mutex_acquire(struct gsp_client *client, u32 wpr_id);
+int gsp_wpr_scratch_mutex_release(struct gsp_client *client, u32 wpr_id);
+
+#endif /* _GSP_RPC_CLIENT_H_ */
diff --git a/kernel/include/gsp_rpc_integration.h b/kernel/include/gsp_rpc_integration.h
new file mode 100644
index 0000000..eea3bf3
--- /dev/null
+++ b/kernel/include/gsp_rpc_integration.h
@@ -0,0 +1,97 @@
+/*
+ * GSP RPC Integration Layer Header
+ * Bridges the firmware-decompiled RPC client with existing gsp_comm.c
+ */
+
+#ifndef _NV_VGPU_GSP_RPC_INTEGRATION_H_
+#define _NV_VGPU_GSP_RPC_INTEGRATION_H_
+
+#include "nvidia-vgpu-vfio.h"
+#include "gsp_comm.h"
+
+/* Initialize the RPC integration layer */
+int nv_vgpu_gsp_rpc_integration_init(struct nv_vgpu_device *vgpu,
+ struct nv_vgpu_gsp_comm_ctx *comm_ctx);
+
+/* Cleanup the RPC integration layer */
+void nv_vgpu_gsp_rpc_integration_cleanup(struct nv_vgpu_device *vgpu);
+
+/* ============================================================
+ * Enhanced RPC Operations (using firmware-decompiled addresses)
+ * ============================================================ */
+
+/* Memory allocation with full firmware parameter support */
+int nv_vgpu_gsp_rpc_alloc_fw(struct nv_vgpu_device *vgpu,
+ u64 size, u64 alignment, u32 mem_type,
+ u32 flags, u64 addr_hint, u32 pid,
+ u64 *gpu_va, u64 *handle, u64 *actual_size);
+
+/* Memory free */
+int nv_vgpu_gsp_rpc_free_fw(struct nv_vgpu_device *vgpu, u64 handle);
+
+/* Memory mapping with full firmware parameter support */
+int nv_vgpu_gsp_rpc_map_fw(struct nv_vgpu_device *vgpu,
+ u64 handle, u64 gpu_va, u64 size,
+ u32 prot, u32 flags, u64 offset,
+ u64 *mapped_va);
+
+/* Memory unmapping */
+int nv_vgpu_gsp_rpc_unmap_fw(struct nv_vgpu_device *vgpu,
+ u64 handle, u64 gpu_va, u64 size);
+
+/* Page pinning for DMA */
+int nv_vgpu_gsp_rpc_pin_fw(struct nv_vgpu_device *vgpu,
+ u64 handle, u64 offset, u64 size,
+ u32 flags, u64 *dma_addr, u32 *num_pages);
+
+/* Page unpinning */
+int nv_vgpu_gsp_rpc_unpin_fw(struct nv_vgpu_device *vgpu,
+ u64 handle, u64 offset, u64 size);
+
+/* Work scheduling */
+int nv_vgpu_gsp_rpc_schedule_fw(struct nv_vgpu_device *vgpu,
+ u64 work_handle, u64 callback, u64 arg,
+ u32 priority, u32 flags);
+
+/* Yield current work */
+int nv_vgpu_gsp_rpc_yield_fw(struct nv_vgpu_device *vgpu);
+
+/* BAR trap emulation */
+int nv_vgpu_gsp_rpc_bar_trap_fw(struct nv_vgpu_device *vgpu,
+ u64 bar_addr, u32 access_type, u32 size,
+ u64 value, u32 bar_num, u64 *ret_value);
+
+/* Migration - save state */
+int nv_vgpu_gsp_rpc_migrate_save_fw(struct nv_vgpu_device *vgpu,
+ u64 src_gpu_id, u64 dst_gpu_id,
+ u64 memory_bitmap, u64 page_table_ptr,
+ u64 *checkpoint);
+
+/* Migration - restore state */
+int nv_vgpu_gsp_rpc_migrate_restore_fw(struct nv_vgpu_device *vgpu,
+ u64 src_gpu_id, u64 dst_gpu_id,
+ u64 memory_bitmap, u64 page_table_ptr,
+ u64 checkpoint);
+
+/* ============================================================
+ * WPR Management (from firmware strings: VPR_WPR_WRITE_MUTEX*)
+ * ============================================================ */
+
+int nv_vgpu_gsp_wpr_write_mutex_acquire(struct nv_vgpu_device *vgpu, u32 wpr_id);
+int nv_vgpu_gsp_wpr_write_mutex_release(struct nv_vgpu_device *vgpu, u32 wpr_id);
+int nv_vgpu_gsp_wpr_scratch_mutex_acquire(struct nv_vgpu_device *vgpu, u32 wpr_id);
+int nv_vgpu_gsp_wpr_scratch_mutex_release(struct nv_vgpu_device *vgpu, u32 wpr_id);
+
+/* ============================================================
+ * Firmware Address Accessors (for debugging/validation)
+ * ============================================================ */
+
+u64 nv_vgpu_gsp_get_primary_dispatcher(void); /* 0x057a1ac0 */
+u64 nv_vgpu_gsp_get_secondary_dispatcher(void); /* 0x04ed39dc */
+u64 nv_vgpu_gsp_get_alloc_main(void); /* 0x057e94ec */
+u64 nv_vgpu_gsp_get_schedule_main(void); /* 0x051efbf4 */
+u64 nv_vgpu_gsp_get_bar_trap_handler_jt(void); /* 0x057675b7 */
+u64 nv_vgpu_gsp_get_bar_trap_handler_primary(void); /* 0x04cb8189 */
+u64 nv_vgpu_gsp_get_entry_point(void); /* 0x04009000 */
+
+#endif /* _NV_VGPU_GSP_RPC_INTEGRATION_H_ */
diff --git a/kernel/include/ioctl.h b/kernel/include/ioctl.h
new file mode 100644
index 0000000..4ff3df9
--- /dev/null
+++ b/kernel/include/ioctl.h
@@ -0,0 +1,105 @@
+#ifndef _NV_VGPU_IOCTL_H_
+#define _NV_VGPU_IOCTL_H_
+
+#include "nvidia-vgpu-vfio.h"
+
+#define NV_VGPU_IOCTL_MAGIC 'N'
+
+#define NV_VGPU_IOCTL_GET_INFO \
+ _IOWR(NV_VGPU_IOCTL_MAGIC, 0x01, struct nv_vgpu_ioctl_get_info)
+
+#define NV_VGPU_IOCTL_MAP_BAR \
+ _IOWR(NV_VGPU_IOCTL_MAGIC, 0x02, struct nv_vgpu_ioctl_map_bar)
+
+#define NV_VGPU_IOCTL_UNMAP_BAR \
+ _IOWR(NV_VGPU_IOCTL_MAGIC, 0x03, struct nv_vgpu_ioctl_unmap_bar)
+
+#define NV_VGPU_IOCTL_ENABLE_IRQ \
+ _IOWR(NV_VGPU_IOCTL_MAGIC, 0x04, struct nv_vgpu_ioctl_irq)
+
+#define NV_VGPU_IOCTL_DISABLE_IRQ \
+ _IOWR(NV_VGPU_IOCTL_MAGIC, 0x05, struct nv_vgpu_ioctl_irq)
+
+#define NV_VGPU_IOCTL_GSP_RPC \
+ _IOWR(NV_VGPU_IOCTL_MAGIC, 0x06, struct nv_vgpu_ioctl_gsp_rpc)
+
+#define NV_VGPU_IOCTL_MIGRATE_SAVE \
+ _IOWR(NV_VGPU_IOCTL_MAGIC, 0x07, struct nv_vgpu_ioctl_migrate)
+
+#define NV_VGPU_IOCTL_MIGRATE_RESTORE \
+ _IOWR(NV_VGPU_IOCTL_MAGIC, 0x08, struct nv_vgpu_ioctl_migrate)
+
+#define NV_VGPU_IOCTL_SET_GSP_FIRMWARE \
+ _IOWR(NV_VGPU_IOCTL_MAGIC, 0x09, struct nv_vgpu_ioctl_firmware)
+
+struct nv_vgpu_ioctl_get_info {
+ u32 vgpu_type;
+ u32 vgpu_id;
+ u32 gpu_instance_id;
+ u32 compute_instance_id;
+ u32 state;
+ u64 fb_base;
+ u64 fb_size;
+ u64 bar0_config_base;
+ u32 num_bars;
+ struct {
+ u32 index;
+ u64 gpa;
+ u64 size;
+ u64 iova;
+ bool mapped;
+ bool trapped;
+ } bars[NV_VGPU_MAX_REGIONS];
+};
+
+struct nv_vgpu_ioctl_map_bar {
+ u32 bar_index;
+ u64 gpa;
+ u64 size;
+ u64 iova;
+ u32 flags;
+};
+
+struct nv_vgpu_ioctl_unmap_bar {
+ u32 bar_index;
+ u64 iova;
+ u64 size;
+};
+
+struct nv_vgpu_ioctl_irq {
+ u32 irq_index;
+ int fd;
+};
+
+struct nv_vgpu_ioctl_gsp_rpc {
+ u32 type;
+ u32 flags;
+ u64 data_ptr;
+ u32 data_size;
+ u32 result;
+};
+
+struct nv_vgpu_ioctl_migrate {
+ u64 data_ptr;
+ u32 data_size;
+ u32 flags;
+ int result;
+};
+
+struct nv_vgpu_ioctl_firmware {
+ u32 chip_id;
+ u64 firmware_ptr;
+ u32 firmware_size;
+ u32 firmware_type;
+};
+
+int nv_vgpu_ioctl_get_info(struct nv_vgpu_device *vgpu, void __user *arg);
+int nv_vgpu_ioctl_map_bar(struct nv_vgpu_device *vgpu, void __user *arg);
+int nv_vgpu_ioctl_unmap_bar(struct nv_vgpu_device *vgpu, void __user *arg);
+int nv_vgpu_ioctl_enable_irq(struct nv_vgpu_device *vgpu, void __user *arg);
+int nv_vgpu_ioctl_disable_irq(struct nv_vgpu_device *vgpu, void __user *arg);
+int nv_vgpu_ioctl_gsp_rpc(struct nv_vgpu_device *vgpu, void __user *arg);
+int nv_vgpu_ioctl_migrate_save(struct nv_vgpu_device *vgpu, void __user *arg);
+int nv_vgpu_ioctl_migrate_restore(struct nv_vgpu_device *vgpu, void __user *arg);
+
+#endif \ No newline at end of file
diff --git a/kernel/include/irq.h b/kernel/include/irq.h
new file mode 100644
index 0000000..d06ac5b
--- /dev/null
+++ b/kernel/include/irq.h
@@ -0,0 +1,45 @@
+#ifndef _NV_VGPU_IRQ_H_
+#define _NV_VGPU_IRQ_H_
+
+#include "nvidia-vgpu-vfio.h"
+
+#define NV_VGPU_MAX_MSI_VECTORS 32
+
+struct nv_vgpu_msi_irq {
+ int virq;
+ u32 vector;
+ bool enabled;
+ struct eventfd_ctx *trigger;
+ struct irq_domain *domain;
+ struct msi_msg msg;
+};
+
+struct nv_vgpu_irq_ctx {
+ struct nv_vgpu_device *vgpu;
+ struct mutex lock;
+ struct nv_vgpu_msi_irq msis[NV_VGPU_MAX_MSI_VECTORS];
+ int msi_count;
+ bool msi_enabled;
+ bool msix_enabled;
+};
+
+int nv_vgpu_irq_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_irq_cleanup(struct nv_vgpu_device *vgpu);
+
+int nv_vgpu_irq_enable(struct nv_vgpu_device *vgpu, int irq_idx);
+int nv_vgpu_irq_disable(struct nv_vgpu_device *vgpu, int irq_idx);
+
+int nv_vgpu_irq_setup_msi(struct nv_vgpu_device *vgpu, int num_vectors);
+int nv_vgpu_irq_setup_msix(struct nv_vgpu_device *vgpu, int num_vectors);
+void nv_vgpu_irq_teardown_msi(struct nv_vgpu_device *vgpu);
+void nv_vgpu_irq_teardown_msix(struct nv_vgpu_device *vgpu);
+
+int nv_vgpu_irq_set_trigger(struct nv_vgpu_device *vgpu, int irq_idx, int fd);
+int nv_vgpu_irq_get_virq(struct nv_vgpu_device *vgpu, int irq_idx);
+
+static inline struct nv_vgpu_irq_ctx *vgpu_to_irq_ctx(struct nv_vgpu_device *vgpu)
+{
+ return (struct nv_vgpu_irq_ctx *)vgpu->irq_ctx;
+}
+
+#endif \ No newline at end of file
diff --git a/kernel/include/memory.h b/kernel/include/memory.h
new file mode 100644
index 0000000..14a35e9
--- /dev/null
+++ b/kernel/include/memory.h
@@ -0,0 +1,45 @@
+#ifndef _NV_VGPU_MEMORY_H_
+#define _NV_VGPU_MEMORY_H_
+
+#include "nvidia-vgpu-vfio.h"
+
+#define NV_VGPU_MAX_MAPPINGS 1024
+
+struct nv_vgpu_mapping {
+ u64 gpa;
+ u64 iova;
+ u64 size;
+ struct page **pages;
+ int page_count;
+ bool pinned;
+ bool mapped;
+ struct list_head list;
+};
+
+struct nv_vgpu_mm_ctx {
+ struct nv_vgpu_device *vgpu;
+ struct mutex lock;
+ struct list_head mappings;
+ u32 mapping_count;
+ struct iommu_domain *iommu_domain;
+ struct dma_iommu_mapping *dma_mapping;
+ bool use_simple;
+};
+
+int nv_vgpu_memory_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_memory_cleanup(struct nv_vgpu_device *vgpu);
+
+int nv_vgpu_memory_map(struct nv_vgpu_device *vgpu, u64 gpa, u64 size, u64 *iova);
+int nv_vgpu_memory_unmap(struct nv_vgpu_device *vgpu, u64 iova, u64 size);
+
+int nv_vgpu_memory_pin(struct nv_vgpu_device *vgpu, u64 gpa, u64 size);
+int nv_vgpu_memory_unpin(struct nv_vgpu_device *vgpu, u64 gpa, u64 size);
+
+int nv_vgpu_memory_mmap(struct nv_vgpu_device *vgpu, struct vm_area_struct *vma);
+
+static inline struct nv_vgpu_mm_ctx *vgpu_to_mm_ctx(struct nv_vgpu_device *vgpu)
+{
+ return vgpu->mm_ctx;
+}
+
+#endif \ No newline at end of file
diff --git a/kernel/include/migration.h b/kernel/include/migration.h
new file mode 100644
index 0000000..17cf8db
--- /dev/null
+++ b/kernel/include/migration.h
@@ -0,0 +1,75 @@
+#ifndef _NV_VGPU_MIGRATION_H_
+#define _NV_VGPU_MIGRATION_H_
+
+#include "nvidia-vgpu-vfio.h"
+
+#define NV_VGPU_MIGRATION_MAGIC 0x4E564750
+#define NV_VGPU_MIGRATION_VERSION 1
+
+struct nv_vgpu_migration_ctx {
+ struct nv_vgpu_device *vgpu;
+ struct mutex lock;
+ struct nv_vgpu_migration_state state;
+ struct task_struct *save_thread;
+ struct task_struct *restore_thread;
+ bool in_progress;
+};
+
+struct nv_vgpu_migration_header {
+ u32 magic;
+ u32 version;
+ u32 flags;
+ u32 num_sections;
+ u64 total_size;
+ u64 timestamp;
+};
+
+enum nv_vgpu_migration_section_type {
+ NV_VGPU_MIG_SECTION_DEVICE_STATE = 0x01,
+ NV_VGPU_MIG_SECTION_BAR_STATE = 0x02,
+ NV_VGPU_MIG_SECTION_MEMORY_STATE = 0x03,
+ NV_VGPU_MIG_SECTION_IRQ_STATE = 0x04,
+ NV_VGPU_MIG_SECTION_GSP_STATE = 0x05,
+ NV_VGPU_MIG_SECTION_ENGINE_STATE = 0x06,
+ NV_VGPU_MIG_SECTION_CHANNEL_STATE = 0x07,
+ NV_VGPU_MIG_SECTION_CONTEXT_STATE = 0x08,
+};
+
+struct nv_vgpu_migration_section {
+ u32 type;
+ u32 flags;
+ u64 offset;
+ u64 size;
+ u32 checksum;
+};
+
+struct nv_vgpu_migration_device_state {
+ u32 vgpu_type;
+ u32 vgpu_id;
+ u32 gpu_instance_id;
+ u32 compute_instance_id;
+ u32 state;
+ u64 fb_base;
+ u64 fb_size;
+ u64 bar0_config_base;
+};
+
+struct nv_vgpu_migration_bar_state {
+ u32 bar_index;
+ u64 gpa;
+ u64 size;
+ u64 iova;
+ u8 data[];
+};
+
+int nv_vgpu_migration_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_migration_cleanup(struct nv_vgpu_device *vgpu);
+
+int nv_vgpu_migration_save_state(struct nv_vgpu_device *vgpu, u8 **data, size_t *size);
+int nv_vgpu_migration_restore_state(struct nv_vgpu_device *vgpu, u8 *data, size_t size);
+
+int nv_vgpu_migration_prepare(struct nv_vgpu_device *vgpu);
+int nv_vgpu_migration_complete(struct nv_vgpu_device *vgpu);
+int nv_vgpu_migration_cancel(struct nv_vgpu_device *vgpu);
+
+#endif \ No newline at end of file
diff --git a/kernel/include/nv-hypervisor.h b/kernel/include/nv-hypervisor.h
new file mode 100644
index 0000000..a2b2649
--- /dev/null
+++ b/kernel/include/nv-hypervisor.h
@@ -0,0 +1,93 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 1999-2018 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _NV_HYPERVISOR_H_
+#define _NV_HYPERVISOR_H_
+
+#include <nv-kernel-interface-api.h>
+
+// Enums for supported hypervisor types.
+// New hypervisor type should be added before OS_HYPERVISOR_UNKNOWN
+typedef enum _HYPERVISOR_TYPE
+{
+ OS_HYPERVISOR_XEN = 0,
+ OS_HYPERVISOR_VMWARE,
+ OS_HYPERVISOR_HYPERV,
+ OS_HYPERVISOR_KVM,
+ OS_HYPERVISOR_UNKNOWN
+} HYPERVISOR_TYPE;
+
+#define CMD_VFIO_WAKE_REMOVE_GPU 1
+#define CMD_VGPU_VFIO_PRESENT 2
+#define CMD_VFIO_PCI_CORE_PRESENT 3
+
+#define MAX_VF_COUNT_PER_GPU 64
+
+typedef enum _VGPU_TYPE_INFO
+{
+ VGPU_TYPE_NAME = 0,
+ VGPU_TYPE_DESCRIPTION,
+ VGPU_TYPE_INSTANCES,
+} VGPU_TYPE_INFO;
+
+typedef struct
+{
+ void *nv;
+ NvU32 domain;
+ NvU32 bus;
+ NvU32 device;
+ NvU32 return_status;
+} vgpu_vfio_info;
+
+typedef struct
+{
+ NvU32 domain;
+ NvU8 bus;
+ NvU8 slot;
+ NvU8 function;
+ NvBool isNvidiaAttached;
+ NvBool isMdevAttached;
+} vgpu_vf_pci_info;
+
+typedef enum VGPU_CMD_PROCESS_VF_INFO_E
+{
+ NV_VGPU_SAVE_VF_INFO = 0,
+ NV_VGPU_REMOVE_VF_PCI_INFO = 1,
+ NV_VGPU_REMOVE_VF_MDEV_INFO = 2,
+ NV_VGPU_GET_VF_INFO = 3
+} VGPU_CMD_PROCESS_VF_INFO;
+
+typedef enum VGPU_DEVICE_STATE_E
+{
+ NV_VGPU_DEV_UNUSED = 0,
+ NV_VGPU_DEV_OPENED = 1,
+ NV_VGPU_DEV_IN_USE = 2
+} VGPU_DEVICE_STATE;
+
+/*
+ * Function prototypes
+ */
+
+HYPERVISOR_TYPE NV_API_CALL nv_get_hypervisor_type(void);
+
+#endif // _NV_HYPERVISOR_H_
diff --git a/kernel/include/nv-vgpu-vfio-interface.h b/kernel/include/nv-vgpu-vfio-interface.h
new file mode 100644
index 0000000..2553722
--- /dev/null
+++ b/kernel/include/nv-vgpu-vfio-interface.h
@@ -0,0 +1,83 @@
+/* SPDX-FileCopyrightText: Copyright (c) 2016-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef _NV_VGPU_VFIO_INTERFACE_H_
+#define _NV_VGPU_VFIO_INTERFACE_H_
+
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/mdev.h>
+#include <linux/vfio.h>
+
+/* Use standard kernel types */
+typedef int NV_STATUS;
+typedef unsigned char NvU8;
+typedef unsigned int NvU32;
+typedef unsigned short NvU16;
+typedef unsigned long long NvU64;
+typedef int NvS32;
+typedef unsigned char NvBool;
+
+#define NV_OK 0
+#define NV_ERR_NOT_SUPPORTED -1
+#define NV_ERR_GENERIC -2
+#define NV_ERR_INVALID_ARGUMENT -3
+#define NV_ERR_NO_MEMORY -4
+
+typedef enum {
+ VGPU_DEVICE_STATE_UNINITIALIZED = 0,
+ VGPU_DEVICE_STATE_INITIALIZING,
+ VGPU_DEVICE_STATE_READY,
+ VGPU_DEVICE_STATE_RUNNING,
+ VGPU_DEVICE_STATE_SUSPENDED,
+ VGPU_DEVICE_STATE_ERROR,
+ VGPU_DEVICE_STATE_MIGRATING,
+} VGPU_DEVICE_STATE;
+
+typedef NV_STATUS (*vgpu_vfio_probe_t)(struct pci_dev *, NvU32, NvU32 *);
+typedef void (*vgpu_vfio_remove_t)(struct pci_dev *);
+typedef NV_STATUS (*vgpu_vfio_inject_interrupt_t)(void *);
+
+typedef struct
+{
+ vgpu_vfio_probe_t probe;
+ vgpu_vfio_remove_t remove;
+ vgpu_vfio_inject_interrupt_t inject_interrupt;
+} vgpu_vfio_ops_t;
+
+typedef NV_STATUS (*vgpu_vfio_vgpu_create_t) (struct pci_dev *dev, const NvU8 *uuid,
+ NvU32 vgpu_type_id, NvU16 *vgpu_id,
+ NvU32 *gpu_pci_id, NvU32 gpu_pci_bdf);
+typedef NV_STATUS (*vgpu_vfio_vgpu_destroy_t) (const NvU8 *uuid, NvU16 vgpu_id);
+typedef NV_STATUS (*vgpu_vfio_start_t) (const NvU8 *uuid, void *wait_queue, NvS32 *return_status,
+ NvU8 *vm_name, NvU32 qemu_pid);
+typedef NV_STATUS (*vgpu_vfio_bar_info_t) (struct pci_dev *dev, const NvU8 *, NvU64 *,
+ NvU32 bar_index, void *);
+typedef NV_STATUS (*vgpu_vfio_get_description) (struct pci_dev *, NvU32, char *);
+typedef NV_STATUS (*vgpu_vfio_get_name) (struct pci_dev *, NvU32, char *);
+typedef NV_STATUS (*vgpu_vfio_get_instance) (struct pci_dev *, NvU32, char *);
+typedef NV_STATUS (*vgpu_vfio_sparse_mmap_t) (struct pci_dev *, const NvU8 *, NvU64 **, NvU64 **, NvU32 *);
+typedef void (*vgpu_vfio_update_request_t) (const NvU8 *, NvU64 *, NvU64 *, VGPU_DEVICE_STATE, const char *);
+
+typedef struct
+{
+ const char *version_string;
+ vgpu_vfio_vgpu_create_t vgpu_create;
+ vgpu_vfio_vgpu_destroy_t vgpu_delete;
+ vgpu_vfio_bar_info_t vgpu_bar_info;
+ vgpu_vfio_start_t vgpu_start;
+ vgpu_vfio_get_description get_description;
+ vgpu_vfio_get_instance get_instances;
+ vgpu_vfio_get_name get_name;
+ vgpu_vfio_sparse_mmap_t get_sparse_mmap;
+ vgpu_vfio_update_request_t update_request;
+} rm_vgpu_vfio_ops_t;
+
+extern NV_STATUS nvidia_vgpu_vfio_set_ops(vgpu_vfio_ops_t *vgpu_vfio_ops);
+extern NV_STATUS nvidia_vgpu_vfio_get_ops(rm_vgpu_vfio_ops_t *ops);
+
+extern NV_STATUS nvidia_vgpu_vfio_probe(struct pci_dev *);
+extern void nvidia_vgpu_vfio_remove(struct pci_dev *, NvBool);
+
+#endif /* _NV_VGPU_VFIO_INTERFACE_H_ */ \ No newline at end of file
diff --git a/kernel/include/nvidia-vgpu-vfio.h b/kernel/include/nvidia-vgpu-vfio.h
new file mode 100644
index 0000000..7f778ee
--- /dev/null
+++ b/kernel/include/nvidia-vgpu-vfio.h
@@ -0,0 +1,194 @@
+#ifndef _NVIDIA_VGPU_VFIO_H_
+#define _NVIDIA_VGPU_VFIO_H_
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/vfio.h>
+#include <linux/mdev.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/atomic.h>
+
+#define OPEN_IOV_VFIO_VERSION "0.1.0"
+#define OPEN_IOV_VFIO_NAME "open-iov-vfio"
+
+#define NVIDIA_VGPU_VFIO_VERSION OPEN_IOV_VFIO_VERSION
+#define NVIDIA_VGPU_VFIO_NAME OPEN_IOV_VFIO_NAME
+
+#define NVIDIA_VGPU_MAX_VF_COUNT 32
+#define NVIDIA_VGPU_MAX_REGIONS 8
+#define NVIDIA_VGPU_MAX_IRQS 16
+
+#define NV_VGPU_MAX_REGIONS NVIDIA_VGPU_MAX_REGIONS
+#define NV_VGPU_MAX_IRQS NVIDIA_VGPU_MAX_IRQS
+
+#define NV_VGPU_BAR0_SIZE (16 * 1024 * 1024)
+#define NV_VGPU_BAR1_SIZE (256 * 1024 * 1024)
+#define NV_VGPU_BAR2_SIZE (32 * 1024 * 1024)
+#define NV_VGPU_BAR3_SIZE (32 * 1024 * 1024)
+
+enum nv_vgpu_type {
+ NV_VGPU_TYPE_UNKNOWN = 0,
+ NV_VGPU_TYPE_AMPERE,
+ NV_VGPU_TYPE_HOPPER,
+ NV_VGPU_TYPE_TURING,
+ NV_VGPU_TYPE_PASCAL,
+ NV_VGPU_TYPE_MAXWELL,
+ NV_VGPU_TYPE_KEPLER,
+};
+
+enum nv_vgpu_state {
+ NV_VGPU_STATE_UNINITIALIZED = 0,
+ NV_VGPU_STATE_INITIALIZING,
+ NV_VGPU_STATE_READY,
+ NV_VGPU_STATE_RUNNING,
+ NV_VGPU_STATE_SUSPENDED,
+ NV_VGPU_STATE_ERROR,
+ NV_VGPU_STATE_MIGRATING,
+};
+
+struct nv_vgpu_bar {
+ u64 gpa;
+ u64 size;
+ u64 iova;
+ void *vaddr;
+ bool mapped;
+ bool trapped;
+ struct mutex lock;
+};
+
+struct nv_vgpu_irq {
+ int virq;
+ int type;
+ bool masked;
+ struct eventfd_ctx *trigger;
+ struct irq_domain *domain;
+};
+
+struct nv_vgpu_region {
+ u64 offset;
+ u64 size;
+ u64 iova;
+ int fd;
+ void *vaddr;
+ bool readonly;
+};
+
+struct nv_vgpu_migration_ctx;
+
+struct nv_vgpu_migration_state {
+ u32 version;
+ u32 flags;
+ u64 timestamp;
+ u8 *data;
+ size_t data_size;
+ struct completion done;
+ int result;
+ struct nv_vgpu_migration_ctx *ctx;
+};
+
+struct nv_vgpu_device {
+ struct mdev_device *mdev;
+ struct pci_dev *pdev;
+ struct device dev;
+ struct mutex lock;
+ enum nv_vgpu_type type;
+ enum nv_vgpu_state state;
+ u32 vgpu_id;
+ u32 gpu_instance_id;
+ u32 compute_instance_id;
+
+ struct nv_vgpu_bar bars[NV_VGPU_MAX_REGIONS];
+ struct nv_vgpu_irq irqs[NV_VGPU_MAX_IRQS];
+ struct nv_vgpu_region regions[NV_VGPU_MAX_REGIONS];
+
+ struct nv_vgpu_migration_state migration;
+
+ struct work_struct init_work;
+ struct work_struct cleanup_work;
+
+ void *gsp_comm_ctx;
+ void *bar_emul_ctx;
+ void *mm_ctx;
+ void *irq_ctx;
+
+ u64 fb_base;
+ u64 fb_size;
+ u64 bar0_config_base;
+
+ struct list_head list;
+
+ bool dry_run;
+
+ /* PCI Config Space for VFIO mdev */
+ u8 pci_config[256];
+ bool config_space_dirty;
+};
+
+struct nv_vgpu_driver_data {
+ struct mutex lock;
+ struct list_head devices;
+ u32 device_count;
+ struct class *class;
+ struct bus_type *bus;
+};
+
+extern struct nv_vgpu_driver_data nv_vgpu_driver;
+
+int nv_vgpu_device_create(struct mdev_device *mdev);
+void nv_vgpu_device_destroy(struct mdev_device *mdev);
+int nv_vgpu_device_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_device_cleanup(struct nv_vgpu_device *vgpu);
+
+int nv_vgpu_bar_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_bar_cleanup(struct nv_vgpu_device *vgpu);
+int nv_vgpu_bar_trap(struct nv_vgpu_device *vgpu, int bar_idx);
+void nv_vgpu_bar_untrap(struct nv_vgpu_device *vgpu, int bar_idx);
+
+int nv_vgpu_irq_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_irq_cleanup(struct nv_vgpu_device *vgpu);
+int nv_vgpu_irq_enable(struct nv_vgpu_device *vgpu, int irq_idx);
+int nv_vgpu_irq_disable(struct nv_vgpu_device *vgpu, int irq_idx);
+
+int nv_vgpu_memory_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_memory_cleanup(struct nv_vgpu_device *vgpu);
+int nv_vgpu_memory_map(struct nv_vgpu_device *vgpu, u64 gpa, u64 size, u64 *iova);
+int nv_vgpu_memory_unmap(struct nv_vgpu_device *vgpu, u64 iova, u64 size);
+
+int nv_vgpu_gsp_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_gsp_cleanup(struct nv_vgpu_device *vgpu);
+int nv_vgpu_gsp_send_rpc(struct nv_vgpu_device *vgpu, void *msg, size_t size);
+int nv_vgpu_gsp_recv_rpc(struct nv_vgpu_device *vgpu, void *msg, size_t size, int timeout_ms);
+int nv_vgpu_gsp_load_firmware(struct nv_vgpu_device *vgpu);
+void nv_vgpu_gsp_release_firmware(struct nv_vgpu_device *vgpu);
+int nv_vgpu_gsp_boot(struct nv_vgpu_device *vgpu);
+
+int nv_vgpu_migration_init(struct nv_vgpu_device *vgpu);
+void nv_vgpu_migration_cleanup(struct nv_vgpu_device *vgpu);
+int nv_vgpu_migration_save_state(struct nv_vgpu_device *vgpu, u8 **data, size_t *size);
+int nv_vgpu_migration_restore_state(struct nv_vgpu_device *vgpu, u8 *data, size_t size);
+int nv_vgpu_migration_prepare(struct nv_vgpu_device *vgpu);
+int nv_vgpu_migration_complete(struct nv_vgpu_device *vgpu);
+int nv_vgpu_migration_cancel(struct nv_vgpu_device *vgpu);
+u8 *nv_vgpu_migration_get_data(struct nv_vgpu_device *vgpu, size_t *size);
+
+static inline struct nv_vgpu_device *mdev_to_vgpu(struct mdev_device *mdev)
+{
+ return dev_get_drvdata(&mdev->dev);
+}
+
+#define nv_vgpu_dbg(vgpu, fmt, ...) \
+ dev_dbg(&(vgpu)->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
+
+#define nv_vgpu_info(vgpu, fmt, ...) \
+ dev_info(&(vgpu)->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
+
+#define nv_vgpu_warn(vgpu, fmt, ...) \
+ dev_warn(&(vgpu)->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
+
+#define nv_vgpu_err(vgpu, fmt, ...) \
+ dev_err(&(vgpu)->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
+
+#endif \ No newline at end of file
diff --git a/kernel/include/nvstatus.h b/kernel/include/nvstatus.h
new file mode 100644
index 0000000..4f5284d
--- /dev/null
+++ b/kernel/include/nvstatus.h
@@ -0,0 +1,123 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2014-2019 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SDK_NVSTATUS_H
+#define SDK_NVSTATUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "nvtypes.h"
+
+typedef NvU32 NV_STATUS;
+
+#define NV_STATUS_CODE( name, code, string ) name = (code),
+
+enum
+{
+ #include "nvstatuscodes.h"
+};
+
+#undef NV_STATUS_CODE
+
+/*!
+ * @def NV_STATUS_LEVEL_OK
+ * @see NV_STATUS_LEVEL
+ * @brief Success: No error or special condition
+ */
+#define NV_STATUS_LEVEL_OK 0
+
+/*!
+ * @def NV_STATUS_LEVEL_WARN
+ * @see NV_STATUS_LEVEL
+ * @brief Success, but there is an special condition
+ *
+ * @details In general, NV_STATUS_LEVEL_WARN status codes are handled the
+ * same as NV_STATUS_LEVEL_OK, but are usefil to indicate that
+ * there is a condition that may be specially handled.
+ *
+ * Therefore, in most cases, client function should test for
+ * status <= NV_STATUS_LEVEL_WARN or status > NV_STATUS_LEVEL_WARN
+ * to determine success v. failure of a call.
+ */
+#define NV_STATUS_LEVEL_WARN 1
+
+/*!
+ * @def NV_STATUS_LEVEL_ERR
+ * @see NV_STATUS_LEVEL
+ * @brief Unrecoverable error condition
+ */
+#define NV_STATUS_LEVEL_ERR 3
+
+/*!
+ * @def NV_STATUS_LEVEL
+ * @see NV_STATUS_LEVEL_OK
+ * @see NV_STATUS_LEVEL_WARN
+ * @see NV_STATUS_LEVEL_ERR
+ * @brief Level of the status code
+ *
+ * @warning IMPORTANT: When comparing NV_STATUS_LEVEL(_S) against one of
+ * these constants, it is important to use '<=' or '>' (rather
+ * than '<' or '>=').
+ *
+ * For example. do:
+ * if (NV_STATUS_LEVEL(status) <= NV_STATUS_LEVEL_WARN)
+ * rather than:
+ * if (NV_STATUS_LEVEL(status) < NV_STATUS_LEVEL_ERR)
+ *
+ * By being consistent in this manner, it is easier to systematically
+ * add additional level constants. New levels are likely to lower
+ * (rather than raise) the severity of _ERR codes. For example,
+ * if we were to add NV_STATUS_LEVEL_RETRY to indicate hardware
+ * failures that may be recoverable (e.g. RM_ERR_TIMEOUT_RETRY
+ * or RM_ERR_BUSY_RETRY), it would be less severe than
+ * NV_STATUS_LEVEL_ERR the level to which these status codes now
+ * belong. Using '<=' and '>' ensures your code is not broken in
+ * cases like this.
+ */
+#define NV_STATUS_LEVEL(_S) \
+ ((_S) == NV_OK? NV_STATUS_LEVEL_OK: \
+ ((_S) != NV_ERR_GENERIC && (_S) & 0x00010000? NV_STATUS_LEVEL_WARN: \
+ NV_STATUS_LEVEL_ERR))
+
+/*!
+ * @def NV_STATUS_LEVEL
+ * @see NV_STATUS_LEVEL_OK
+ * @see NV_STATUS_LEVEL_WARN
+ * @see NV_STATUS_LEVEL_ERR
+ * @brief Character representing status code level
+ */
+#define NV_STATUS_LEVEL_CHAR(_S) \
+ ((_S) == NV_OK? '0': \
+ ((_S) != NV_ERR_GENERIC && (_S) & 0x00010000? 'W': \
+ 'E'))
+
+// Function definitions
+const char *nvstatusToString(NV_STATUS nvStatusIn);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SDK_NVSTATUS_H */
diff --git a/kernel/include/nvtypes.h b/kernel/include/nvtypes.h
new file mode 100644
index 0000000..7810d34
--- /dev/null
+++ b/kernel/include/nvtypes.h
@@ -0,0 +1,830 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 1993-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef NVTYPES_INCLUDED
+#define NVTYPES_INCLUDED
+
+#include "cpuopsys.h"
+
+#ifndef NVTYPES_USE_STDINT
+#define NVTYPES_USE_STDINT 0
+#endif
+
+#if NVTYPES_USE_STDINT
+#ifdef __cplusplus
+#include <cstdint>
+#include <cinttypes>
+#else
+#include <stdint.h>
+#include <inttypes.h>
+#endif // __cplusplus
+#endif // NVTYPES_USE_STDINT
+
+#ifndef __cplusplus
+// Header includes to make sure wchar_t is defined for C-file compilation
+// (C++ is not affected as it is a fundamental type there)
+// _MSC_VER is a hack to avoid failures for old setup of UEFI builds which are
+// currently set to msvc100 but do not properly set the include paths
+#if defined(NV_WINDOWS) && (!defined(_MSC_VER) || (_MSC_VER > 1600))
+#include <stddef.h>
+#define NV_HAS_WCHAR_T_TYPEDEF 1
+#endif
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(MAKE_NV64TYPES_8BYTES_ALIGNED) && defined(__i386__)
+// ensure or force 8-bytes alignment of NV 64-bit types
+#define OPTIONAL_ALIGN8_ATTR __attribute__((aligned(8)))
+#else
+// nothing needed
+#define OPTIONAL_ALIGN8_ATTR
+#endif // MAKE_NV64TYPES_8BYTES_ALIGNED && i386
+
+ /***************************************************************************\
+|* Typedefs *|
+ \***************************************************************************/
+
+#ifdef NV_MISRA_COMPLIANCE_REQUIRED
+//Typedefs for MISRA COMPLIANCE
+typedef unsigned long long UInt64;
+typedef signed long long Int64;
+typedef unsigned int UInt32;
+typedef signed int Int32;
+typedef unsigned short UInt16;
+typedef signed short Int16;
+typedef unsigned char UInt8 ;
+typedef signed char Int8 ;
+
+typedef void Void;
+typedef float float32_t;
+typedef double float64_t;
+#endif
+
+
+// Floating point types
+#ifdef NV_MISRA_COMPLIANCE_REQUIRED
+typedef float32_t NvF32; /* IEEE Single Precision (S1E8M23) */
+typedef float64_t NvF64 OPTIONAL_ALIGN8_ATTR; /* IEEE Double Precision (S1E11M52) */
+#else
+typedef float NvF32; /* IEEE Single Precision (S1E8M23) */
+typedef double NvF64 OPTIONAL_ALIGN8_ATTR; /* IEEE Double Precision (S1E11M52) */
+#endif
+
+
+// 8-bit: 'char' is the only 8-bit in the C89 standard and after.
+#if NVTYPES_USE_STDINT
+typedef uint8_t NvV8; /* "void": enumerated or multiple fields */
+typedef uint8_t NvU8; /* 0 to 255 */
+typedef int8_t NvS8; /* -128 to 127 */
+#else
+#ifdef NV_MISRA_COMPLIANCE_REQUIRED
+typedef UInt8 NvV8; /* "void": enumerated or multiple fields */
+typedef UInt8 NvU8; /* 0 to 255 */
+typedef Int8 NvS8; /* -128 to 127 */
+#else
+typedef unsigned char NvV8; /* "void": enumerated or multiple fields */
+typedef unsigned char NvU8; /* 0 to 255 */
+typedef signed char NvS8; /* -128 to 127 */
+#endif
+#endif // NVTYPES_USE_STDINT
+
+
+#if NVTYPES_USE_STDINT
+typedef uint16_t NvV16; /* "void": enumerated or multiple fields */
+typedef uint16_t NvU16; /* 0 to 65535 */
+typedef int16_t NvS16; /* -32768 to 32767 */
+#else
+// 16-bit: If the compiler tells us what we can use, then use it.
+#ifdef __INT16_TYPE__
+typedef unsigned __INT16_TYPE__ NvV16; /* "void": enumerated or multiple fields */
+typedef unsigned __INT16_TYPE__ NvU16; /* 0 to 65535 */
+typedef signed __INT16_TYPE__ NvS16; /* -32768 to 32767 */
+
+// The minimal standard for C89 and after
+#else // __INT16_TYPE__
+#ifdef NV_MISRA_COMPLIANCE_REQUIRED
+typedef UInt16 NvV16; /* "void": enumerated or multiple fields */
+typedef UInt16 NvU16; /* 0 to 65535 */
+typedef Int16 NvS16; /* -32768 to 32767 */
+#else
+typedef unsigned short NvV16; /* "void": enumerated or multiple fields */
+typedef unsigned short NvU16; /* 0 to 65535 */
+typedef signed short NvS16; /* -32768 to 32767 */
+#endif
+#endif // __INT16_TYPE__
+#endif // NVTYPES_USE_STDINT
+
+// wchar type (fixed size types consistent across Linux/Windows boundaries)
+#if defined(NV_HAS_WCHAR_T_TYPEDEF)
+ typedef wchar_t NvWchar;
+#else
+ typedef NvV16 NvWchar;
+#endif
+
+// Macro to build an NvU32 from four bytes, listed from msb to lsb
+#define NvU32_BUILD(a, b, c, d) \
+ ((NvU32)( \
+ (((NvU32)(a) & 0xff) << 24) | \
+ (((NvU32)(b) & 0xff) << 16) | \
+ (((NvU32)(c) & 0xff) << 8) | \
+ (((NvU32)(d) & 0xff))))
+
+// Macro to build an NvU64 from two DWORDS, listed from msb to lsb
+#define NvU64_BUILD(a, b) \
+ ((NvU64)( \
+ (((NvU64)(a) & ~0U) << 32) | \
+ (((NvU64)(b) & ~0U))))
+
+#if NVTYPES_USE_STDINT
+typedef uint32_t NvV32; /* "void": enumerated or multiple fields */
+typedef uint32_t NvU32; /* 0 to 4294967295 */
+typedef int32_t NvS32; /* -2147483648 to 2147483647 */
+#else
+// 32-bit: If the compiler tells us what we can use, then use it.
+#ifdef __INT32_TYPE__
+typedef unsigned __INT32_TYPE__ NvV32; /* "void": enumerated or multiple fields */
+typedef unsigned __INT32_TYPE__ NvU32; /* 0 to 4294967295 */
+typedef signed __INT32_TYPE__ NvS32; /* -2147483648 to 2147483647 */
+
+// Older compilers
+#else // __INT32_TYPE__
+
+// For historical reasons, NvU32/NvV32 are defined to different base intrinsic
+// types than NvS32 on some platforms.
+// Mainly for 64-bit linux, where long is 64 bits and win9x, where int is 16 bit.
+#if (defined(NV_UNIX) || defined(vxworks) || defined(NV_WINDOWS_CE) || \
+ defined(__arm) || defined(__IAR_SYSTEMS_ICC__) || defined(NV_QNX) || \
+ defined(NV_INTEGRITY) || defined(NV_MODS) || \
+ defined(__GNUC__) || defined(__clang__) || defined(NV_MACINTOSH_64)) && \
+ (!defined(NV_MACINTOSH) || defined(NV_MACINTOSH_64))
+#ifdef NV_MISRA_COMPLIANCE_REQUIRED
+typedef UInt32 NvV32; /* "void": enumerated or multiple fields */
+typedef UInt32 NvU32; /* 0 to 4294967295 */
+#else
+typedef unsigned int NvV32; /* "void": enumerated or multiple fields */
+typedef unsigned int NvU32; /* 0 to 4294967295 */
+#endif
+
+// The minimal standard for C89 and after
+#else // (defined(NV_UNIX) || defined(vxworks) || ...
+typedef unsigned long NvV32; /* "void": enumerated or multiple fields */
+typedef unsigned long NvU32; /* 0 to 4294967295 */
+#endif // (defined(NV_UNIX) || defined(vxworks) || ...
+
+// Mac OS 32-bit still needs this
+#if defined(NV_MACINTOSH) && !defined(NV_MACINTOSH_64)
+typedef signed long NvS32; /* -2147483648 to 2147483647 */
+#else
+#ifdef NV_MISRA_COMPLIANCE_REQUIRED
+typedef Int32 NvS32; /* -2147483648 to 2147483647 */
+#else
+typedef signed int NvS32; /* -2147483648 to 2147483647 */
+#endif
+#endif // defined(NV_MACINTOSH) && !defined(NV_MACINTOSH_64)
+#endif // __INT32_TYPE__
+#endif // NVTYPES_USE_STDINT
+
+
+
+#if NVTYPES_USE_STDINT
+typedef uint64_t NvU64 OPTIONAL_ALIGN8_ATTR; /* 0 to 18446744073709551615 */
+typedef int64_t NvS64 OPTIONAL_ALIGN8_ATTR; /* -9223372036854775808 to 9223372036854775807 */
+
+#define NvU64_fmtX PRIX64
+#define NvU64_fmtx PRIx64
+#define NvU64_fmtu PRIu64
+#define NvU64_fmto PRIo64
+#define NvS64_fmtd PRId64
+#define NvS64_fmti PRIi64
+#else
+// 64-bit types for compilers that support them, plus some obsolete variants
+#if defined(__GNUC__) || defined(__clang__) || defined(__arm) || \
+ defined(__IAR_SYSTEMS_ICC__) || defined(__ghs__) || defined(_WIN64) || \
+ defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined (__xlC__)
+#ifdef NV_MISRA_COMPLIANCE_REQUIRED
+typedef UInt64 NvU64 OPTIONAL_ALIGN8_ATTR; /* 0 to 18446744073709551615 */
+typedef Int64 NvS64 OPTIONAL_ALIGN8_ATTR; /* -9223372036854775808 to 9223372036854775807 */
+#else
+typedef unsigned long long NvU64 OPTIONAL_ALIGN8_ATTR; /* 0 to 18446744073709551615 */
+typedef long long NvS64 OPTIONAL_ALIGN8_ATTR; /* -9223372036854775808 to 9223372036854775807 */
+#endif
+
+#define NvU64_fmtX "llX"
+#define NvU64_fmtx "llx"
+#define NvU64_fmtu "llu"
+#define NvU64_fmto "llo"
+#define NvS64_fmtd "lld"
+#define NvS64_fmti "lli"
+
+// Microsoft since 2003 -- https://msdn.microsoft.com/en-us/library/29dh1w7z.aspx
+#else
+typedef unsigned __int64 NvU64 OPTIONAL_ALIGN8_ATTR; /* 0 to 18446744073709551615 */
+typedef __int64 NvS64 OPTIONAL_ALIGN8_ATTR; /* -9223372036854775808 to 9223372036854775807 */
+
+#define NvU64_fmtX "I64X"
+#define NvU64_fmtx "I64x"
+#define NvU64_fmtu "I64u"
+#define NvU64_fmto "I64o"
+#define NvS64_fmtd "I64d"
+#define NvS64_fmti "I64i"
+
+#endif
+#endif // NVTYPES_USE_STDINT
+
+#ifdef NV_TYPESAFE_HANDLES
+/*
+ * Can't use opaque pointer as clients might be compiled with mismatched
+ * pointer sizes. TYPESAFE check will eventually be removed once all clients
+ * have transistioned safely to NvHandle.
+ * The plan is to then eventually scale up the handle to be 64-bits.
+ */
+typedef struct
+{
+ NvU32 val;
+} NvHandle;
+#else
+/*
+ * For compatibility with modules that haven't moved typesafe handles.
+ */
+typedef NvU32 NvHandle;
+#endif // NV_TYPESAFE_HANDLES
+
+/* Boolean type */
+typedef NvU8 NvBool;
+#define NV_TRUE ((NvBool)(0 == 0))
+#define NV_FALSE ((NvBool)(0 != 0))
+
+/* Tristate type: NV_TRISTATE_FALSE, NV_TRISTATE_TRUE, NV_TRISTATE_INDETERMINATE */
+typedef NvU8 NvTristate;
+#define NV_TRISTATE_FALSE ((NvTristate) 0)
+#define NV_TRISTATE_TRUE ((NvTristate) 1)
+#define NV_TRISTATE_INDETERMINATE ((NvTristate) 2)
+
+/* Macros to extract the low and high parts of a 64-bit unsigned integer */
+/* Also designed to work if someone happens to pass in a 32-bit integer */
+#ifdef NV_MISRA_COMPLIANCE_REQUIRED
+#define NvU64_HI32(n) ((NvU32)((((NvU64)(n)) >> 32) & 0xffffffffU))
+#define NvU64_LO32(n) ((NvU32)(( (NvU64)(n)) & 0xffffffffU))
+#else
+#define NvU64_HI32(n) ((NvU32)((((NvU64)(n)) >> 32) & 0xffffffff))
+#define NvU64_LO32(n) ((NvU32)(( (NvU64)(n)) & 0xffffffff))
+#endif
+#define NvU40_HI32(n) ((NvU32)((((NvU64)(n)) >> 8) & 0xffffffffU))
+#define NvU40_HI24of32(n) ((NvU32)( (NvU64)(n) & 0xffffff00U))
+
+/* Macros to get the MSB and LSB of a 32 bit unsigned number */
+#define NvU32_HI16(n) ((NvU16)((((NvU32)(n)) >> 16) & 0xffffU))
+#define NvU32_LO16(n) ((NvU16)(( (NvU32)(n)) & 0xffffU))
+
+ /***************************************************************************\
+|* *|
+|* 64 bit type definitions for use in interface structures. *|
+|* *|
+ \***************************************************************************/
+
+#if defined(NV_64_BITS)
+
+typedef void* NvP64; /* 64 bit void pointer */
+typedef NvU64 NvUPtr; /* pointer sized unsigned int */
+typedef NvS64 NvSPtr; /* pointer sized signed int */
+typedef NvU64 NvLength; /* length to agree with sizeof */
+
+#define NvP64_VALUE(n) (n)
+#define NvP64_fmt "%p"
+
+#define KERNEL_POINTER_FROM_NvP64(p,v) ((p)(v))
+#define NvP64_PLUS_OFFSET(p,o) (NvP64)((NvU64)(p) + (NvU64)(o))
+
+#define NvUPtr_fmtX NvU64_fmtX
+#define NvUPtr_fmtx NvU64_fmtx
+#define NvUPtr_fmtu NvU64_fmtu
+#define NvUPtr_fmto NvU64_fmto
+#define NvSPtr_fmtd NvS64_fmtd
+#define NvSPtr_fmti NvS64_fmti
+
+#else
+
+typedef NvU64 NvP64; /* 64 bit void pointer */
+typedef NvU32 NvUPtr; /* pointer sized unsigned int */
+typedef NvS32 NvSPtr; /* pointer sized signed int */
+typedef NvU32 NvLength; /* length to agree with sizeof */
+
+#define NvP64_VALUE(n) ((void *)(NvUPtr)(n))
+#define NvP64_fmt "0x%llx"
+
+#define KERNEL_POINTER_FROM_NvP64(p,v) ((p)(NvUPtr)(v))
+#define NvP64_PLUS_OFFSET(p,o) ((p) + (NvU64)(o))
+
+#define NvUPtr_fmtX "X"
+#define NvUPtr_fmtx "x"
+#define NvUPtr_fmtu "u"
+#define NvUPtr_fmto "o"
+#define NvSPtr_fmtd "d"
+#define NvSPtr_fmti "i"
+
+#endif
+
+#define NvP64_NULL (NvP64)0
+
+/*!
+ * Helper macro to pack an @ref NvU64_ALIGN32 structure from a @ref NvU64.
+ *
+ * @param[out] pDst Pointer to NvU64_ALIGN32 structure to pack
+ * @param[in] pSrc Pointer to NvU64 with which to pack
+ */
+#define NvU64_ALIGN32_PACK(pDst, pSrc) \
+do { \
+ (pDst)->lo = NvU64_LO32(*(pSrc)); \
+ (pDst)->hi = NvU64_HI32(*(pSrc)); \
+} while (NV_FALSE)
+
+/*!
+ * Helper macro to unpack a @ref NvU64_ALIGN32 structure into a @ref NvU64.
+ *
+ * @param[out] pDst Pointer to NvU64 in which to unpack
+ * @param[in] pSrc Pointer to NvU64_ALIGN32 structure from which to unpack
+ */
+#define NvU64_ALIGN32_UNPACK(pDst, pSrc) \
+do { \
+ (*(pDst)) = NvU64_ALIGN32_VAL(pSrc); \
+} while (NV_FALSE)
+
+/*!
+ * Helper macro to unpack a @ref NvU64_ALIGN32 structure as a @ref NvU64.
+ *
+ * @param[in] pSrc Pointer to NvU64_ALIGN32 structure to unpack
+ */
+#define NvU64_ALIGN32_VAL(pSrc) \
+ ((NvU64) ((NvU64)((pSrc)->lo) | (((NvU64)(pSrc)->hi) << 32U)))
+
+/*!
+ * Helper macro to check whether the 32 bit aligned 64 bit number is zero.
+ *
+ * @param[in] _pU64 Pointer to NvU64_ALIGN32 structure.
+ *
+ * @return
+ * NV_TRUE _pU64 is zero.
+ * NV_FALSE otherwise.
+ */
+#define NvU64_ALIGN32_IS_ZERO(_pU64) \
+ (((_pU64)->lo == 0U) && ((_pU64)->hi == 0U))
+
+/*!
+ * Helper macro to sub two 32 aligned 64 bit numbers on 64 bit processor.
+ *
+ * @param[in] pSrc1 Pointer to NvU64_ALIGN32 source 1 structure.
+ * @param[in] pSrc2 Pointer to NvU64_ALIGN32 source 2 structure.
+ * @param[in/out] pDst Pointer to NvU64_ALIGN32 dest. structure.
+ */
+#define NvU64_ALIGN32_ADD(pDst, pSrc1, pSrc2) \
+do { \
+ NvU64 __dst, __src1, __scr2; \
+ \
+ NvU64_ALIGN32_UNPACK(&__src1, (pSrc1)); \
+ NvU64_ALIGN32_UNPACK(&__scr2, (pSrc2)); \
+ __dst = __src1 + __scr2; \
+ NvU64_ALIGN32_PACK((pDst), &__dst); \
+} while (NV_FALSE)
+
+/*!
+ * Helper macro to sub two 32 aligned 64 bit numbers on 64 bit processor.
+ *
+ * @param[in] pSrc1 Pointer to NvU64_ALIGN32 source 1 structure.
+ * @param[in] pSrc2 Pointer to NvU64_ALIGN32 source 2 structure.
+ * @param[in/out] pDst Pointer to NvU64_ALIGN32 dest. structure.
+ */
+#define NvU64_ALIGN32_SUB(pDst, pSrc1, pSrc2) \
+do { \
+ NvU64 __dst, __src1, __scr2; \
+ \
+ NvU64_ALIGN32_UNPACK(&__src1, (pSrc1)); \
+ NvU64_ALIGN32_UNPACK(&__scr2, (pSrc2)); \
+ __dst = __src1 - __scr2; \
+ NvU64_ALIGN32_PACK((pDst), &__dst); \
+} while (NV_FALSE)
+
+/*!
+ * Structure for representing 32 bit aligned NvU64 (64-bit unsigned integer)
+ * structures. This structure must be used because the 32 bit processor and
+ * 64 bit processor compilers will pack/align NvU64 differently.
+ *
+ * One use case is RM being 64 bit proc whereas PMU being 32 bit proc, this
+ * alignment difference will result in corrupted transactions between the RM
+ * and PMU.
+ *
+ * See the @ref NvU64_ALIGN32_PACK and @ref NvU64_ALIGN32_UNPACK macros for
+ * packing and unpacking these structures.
+ *
+ * @note The intention of this structure is to provide a datatype which will
+ * packed/aligned consistently and efficiently across all platforms.
+ * We don't want to use "NV_DECLARE_ALIGNED(NvU64, 8)" because that
+ * leads to memory waste on our 32-bit uprocessors (e.g. FALCONs) where
+ * DMEM efficiency is vital.
+ */
+typedef struct
+{
+ /*!
+ * Low 32 bits.
+ */
+ NvU32 lo;
+ /*!
+ * High 32 bits.
+ */
+ NvU32 hi;
+} NvU64_ALIGN32;
+
+/* Useful macro to hide required double cast */
+#define NV_PTR_TO_NvP64(n) (NvP64)(NvUPtr)(n)
+#define NV_SIGN_EXT_PTR_TO_NvP64(p) ((NvP64)(NvS64)(NvSPtr)(p))
+#define KERNEL_POINTER_TO_NvP64(p) ((NvP64)(uintptr_t)(p))
+
+ /***************************************************************************\
+|* *|
+|* Limits for common types. *|
+|* *|
+ \***************************************************************************/
+
+/* Explanation of the current form of these limits:
+ *
+ * - Decimal is used, as hex values are by default positive.
+ * - Casts are not used, as usage in the preprocessor itself (#if) ends poorly.
+ * - The subtraction of 1 for some MIN values is used to get around the fact
+ * that the C syntax actually treats -x as NEGATE(x) instead of a distinct
+ * number. Since 214748648 isn't a valid positive 32-bit signed value, we
+ * take the largest valid positive signed number, negate it, and subtract 1.
+ */
+#define NV_S8_MIN (-128)
+#define NV_S8_MAX (+127)
+#define NV_U8_MIN (0U)
+#define NV_U8_MAX (+255U)
+#define NV_S16_MIN (-32768)
+#define NV_S16_MAX (+32767)
+#define NV_U16_MIN (0U)
+#define NV_U16_MAX (+65535U)
+#define NV_S32_MIN (-2147483647 - 1)
+#define NV_S32_MAX (+2147483647)
+#define NV_U32_MIN (0U)
+#define NV_U32_MAX (+4294967295U)
+#define NV_S64_MIN (-9223372036854775807LL - 1LL)
+#define NV_S64_MAX (+9223372036854775807LL)
+#define NV_U64_MIN (0ULL)
+#define NV_U64_MAX (+18446744073709551615ULL)
+
+/* Aligns fields in structs so they match up between 32 and 64 bit builds */
+#if defined(__GNUC__) || defined(__clang__) || defined(NV_QNX)
+#define NV_ALIGN_BYTES(size) __attribute__ ((aligned (size)))
+#elif defined(__arm)
+#define NV_ALIGN_BYTES(size) __align(ALIGN)
+#else
+// XXX This is dangerously nonportable! We really shouldn't provide a default
+// version of this that doesn't do anything.
+#define NV_ALIGN_BYTES(size)
+#endif
+
+// NV_DECLARE_ALIGNED() can be used on all platforms.
+// This macro form accounts for the fact that __declspec on Windows is required
+// before the variable type,
+// and NV_ALIGN_BYTES is required after the variable name.
+#if defined(__GNUC__) || defined(__clang__) || defined(NV_QNX)
+#define NV_DECLARE_ALIGNED(TYPE_VAR, ALIGN) TYPE_VAR __attribute__ ((aligned (ALIGN)))
+#elif defined(_MSC_VER)
+#define NV_DECLARE_ALIGNED(TYPE_VAR, ALIGN) __declspec(align(ALIGN)) TYPE_VAR
+#elif defined(__arm)
+#define NV_DECLARE_ALIGNED(TYPE_VAR, ALIGN) __align(ALIGN) TYPE_VAR
+#endif
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+#define NV_ALIGNOF(type) _Alignof(type)
+#elif defined(__cplusplus) && (__cplusplus >= 201103L)
+#define NV_ALIGNOF(type) alignof(type)
+#elif defined(__GNUC__) || defined(__clang__)
+#define NV_ALIGNOF(type) __alignof__(type)
+#elif defined(_MSC_VER)
+#define NV_ALIGNOF(type) __alignof(type)
+#endif
+
+ /***************************************************************************\
+|* Function Declaration Types *|
+ \***************************************************************************/
+
+// stretching the meaning of "nvtypes", but this seems to least offensive
+// place to re-locate these from nvos.h which cannot be included by a number
+// of builds that need them
+
+#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)
+ #define NV_ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+ #define NV_ATTRIBUTE_UNUSED
+#endif
+
+#if defined(_MSC_VER)
+
+ #if _MSC_VER >= 1310
+ #define NV_NOINLINE __declspec(noinline)
+ #else
+ #define NV_NOINLINE
+ #endif
+
+ #define NV_INLINE __inline
+
+ #if _MSC_VER >= 1200
+ #define NV_FORCEINLINE __forceinline
+ #else
+ #define NV_FORCEINLINE __inline
+ #endif
+
+ #define NV_APIENTRY __stdcall
+ #define NV_FASTCALL __fastcall
+ #define NV_CDECLCALL __cdecl
+ #define NV_STDCALL __stdcall
+
+ #define NV_FORCERESULTCHECK
+
+ #define NV_FORMAT_PRINTF(_f, _a)
+
+#else // ! defined(_MSC_VER)
+
+ #if defined(__GNUC__)
+ #if (__GNUC__ > 3) || \
+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) && (__GNUC_PATCHLEVEL__ >= 1))
+ #define NV_NOINLINE __attribute__((__noinline__))
+ #endif
+ #elif defined(__clang__)
+ #if __has_attribute(noinline)
+ #define NV_NOINLINE __attribute__((__noinline__))
+ #endif
+ #elif defined(__arm) && (__ARMCC_VERSION >= 300000)
+ #define NV_NOINLINE __attribute__((__noinline__))
+ #elif (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) ||\
+ (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x590))
+ #define NV_NOINLINE __attribute__((__noinline__))
+ #elif defined (__INTEL_COMPILER)
+ #define NV_NOINLINE __attribute__((__noinline__))
+ #endif
+
+ #if !defined(NV_NOINLINE)
+ #define NV_NOINLINE
+ #endif
+
+ /* GreenHills compiler defines __GNUC__, but doesn't support
+ * __inline__ keyword. */
+ #if defined(__ghs__)
+ #define NV_INLINE inline
+ #elif defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)
+ #define NV_INLINE __inline__
+ #elif defined (macintosh) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ #define NV_INLINE inline
+ #elif defined(__arm)
+ #define NV_INLINE __inline
+ #else
+ #define NV_INLINE
+ #endif
+
+ /* Don't force inline on DEBUG builds -- it's annoying for debuggers. */
+ #if !defined(DEBUG)
+ /* GreenHills compiler defines __GNUC__, but doesn't support
+ * __attribute__ or __inline__ keyword. */
+ #if defined(__ghs__)
+ #define NV_FORCEINLINE inline
+ #elif defined(__GNUC__)
+ // GCC 3.1 and beyond support the always_inline function attribute.
+ #if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))
+ #define NV_FORCEINLINE __attribute__((__always_inline__)) __inline__
+ #else
+ #define NV_FORCEINLINE __inline__
+ #endif
+ #elif defined(__clang__)
+ #if __has_attribute(always_inline)
+ #define NV_FORCEINLINE __attribute__((__always_inline__)) __inline__
+ #else
+ #define NV_FORCEINLINE __inline__
+ #endif
+ #elif defined(__arm) && (__ARMCC_VERSION >= 220000)
+ // RVDS 2.2 also supports forceinline, but ADS 1.2 does not
+ #define NV_FORCEINLINE __forceinline
+ #else /* defined(__GNUC__) */
+ #define NV_FORCEINLINE NV_INLINE
+ #endif
+ #else
+ #define NV_FORCEINLINE NV_INLINE
+ #endif
+
+ #define NV_APIENTRY
+ #define NV_FASTCALL
+ #define NV_CDECLCALL
+ #define NV_STDCALL
+
+ /*
+ * The 'warn_unused_result' function attribute prompts GCC to issue a
+ * warning if the result of a function tagged with this attribute
+ * is ignored by a caller. In combination with '-Werror', it can be
+ * used to enforce result checking in RM code; at this point, this
+ * is only done on UNIX.
+ */
+ #if defined(__GNUC__) && defined(NV_UNIX)
+ #if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))
+ #define NV_FORCERESULTCHECK __attribute__((__warn_unused_result__))
+ #else
+ #define NV_FORCERESULTCHECK
+ #endif
+ #elif defined(__clang__)
+ #if __has_attribute(warn_unused_result)
+ #define NV_FORCERESULTCHECK __attribute__((__warn_unused_result__))
+ #else
+ #define NV_FORCERESULTCHECK
+ #endif
+ #else /* defined(__GNUC__) */
+ #define NV_FORCERESULTCHECK
+ #endif
+
+ /*
+ * Functions decorated with NV_FORMAT_PRINTF(f, a) have a format string at
+ * parameter number 'f' and variadic arguments start at parameter number 'a'.
+ * (Note that for C++ methods, there is an implicit 'this' parameter so
+ * explicit parameters are numbered from 2.)
+ */
+ #if defined(__GNUC__)
+ #define NV_FORMAT_PRINTF(_f, _a) __attribute__((format(printf, _f, _a)))
+ #else
+ #define NV_FORMAT_PRINTF(_f, _a)
+ #endif
+
+#endif // defined(_MSC_VER)
+
+ /***************************************************************************\
+|* *|
+|* Definitions of binary/bytes representations of floating point values *|
+|* *|
+|* Intended for use when passing values across kernel contexts in which *|
+|* floating point use is forbidden *|
+|* *|
+ \***************************************************************************/
+//
+// Determine whether we have to turn FP32 support off based on compiler flags.
+// For now, this is only done when we can detect that we're compiling for x86_64
+// with GCC/clang and SSE is disabled.
+//
+// This is also currently only used to control NvF32Bytes definitions.
+//
+// In the future, it could be possible to:
+// 1.) Define this more generally
+// and
+// 2.) Use it in more places
+//
+// This would allow us to fully prevent usage of NvF32 in codebases where it is
+// not supported.
+//
+#if !defined(NVTYPES_NV_F32_SUPPORTED) && NVCPU_IS_X86_64 && (defined(__GNUC__) || defined(__clang__)) && !defined(__SSE__)
+#define NVTYPES_NV_F32_SUPPORTED 0
+#else
+#define NVTYPES_NV_F32_SUPPORTED 1
+#endif
+
+/*!
+ * A struct containing the 32-bit representation of an (IEEE-754 binary32)
+ * floating point value, i.e., the raw underlying bytes of an @ref NvF32
+ *
+ * This struct must be used in places where a value may be passed across a
+ * kernel boundary, as use of floating point within some kernels is, in general,
+ * banned.
+ */
+typedef struct
+{
+ NvU32 value;
+} NvF32Bytes;
+
+#if !defined(NVDEC_1_0)
+/*!
+ * @brief Maps the bytes of a given @ref NvF32 to an @ref NvF32Bytes
+ *
+ * @param[in] pfValue
+ * Pointer to value to convert
+ *
+ * @return @ref NvF32Bytes byte-mapped from @p *pfValue
+ */
+static NV_FORCEINLINE NvF32Bytes
+nvF32BytesMapFromNvF32
+(
+ const NvF32 *pfValue
+)
+{
+ union
+ {
+ NvF32 f;
+ NvF32Bytes b;
+ } value;
+
+ value.f = *pfValue;
+
+ return value.b;
+}
+
+#if NVTYPES_NV_F32_SUPPORTED
+/*!
+ * @brief Maps the bytes of a given @ref NvF32Bytes to an @ref NvF32
+ *
+ * @param[in] pfValue
+ * Pointer to value to convert
+ *
+ * @return @ref NvF32 byte-mapped from @p *pfValue
+ */
+static NV_FORCEINLINE NvF32
+nvF32BytesMapToNvF32
+(
+ const NvF32Bytes *pfValue
+)
+{
+ union
+ {
+ NvF32Bytes b;
+ NvF32 f;
+ } value;
+
+ value.b = *pfValue;
+
+ return value.f;
+}
+#endif // NVTYPES_NV_F32_SUPPORTED
+
+/*!
+ * @brief Maps the bytes of a given @ref NvU32 to an @ref NvF32Bytes
+ *
+ * @details This function is intended for first "moving" raw byte values into
+ * the "floating point domain."
+ *
+ * @param[in] pfValue
+ * Pointer to value to convert
+ *
+ * @return @ref NvF32Bytes byte-mapped from @p *pfValue
+ */
+static NV_FORCEINLINE NvF32Bytes
+nvF32BytesMapFromNvU32
+(
+ const NvU32 *pfValue
+)
+{
+ union
+ {
+ NvU32 u;
+ NvF32Bytes b;
+ } value;
+
+ value.u = *pfValue;
+
+ return value.b;
+}
+
+/*!
+ * @brief Maps the bytes of a given @ref NvF32Bytes to an @ref NvU32
+ *
+ * @param[in] pfValue
+ * Pointer to value to convert
+ *
+ * @return @ref NvU32 byte-mapped from @p *pfValue
+ */
+static NV_FORCEINLINE NvU32
+nvF32BytesMapToNvU32
+(
+ const NvF32Bytes *pfValue
+)
+{
+ union
+ {
+ NvF32Bytes b;
+ NvU32 u;
+ } value;
+
+ value.b = *pfValue;
+
+ return value.u;
+}
+#endif // !defined(NVDEC_1_0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NVTYPES_INCLUDED */