summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-23 06:06:26 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-23 06:06:26 -0400
commit49f6cc35af91e2a403490cd9319166dd14f5f64e (patch)
tree344eef455f571754f1b166975bf410a4b9ce9764
parent68cdd7728a7cc6715bbbff7decfe2b11c3bdf558 (diff)
downloadopen-iov-49f6cc35af91e2a403490cd9319166dd14f5f64e.tar.gz
open-iov-49f6cc35af91e2a403490cd9319166dd14f5f64e.zip
Untrack legacy trees and purely legacy docs (kept locally)
- patches/ -> legacy-patches/ (gitignored) - legacy-driver-guest/ (old guest vGPU driver, gitignored) - docs/old/ (superseded architecture write-up, gitignored) - docs that only reference the legacy components stay tracked; their path references now point at legacy-patches/ - install.sh PATCH_DIR updated
-rw-r--r--.gitignore17
-rw-r--r--STATE.md2
-rw-r--r--docs/ONBOARDING.md2
-rw-r--r--docs/VERSION_UPGRADE.md2
-rw-r--r--docs/old/ARCHITECTURE.md476
-rwxr-xr-xinstall.sh2
-rw-r--r--legacy-driver-guest/Makefile44
-rw-r--r--legacy-driver-guest/README.md21
-rw-r--r--legacy-driver-guest/bar/gsp_bar.c242
-rw-r--r--legacy-driver-guest/core/gsp_core.c654
-rw-r--r--legacy-driver-guest/debugfs/gsp_debugfs.c273
-rw-r--r--legacy-driver-guest/include/gsp_core.h613
-rw-r--r--legacy-driver-guest/kernel-tests/gsp_vgpu_comprehensive_test.c432
-rw-r--r--legacy-driver-guest/kernel-tests/gsp_vgpu_kunit_test.c327
-rw-r--r--legacy-driver-guest/kernel-tests/gsp_vgpu_mock_test.c624
-rw-r--r--legacy-driver-guest/migration/gsp_migration.c339
-rw-r--r--legacy-driver-guest/rpc/gsp_rpc.c331
-rw-r--r--legacy-driver-guest/vf/gsp_vf.c312
-rw-r--r--legacy-driver-guest/wpr/gsp_wpr.c285
-rw-r--r--patches/nvidia/0001-Build-fixes-and-vGPU-VFIO-interface-integration.patch484
-rw-r--r--patches/nvidia/README.md45
21 files changed, 17 insertions, 5510 deletions
diff --git a/.gitignore b/.gitignore
index 42849ec..8d5c51d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,13 +40,22 @@ userspace/examples/example_vgpu
userspace/tests/*_test
# ----------------------------------------------------------------------------
-# NVIDIA open-gpu-kernel-modules (vendor tree)
-# Cloned at a pinned tag and patched by install.sh - see patches/nvidia/
+# NVIDIA open-gpu-kernel-modules (public upstream)
+# Cloned at a pinned tag and patched by install.sh - see legacy-patches/nvidia/
# ----------------------------------------------------------------------------
/nvidia-open-gpu-kernel-modules/
-# NVIDIA open-gpu-kernel-modules @ 570.144 (local checkout of the open kernel modules
-# driver's exact wire protocol - used by kernel/gsp_rm_emulation.c)
+# Legacy NVIDIA patches (kept locally, no longer tracked)
+/legacy-patches/
+
+# Legacy guest driver (gsp-vgpu.ko, superseded by stock guest driver; kept
+# locally, no longer tracked)
+/legacy-driver-guest/
+
+# Purely legacy docs (describe the superseded guest-driver architecture)
+/docs/old/
+
+# Local checkout of the open kernel modules @ 570.144 (not tracked)
/nvidia-570.144-reference/
# rmq build artifact (source stays)
diff --git a/STATE.md b/STATE.md
index 73a8654..0fb2efa 100644
--- a/STATE.md
+++ b/STATE.md
@@ -82,7 +82,7 @@ regression → unit test → CUDA validation (`docs/DEBUGGING.md` §5 checklist)
## Reproducibility notes
- NVIDIA base: `open-gpu-kernel-modules` tag **610.57.04** + patch series
- in `patches/nvidia/` (re-brands version string to 570.144 to match the
+ in `legacy-patches/nvidia/` (re-brands version string to 570.144 to match the
GSP firmware ABI; adds the vGPU VFIO interface headers + symbol exports).
- GSP firmware: `nvidia/tu102/gsp/gsp-570.144.bin` from
[linux-firmware.git](https://github.com/NVIDIA/linux-firmware)
diff --git a/docs/ONBOARDING.md b/docs/ONBOARDING.md
index 1d0a4f7..bc61a03 100644
--- a/docs/ONBOARDING.md
+++ b/docs/ONBOARDING.md
@@ -53,7 +53,7 @@ open-iov/
├── legacy-driver-guest/ # historical guest-side driver (reference only, NOT built)
├── firmware/57X-GSP/570.144/ # GSP blob + analysis scripts (per-version dirs)
├── nvidia-open-gpu-kernel-modules/ # NVIDIA OpenRM source (patched, builds nvidia.ko)
-├── patches/nvidia/ # our delta vs upstream OpenRM tag
+├── legacy-patches/nvidia/ # our delta vs upstream OpenRM tag
├── scripts/ # stack_manager.sh (THE tool), vgpu_vm.py (THE harness), helpers
├── tools/ # guest monitor, failure analyzer, benchmarks, ghidra
├── config/ # declarative YAML: hardware/, versions/
diff --git a/docs/VERSION_UPGRADE.md b/docs/VERSION_UPGRADE.md
index 94c7d68..b9bd387 100644
--- a/docs/VERSION_UPGRADE.md
+++ b/docs/VERSION_UPGRADE.md
@@ -92,7 +92,7 @@ versions safely.
## 6. Rebuild host + guest against the new anchor
-1. Point `patches/nvidia/` at the new OpenRM tag (rebase our delta; verify
+1. Point `legacy-patches/nvidia/` at the new OpenRM tag (rebase our delta; verify
`modinfo nvidia.ko | grep depends` still shows `open-iov-vfio`).
2. `./scripts/stack_manager.sh build-all` (kernel → nvidia → userspace).
3. Install the new host firmware to `/lib/firmware/`
diff --git a/docs/old/ARCHITECTURE.md b/docs/old/ARCHITECTURE.md
deleted file mode 100644
index f9b7ae4..0000000
--- a/docs/old/ARCHITECTURE.md
+++ /dev/null
@@ -1,476 +0,0 @@
-# Open-IOV vGPU-IO Architecture Document
-
-## Overview
-
-Open-IOV vGPU-IO is a complete open-source implementation of NVIDIA vGPU (virtual GPU) technology for Turing architecture GPUs (TU102/TU104), enabling GPU virtualization without proprietary GRID host drivers. The project provides:
-
-- **Host-side VFIO mdev driver** (`open-iov-vfio.ko`) - Creates mediated devices for QEMU/KVM
-- **Guest-side vGPU driver** (`gsp-vgpu.ko`) - Communicates with GSP firmware via RPC
-- **Userspace library** (`libiov.so`/`libvgpu.so`) - C API for VF management and GPU operations
-- **Firmware decompilation** - Complete reverse engineering of GSP 570.144W firmware
-
-## System Architecture
-
-```
-╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
-║ HOST SYSTEM ║
-║ ╔════════════════════════════════════════════════════════════════════════════════════════════════════════════╗ ║
-║ ║ ║ ║
-║ ║ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐ ║ ║
-║ ║ │ USERSPACE (Host) │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌──────────────┐ ┌─────────────────────┐ ┌──────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ QEMU/KVM │ │ libvfio-user │ │ mdev management CLI / mdev management daemon │ │ ║ ║
-║ ║ │ │ │ │ │ │ (GPU Virtualization Management CLI/Manager) │ │ ║ ║
-║ ║ │ │ -device vfio-│ │ - VFIO userspace │ │ │ │ ║ ║
-║ ║ │ │ pci,sysfsdev│ │ library │ │ • mdev create/destroy │ │ ║ ║
-║ ║ │ │ │ │ - ioctl/eventfd │ │ • VF lifecycle management │ │ ║ ║
-║ ║ │ │ ┌──────────┐ │ │ - mmap support │ │ • Migration orchestration │ │ ║ ║
-║ ║ │ │ │ VFIO │ │ │ │ │ • Resource allocation │ │ ║ ║
-║ ║ │ │ │ Region │ │ └──────────┬──────────┘ └──────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ │ (mdev) │ │ │ │ ║ ║
-║ ║ │ │ └────┬─────┘ │ │ │ ║ ║
-║ ║ │ │ │ │ ▼ │ ║ ║
-║ ║ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ │ │ │ libvgpu.so / libiov.so (Host-side) │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ ║ ║
-║ ║ │ │ │ │ │ • vgpu_open/close/get_info │ │ ║ ║
-║ ║ │ │ │ │ │ • vgpu_vf_create/destroy/get_info │ │ ║ ║
-║ ║ │ │ │ │ │ • vgpu_mem_alloc/free/map/unmap/pin/unpin │ │ ║ ║
-║ ║ │ │ │ │ │ • vgpu_bar_config/force_access/save/restore │ │ ║ ║
-║ ║ │ │ │ │ │ • vgpu_wpr_protect_write/read/unprotect/set_timeout/register_callback │ │ ║ ║
-║ ║ │ │ │ │ │ • vgpu_schedule/yield │ │ ║ ║
-║ ║ │ │ │ │ │ • vgpu_register/unregister_event_callback, vgpu_process_events │ │ ║ ║
-║ ║ │ │ │ │ │ • vgpu_migrate_start/status/cancel │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ ║ ║
-║ ║ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ ║ ║
-║ ║ │ │ │ │ │ │ rpc_emulator.c (Host-side Emulation) │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ • rpc_emu_bar_config/save/restore/get_state │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ • rpc_emu_wpr_protect/unprotect/set_timeout/check_access │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ • rpc_emu_schedule/yield │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ • rpc_emu_notify_register/unregister/send │ │ │ ║ ║
-║ ║ │ │ │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ ║ ║
-║ ║ │ │ │ │ └──────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ └──────┼────────┘ │ ║ ║
-║ ║ │ │ VFIO_DEVICE_GET_REGION_INFO / VFIO_DEVICE_GET_IRQ_INFO / VFIO_DEVICE_RESET │ ║ ║
-║ ║ │ │ mmap() / ioctl() / read() / write() / poll() │ ║ ║
-║ ║ │ ▼ │ ║ ║
-║ ║ └─────────┼──────────────────────────────────────────────────────────────────────────────────────────┘ ║ ║
-║ ║ │ ║ ║
-║ ║ ▼ ║ ║
-║ ║ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐ ║ ║
-║ ║ │ KERNEL SPACE (Host) │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ nvidia.ko (Host RM Kernel Module) │ │ ║ ║
-║ ║ │ │ (NVIDIA OpenRM 570.144 - Host Driver) │ │ ║ ║
-║ ║ │ │ │ │ ║ ║
-║ ║ │ │ • GSP Firmware Boot & Management │ │ ║ ║
-║ ║ │ │ • Physical GPU Resource Management (VRAM, engines, etc.) │ │ ║ ║
-║ ║ │ │ • vGPU VFIO Symbol Exports: │ │ ║ ║
-║ ║ │ │ - nvidia_vgpu_vfio_get_ops() │ │ ║ ║
-║ ║ │ │ - nvidia_vgpu_vfio_set_ops() │ │ ║ ║
-║ ║ │ │ - nv_vgpu_mdev_register_parent() │ │ ║ ║
-║ ║ │ │ - nv_vgpu_mdev_unregister_parent() │ │ ║ ║
-║ ║ │ │ • GPC Callbacks (from open-iov-vfio.ko): │ │ ║ ║
-║ ║ │ │ - vgpu_create / vgpu_delete / vgpu_bar_info / vgpu_start │ │ ║ ║
-║ ║ │ │ - get_name / get_description / get_instances / get_sparse_mmap │ │ ║ ║
-║ ║ │ │ - update_request │ │ ║ ║
-║ ║ │ │ • Host IRQ/MSI-X Handler (owns physical GPU interrupt) │ │ ║ ║
-║ ║ │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ open-iov-vfio.ko (Host VFIO mdev Driver) │ │ ║ ║
-║ ║ │ │ │ │ ║ ║
-║ ║ │ │ • mdev_parent registration with nvidia.ko │ │ ║ ║
-║ ║ │ │ • VFIO Device Ops: probe/remove/open/close/ioctl/mmap │ │ ║ ║
-║ ║ │ │ • PCI Config Space Emulation (256 bytes): │ │ ║ ║
-║ ║ │ │ - Vendor=0x10DE, Device=0x1ED3 (TU104 vGPU) │ │ ║ ║
-║ ║ │ │ - BAR0=16MB, BAR1=256MB, BAR2=32MB, BAR3=32MB (all 64-bit) │ │ ║ ║
-║ ║ │ │ - Capabilities: PM, MSI, MSI-X (Table@BAR0+0x2000), PCIe │ │ ║ ║
-║ ║ │ │ • BAR Trap Emulation (bar_emulation.c): │ │ ║ ║
-║ ║ │ │ - 64 trapped regions covering all BAR0 registers │ │ ║ ║
-║ ║ │ │ - Shadow memory for register state │ │ ║ ║
-║ ║ │ │ • GSP Communication (gsp_comm.c): │ │ ║ ║
-║ ║ │ │ - Polling-based doorbell (queue head @ 0x110c00) │ │ ║ ║
-║ ║ │ │ - Shared memory region for RPC messages │ │ ║ ║
-║ ║ │ │ • Firmware-Decompiled RPC Client (gsp_rpc_client.c + gsp_rpc_integration.c): │ │ ║ ║
-║ ║ │ │ - All 12 RPC types: ALLOC, FREE, MAP, UNMAP, PIN, UNPIN, │ │ ║ ║
-║ ║ │ │ SCHEDULE, YIELD, NOTIFY, BAR_TRAP, MIGRATE, DEBUG │ │ ║ ║
-║ ║ │ │ - Real firmware addresses from decompilation │ │ ║ ║
-║ ║ │ │ • Memory Management (memory.c): │ │ ║ ║
-║ ║ │ │ - DMA mapping, pin/unpin, map/unmap │ │ ║ ║
-║ ║ │ │ • IRQ Forwarding (irq.c): │ │ ║ ║
-║ ║ │ │ - MSI-X table/PBA emulation │ │ ║ ║
-║ ║ │ │ - eventfd trigger injection to guest │ │ ║ ║
-║ ║ │ │ • Live Migration (migration.c): │ │ ║ ║
-║ ║ │ │ - 4-phase: QUERY→PREPARE→TRANSFER→COMMIT→CLEANUP │ │ ║ ║
-║ ║ │ │ - Dual jump tables (0x04179ED8, 0x04179FBC) │ │ ║ ║
-║ ║ │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ vfio-mdev.ko / vfio-pci.ko (Kernel VFIO Core) │ │ ║ ║
-║ ║ │ │ • Mediated device framework │ │ ║ ║
-║ ║ │ │ • VFIO PCI device emulation │ │ ║ ║
-║ ║ │ │ • IOMMU DMA mapping (DMA remapping) │ │ ║ ║
-║ ║ │ │ • Region/IRQ index mapping: │ │ ║ ║
-║ ║ │ │ - VFIO_PCI_BAR0_REGION_INDEX → BAR0 (16MB) │ │ ║ ║
-║ ║ │ │ - VFIO_PCI_BAR1_REGION_INDEX → BAR1 (256MB) │ │ ║ ║
-║ ║ │ │ - VFIO_PCI_BAR2_REGION_INDEX → BAR2 (32MB) │ │ ║ ║
-║ ║ │ │ - VFIO_PCI_BAR3_REGION_INDEX → BAR3 (32MB) │ │ ║ ║
-║ ║ │ │ - VFIO_PCI_CONFIG_REGION_INDEX → PCI Config Space (256B) │ │ ║ ║
-║ ║ │ │ - VFIO_PCI_MSIX_REGION_INDEX → MSI-X Table/PBA │ │ ║ ║
-║ ║ │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ └──────────────────────────────────────────────────────────────────────────────────────────────────────┘ ║ ║
-║ ║ ║ ║
-║ ║ ════════════════════════════════════════════════════════════════════════════════════════════════════════════ ║ ║
-║ ║ HARDWARE (Physical GPU) ║ ║
-║ ║ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐ ║ ║
-║ ║ │ NVIDIA TU102/TU104 GPU (RTX 2080 Ti / T4 / etc.) │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ ║ ║
-║ ║ │ │ BAR0 │ │ BAR1 │ │ BAR2 │ │ BAR3 │ │ GSP FALCON │ │ ║ ║
-║ ║ │ │ (16 MB) │ │ (256 MB) │ │ (32 MB) │ │ (32 MB) │ │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ ┌─────────────────┐ │ │ ║ ║
-║ ║ │ │ Config Regs │ │ Framebuffer │ │ Reserved │ │ Reserved │ │ │ REAL GSP │ │ │ ║ ║
-║ ║ │ │ Doorbell │ │ (VRAM) │ │ │ │ │ │ │ FIRMWARE │ │ │ ║ ║
-║ ║ │ │ Queue Heads │ │ │ │ │ │ │ │ │ (570.144W) │ │ │ ║ ║
-║ ║ │ │ Shared Mem │ │ │ │ │ │ │ │ │ │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ RPC Dispatchers │ │ │ ║ ║
-║ ║ │ │ 0x110c00 │ │ │ │ │ │ │ │ │ • Primary │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 0x057A1AC0 │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ • Secondary │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 0x04ED39DC │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ Specialized │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ Handlers: │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ • BAR_TRAP │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 0x04CB8188 │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ • WPR x2 │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 0x04F00B0C │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 0x04F00C78 │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ • ALLOC │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 0x057E94EC │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ • SCHEDULE │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 0x051EFBF4 │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ • Migration │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 0x04179ED8 │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 0x04179FBC │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ 12 RPC Types: │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ ALLOC, FREE, │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ MAP, UNMAP, │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ PIN, UNPIN, │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ SCHEDULE, │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ YIELD, NOTIFY, │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ BAR_TRAP, │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ │ MIGRATE, DEBUG │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ │ │ │ │ └─────────────────┘ │ │ ║ ║
-║ ║ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ Physical IRQ (MSI-X) ──────────────────────────────────────────────► nvidia.ko ISR │ ║ ║
-║ ║ └──────────────────────────────────────────────────────────────────────────────────────────────────────┘ ║ ║
-║ ║ ║ ║
-║ ╚════════════════════════════════════════════════════════════════════════════════════════════════════════════╝ ║
-║ ║
-╚════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
-
- │ VFIO MEDIATED DEVICE (mdev) │
- │ sysfs: /sys/bus/mdev/devices/<UUID>/ │
- │ • PCI Config Space (256B) │
- │ • BAR0 Region (16MB) │
- │ • BAR1 Region (256MB) │
- │ • BAR2 Region (32MB) │
- │ • BAR3 Region (32MB) │
- │ • MSI-X Table/PBA Region │
- │ • IRQs (MSI-X vectors) │
- ▼
-
-╔═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
-║ GUEST VM ║
-║ ╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗ ║
-║ ║ ║ ║
-║ ║ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐ ║ ║
-║ ║ │ USERSPACE (Guest) │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ Guest Applications │ │ ║ ║
-║ ║ │ │ │ │ ║ ║
-║ ║ │ │ • CUDA Applications │ │ ║ ║
-║ ║ │ │ • OpenGL/Vulkan Applications │ │ ║ ║
-║ ║ │ │ • Video Encode/Decode (NVENC/NVDEC) │ │ ║ ║
-║ ║ │ │ • AI/ML Workloads (cuDNN, TensorRT) │ │ ║ ║
-║ ║ │ │ • Custom vGPU Management (via libvgpu.so) │ │ ║ ║
-║ ║ │ └────────────────────────────────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ libvgpu.so / libiov.so (Guest-side Userspace Library) │ │ ║ ║
-║ ║ │ │ │ │ ║ ║
-║ ║ │ │ • vgpu_open/close/get_info │ │ ║ ║
-║ ║ │ │ • vgpu_vf_create/destroy/get_info │ │ ║ ║
-║ ║ │ │ • vgpu_mem_alloc/free/map/unmap/pin/unpin │ │ ║ ║
-║ ║ │ │ • vgpu_bar_config/force_access/save/restore │ │ ║ ║
-║ ║ │ │ • vgpu_wpr_protect_write/read/unprotect/set_timeout/register_callback │ │ ║ ║
-║ ║ │ │ • vgpu_schedule/yield │ │ ║ ║
-║ ║ │ │ • vgpu_register/unregister_event_callback, vgpu_process_events │ │ ║ ║
-║ ║ │ │ • vgpu_migrate_start/status/cancel │ │ ║ ║
-║ ║ │ │ │ │ ║ ║
-║ ║ │ │ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │ │ ║ ║
-║ ║ │ │ │ rpc_emulator.c (Guest-side Emulation Fallbacks) │ │ │ ║ ║
-║ ║ │ │ │ │ │ │ ║ ║
-║ ║ │ │ │ • rpc_emu_bar_config/save/restore/get_state │ │ │ ║ ║
-║ ║ │ │ │ • rpc_emu_wpr_protect/unprotect/set_timeout/check_access │ │ │ ║ ║
-║ ║ │ │ │ • rpc_emu_schedule/yield │ │ │ ║ ║
-║ ║ │ │ │ • rpc_emu_notify_register/unregister/send │ │ │ ║ ║
-║ ║ │ │ └────────────────────────────────────────────────────────────────────────────────────────────┘ │ │ ║ ║
-║ ║ │ └────────────────────────────────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ libnvidia-ml.so / libnvidia-opencl.so / libcuda.so (NVIDIA Userspace Drivers) │ │ ║ ║
-║ ║ │ │ • Standard NVIDIA userspace driver stack (unchanged) │ │ ║ ║
-║ ║ │ │ • Communicates with guest nvidia.ko via ioctl on /dev/nvidia* │ │ ║ ║
-║ ║ │ └────────────────────────────────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ └──────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ║ ║
-║ ║ ║ ║
-║ ║ ═════════════════════════════════════════════════════════════════════════════════════════════════════════════ ║ ║
-║ ║ KERNEL SPACE (Guest) ║ ║
-║ ║ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ nvidia.ko (Guest RM Kernel Module) │ │ ║ ║
-║ ║ │ │ (NVIDIA OpenRM 570.144 - Guest Driver, UNMODIFIED) │ │ ║ ║
-║ ║ │ │ │ │ ║ ║
-║ ║ │ │ • Detects vGPU via PCI Config Space (Vendor=0x10DE, Device=0x1ED3) │ │ ║ ║
-║ ║ │ │ • Maps BAR0 (config), BAR1 (framebuffer), BAR2, BAR3 │ │ ║ ║
-║ ║ │ │ • Sets up MSI-X interrupts (table @ BAR0+0x2000, PBA @ BAR0+0x3000) │ │ ║ ║
-║ ║ │ │ • GSP Client: │ │ ║ ║
-║ ║ │ │ - Writes to BAR0 doorbell (queue head @ 0x110c00) │ │ ║ ║
-║ ║ │ │ - Reads/writes shared memory for RPC messages │ │ ║ ║
-║ ║ │ │ - Expects GSP firmware with vGPU RPC handlers │ │ ║ ║
-║ ║ │ │ • RM (Resource Manager) for GPU resources │ │ ║ ║
-║ ║ │ │ • nvidia-modeset.ko / nvidia-uvm.ko / nvidia-peermem.ko │ │ ║ ║
-║ ║ │ └────────────────────────────────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ gsp-vgpu.ko (Guest vGPU Driver - Open-IOV) │ │ ║ ║
-║ ║ │ │ │ │ ║ ║
-║ ║ │ │ • Char Device: /dev/gsp-vgpu (misc device) │ │ ║ ║
-║ ║ │ │ • IOCTL Interface (matches libvgpu.so API): │ │ ║ ║
-║ ║ │ │ - GSP_IOCTL_CREATE_VF / DESTROY_VF │ │ ║ ║
-║ ║ │ │ - GSP_IOCTL_ALLOC / FREE / MAP / UNMAP / PIN / UNPIN │ │ ║ ║
-║ ║ │ │ - GSP_IOCTL_BAR_CONFIG / FORCE / SAVE / RESTORE │ │ ║ ║
-║ ║ │ │ - GSP_IOCTL_WPR_PROTECT / UNPROTECT / TIMEOUT │ │ ║ ║
-║ ║ │ │ - GSP_IOCTL_SCHEDULE / YIELD │ │ ║ ║
-║ ║ │ │ - GSP_IOCTL_MIGRATE │ │ ║ ║
-║ ║ │ │ - GSP_IOCTL_GET_INFO │ │ ║ ║
-║ ║ │ │ • RPC Client (rpc/gsp_rpc.c): │ │ ║ ║
-║ ║ │ │ - Doorbell writes to queue head │ │ ║ ║
-║ ║ │ │ - Ring buffer management │ │ ║ ║
-║ ║ │ │ • Emulation Mode (AUTO-DETECTED): │ │ ║ ║
-║ ║ │ │ - Test BAR_TRAP RPC at load; if timeout → enable emulation │ │ ║ ║
-║ ║ │ │ - Module params: emulation_mode (ro), emulation_override (force) │ │ ║ ║
-║ ║ │ │ - In emulation: BAR_TRAP, WPR, ALLOC, PIN, MAP handled locally │ │ ║ ║
-║ ║ │ │ • Debugfs: /sys/kernel/debug/gsp-vgpu/ │ │ ║ ║
-║ ║ │ │ • VF Lifecycle (vf/gsp_vf.c) │ │ ║ ║
-║ ║ │ │ • BAR Emulation (bar/gsp_bar.c) │ │ ║ ║
-║ ║ │ │ • WPR Management (wpr/gsp_wpr.c) │ │ ║ ║
-║ ║ │ │ • Migration (migration/gsp_migration.c) │ │ ║ ║
-║ ║ │ └────────────────────────────────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ │ ┌────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ ║ ║
-║ ║ │ │ VFIO-PCI Core (Guest Kernel) │ │ ║ ║
-║ ║ │ │ • vfio-pci.ko: PCI device emulation for VFIO │ │ ║ ║
-║ ║ │ │ • Handles mmap of BAR regions │ │ ║ ║
-║ ║ │ │ • MSI-X interrupt handling │ │ ║ ║
-║ ║ │ │ • Config space read/write │ │ ║ ║
-║ ║ │ └────────────────────────────────────────────────────────────────────────────────────────────────────┘ │ ║ ║
-║ ║ │ │ ║ ║
-║ ║ └──────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ║ ║
-║ ║ ║ ║
-║ ║ ══════════════════════════════════════════════════════════════════════════════════════════════════════════════ ║ ║
-║ ║ VIRTUAL GPU (mdev Device as seen by Guest) ║ ║
-║ ║ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐ ║ ║
-║ ║ │ PCI Config Space (256B) │ BAR0 (16MB) │ BAR1 (256MB) │ BAR2 (32MB) │ BAR3 (32MB) │ MSI-X │ ║ ║
-║ ║ │ • Vendor=0x10DE │ Config Regs │ Framebuffer │ Reserved │ Reserved │ Table │ ║ ║
-║ ║ │ • Device=0x1ED3 │ Doorbell │ (VRAM) │ │ │ @0x2000│ ║ ║
-║ ║ │ • Class=0x030000 │ Queue Heads │ │ │ │ PBA │ ║ ║
-║ ║ │ • BARs: 64-bit, prefetch │ Shared Mem │ │ │ │ @0x3000│ ║ ║
-║ ║ │ • Caps: PM, MSI, MSI-X, │ @0x110c00 │ │ │ │ │ ║ ║
-║ ║ │ PCIe │ ║ ║
-║ ║ └──────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ║ ║
-║ ║ ║ ║
-║ ╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝ ║
-╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
-```
-
-## Communication Pathways (Host ↔ Guest)
-
-### 1. **VFIO Region Access (Memory-Mapped I/O)**
-```
-Guest App → libvgpu.so → ioctl(/dev/gsp-vgpu) → gsp-vgpu.ko
- → Guest vfio-pci.ko → mmap(BAR0/BAR1/BAR2/BAR3)
- → Host vfio-pci.ko → open-iov-vfio.ko BAR emulation
- → Host nvidia.ko → Physical GPU BARs
-```
-**Path**: Guest userspace → Guest kernel → Host kernel → Physical GPU
-**Mechanism**: VFIO mmap with IOMMU DMA remapping
-
-### 2. **PCI Config Space Access**
-```
-Guest nvidia.ko → pci_read_config_* / pci_write_config_*
- → Guest vfio-pci.ko → VFIO_DEVICE_GET_REGION_INFO (CONFIG_REGION)
- → Host open-iov-vfio.ko → nv_vgpu_config_read/write()
- → Returns emulated 256-byte config space
-```
-**Path**: Guest kernel → Host kernel (via VFIO ioctl)
-**Mechanism**: VFIO config space region emulation
-
-### 3. **GSP RPC Communication (Native Path)**
-```
-Guest nvidia.ko → Write BAR0 doorbell (0x110c00) + shared memory
- → Physical GPU GSP firmware receives RPC
- → GSP processes RPC (ALLOC, MAP, PIN, SCHEDULE, BAR_TRAP, etc.)
- → GSP writes response to shared memory
- → Guest nvidia.ko reads response
-```
-**Path**: Guest kernel → Physical GPU (direct, no host kernel involvement)
-**Mechanism**: Doorbell register + shared memory in BAR0
-
-### 4. **GSP RPC Communication (Emulation Path - Host Mediated)**
-```
-Guest nvidia.ko → Write BAR0 doorbell (0x110c00)
- → Host open-iov-vfio.ko (polling) detects doorbell
- → gsp_comm.c → gsp_rpc_integration.c → gsp_rpc_client.c
- → Firmware-decompiled RPC handlers (emulated in host kernel)
- → Response written to shared memory
- → Guest nvidia.ko reads response
-```
-**Path**: Guest kernel → Host kernel (open-iov-vfio.ko) → Emulated RPC
-**Mechanism**: Host polls GSP doorbell, processes RPC in software
-
-### 5. **BAR Trap Emulation**
-```
-Guest nvidia.ko → Write to trapped BAR register (page fault)
- → Guest vfio-pci.ko → VFIO page fault handler
- → Host open-iov-vfio.ko → nv_vgpu_bar_trap()
- → If native: gsp_rpc_bar_trap() → GSP firmware (0x04CB8188)
- → If emulated: rpc_emu_bar_trap() in host userspace (libvgpu.so)
- → Result written back to guest BAR mapping
-```
-**Path**: Guest kernel page fault → Host kernel → Host userspace (emulation) or GSP firmware
-**Mechanism**: VFIO page fault + BAR trap emulation
-
-### 6. **Interrupt Forwarding (Host → Guest)**
-```
-Physical GPU → MSI-X IRQ → Host nvidia.ko ISR
- → nvidia.ko calls nv_vgpu_vfio_inject_interrupt() (VFIO ops)
- → open-iov-vfio.ko → eventfd_signal()
- → QEMU/KVM → Guest MSI-X interrupt injected
- → Guest nvidia.ko ISR handles interrupt
-```
-**Path**: Physical GPU → Host kernel → Host userspace (QEMU) → Guest kernel
-**Mechanism**: VFIO interrupt injection via eventfd
-
-### 7. **Userspace Management (mdev management CLI/mdev management daemon)**
-```
-mdev management CLI → libvgpu.so (host) → ioctl(/dev/vfio/<mdev>)
- → open-iov-vfio.ko → mdev VFIO ops
- → VF creation, BAR config, memory ops, migration
-```
-**Path**: Host userspace → Host kernel (VFIO mdev)
-**Mechanism**: Standard VFIO ioctl on mdev device
-
-### 8. **Guest vGPU Driver Communication**
-```
-Guest App → libvgpu.so (guest) → ioctl(/dev/gsp-vgpu)
- → gsp-vgpu.ko → Internal RPC client
- → If emulation: Local handling in gsp-vgpu.ko
- → If native: GSP RPC via BAR0 doorbell
-```
-**Path**: Guest userspace → Guest kernel (gsp-vgpu.ko) → GSP or emulation
-
-## Key Component Summary
-
-| Component | Location | Type | Purpose |
-|-----------|----------|------|---------|
-| **nvidia.ko (Host)** | Host Kernel | RM Driver | Boots GSP, manages physical GPU, exports vGPU VFIO symbols |
-| **open-iov-vfio.ko** | Host Kernel | VFIO mdev Driver | Creates mdev, PCI config space, BAR emulation, RPC integration, IRQ forwarding |
-| **gsp-vgpu.ko** | Guest Kernel | vGPU Driver | Char device `/dev/gsp-vgpu`, ioctl API, emulation mode, RPC client |
-| **nvidia.ko (Guest)** | Guest Kernel | RM Driver | Standard NVIDIA driver, detects vGPU, communicates with GSP |
-| **libvgpu.so / libiov.so (Host)** | Host Userspace | Library | Management API (mdev management CLI/mdev management daemon), emulation fallbacks |
-| **libvgpu.so / libiov.so (Guest)** | Guest Userspace | Library | Application API, emulation fallbacks |
-| **libnvidia-*.so** | Guest Userspace | NVIDIA Drivers | Standard CUDA/OpenGL/OpenCL userspace stack |
-| **mdev management CLI / mdev management daemon** | Host Userspace | Tools | mdev lifecycle, VF management, migration orchestration |
-| **REAL GSP Firmware** | Physical GPU | Firmware | 570.144W, 12 RPC types, BAR_TRAP/WPR/SCHEDULE/MIGRATE handlers |
-| **EMULATED GSP** | Host Kernel + Userspace | Software | rpc_emulator.c, gsp_rpc_client.c (when GSP lacks vGPU handlers) |
-
-## Emulation Mode Details
-
-### When Enabled
-- **Auto-detect**: At gsp-vgpu.ko load, sends test BAR_TRAP RPC
-- **Timeout/Error** → `emulation_mode = true`
-- **Module params**: `emulation_override=1` (force on), `emulation_override=0` (force off)
-
-### What Gets Emulated
-| Operation | Host Kernel (open-iov-vfio.ko) | Host Userspace (libvgpu.so) | Guest Kernel (gsp-vgpu.ko) |
-|-----------|-------------------------------|----------------------------|---------------------------|
-| BAR_TRAP | nv_vgpu_bar_trap() → rpc_emu_bar_trap() | rpc_emu_bar_config/save/restore | gsp_bar_force_access() |
-| WPR | nv_vgpu_wpr_*() | rpc_emu_wpr_protect/unprotect | gsp_vf_wpr_protect/unprotect |
-| ALLOC/MAP/PIN | gsp_rpc_client.c (local) | rpc_emu_* fallbacks | gsp_vf_mem_alloc/map/pin |
-| SCHEDULE/YIELD | gsp_rpc_schedule/yield (workqueue) | rpc_emu_schedule/yield | gsp_vf_schedule/yield |
-| NOTIFY | gsp_rpc_notify_register/unregister | rpc_emu_notify_register/unregister/send | gsp_vf_notify_* |
-| MIGRATION | migration.c (4-phase) | rpc_emu_migrate_* | gsp_migration_start |
-
-## Build Artifacts
-
-```
-$OPEN_IOV_ROOT/
-├── nvidia-open-gpu-kernel-modules/kernel-open/nvidia.ko (34MB) Host RM Driver
-├── kernel/open-iov-vfio.ko (2.8MB) Host VFIO mdev Driver
-├── driver/gsp-vgpu.ko (1.8MB) Guest vGPU Driver
-├── userspace/lib/libiov.so (76KB) Userspace Library (libvgpu.so symlink)
-├── userspace/examples/example_vgpu (28KB) Test Application
-├── firmware/570-GSP/gsp-570.144.fwimage.bin (28MB) GSP Firmware
-├── scripts/load_vgpu_stack.sh Host module loader
-├── scripts/create_mdev.sh mdev creation
-├── scripts/launch_qemu_vgpu.sh QEMU launcher
-├── scripts/test_vgpu_stack.sh Test suite
-├── scripts/setup_guest_driver.sh Guest driver setup
-├── scripts/unload_vgpu_stack.sh Cleanup
-├── docs/ARCHITECTURE.md This document
-└── wiki/ 10 technical docs
-```
-
-## Deployment Sequence
-
-```bash
-# HOST (after reboot to clear module_blacklist)
-# 1. Load NVIDIA OpenRM host driver (exports vGPU VFIO symbols)
-sudo insmod nvidia-open-gpu-kernel-modules/kernel-open/nvidia.ko
-
-# 2. Load Open-IOV VFIO mdev driver (registers mdev parent with nvidia.ko)
-sudo insmod kernel/open-iov-vfio.ko
-
-# 3. Create mediated device for QEMU
-./scripts/create_mdev.sh # Creates /sys/bus/mdev/devices/<UUID>/
-
-# 4. Launch QEMU with vGPU
-./scripts/launch_qemu_vgpu.sh # -device vfio-pci,sysfsdev=/sys/bus/mdev/devices/<UUID>
-
-# GUEST (inside VM)
-# 5. Install NVIDIA driver (unmodified OpenRM)
-./scripts/setup_guest_driver.sh # Installs nvidia.ko, firmware, loads driver
-
-# 6. Verify
-nvidia-smi # Should show vGPU (T4 / A100 / etc.)
-lspci -d 10de: # Should show 10de:1ed3 (TU104 vGPU)
-```
-
----
-
-*Architecture Version: 2.0 (with detailed host/guest communication pathways)*
-*Last Updated: $(date)*
-*Project: $OPEN_IOV_ROOT* \ No newline at end of file
diff --git a/install.sh b/install.sh
index 8cfb885..36a1ef2 100755
--- a/install.sh
+++ b/install.sh
@@ -56,7 +56,7 @@
set -euo pipefail
OPEN_IOV_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-PATCH_DIR="$OPEN_IOV_ROOT/patches/nvidia"
+PATCH_DIR="$OPEN_IOV_ROOT/legacy-patches/nvidia"
NVIDIA_DIR="$OPEN_IOV_ROOT/nvidia-open-gpu-kernel-modules"
NVIDIA_REPO="https://github.com/NVIDIA/open-gpu-kernel-modules.git"
NVIDIA_TAG="${NVIDIA_TAG:-610.57.04}"
diff --git a/legacy-driver-guest/Makefile b/legacy-driver-guest/Makefile
deleted file mode 100644
index 4675cbf..0000000
--- a/legacy-driver-guest/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-# GSP vGPU-IO Driver Makefile
-
-obj-m += gsp-vgpu.o
-
-gsp-vgpu-y := \
- core/gsp_core.o \
- rpc/gsp_rpc.o \
- vf/gsp_vf.o \
- bar/gsp_bar.o \
- wpr/gsp_wpr.o \
- migration/gsp_migration.o \
- debugfs/gsp_debugfs.o
-
-ccflags-y += -I$(src)/include
-ccflags-y += -I$(src)/../kernel/include
-
-# Build against the kernel source
-KDIR ?= /lib/modules/$(shell uname -r)/build
-
-all:
- $(MAKE) -C $(KDIR) M=$(PWD) modules
-
-clean:
- $(MAKE) -C $(KDIR) M=$(PWD) clean
-
-install:
- $(MAKE) -C $(KDIR) M=$(PWD) modules_install
-
-load: all
- sudo insmod gsp-vgpu.ko firmware_name=gsp-570.144.fwimage.bin
-
-unload:
- sudo rmmod gsp-vgpu
-
-test: all load
- @echo "Driver loaded, checking status..."
- sleep 2
- dmesg -T | tail -20
- @echo "Checking debugfs..."
- ls -la /sys/kernel/debug/gsp-vgpu/ 2>/dev/null || echo "Debugfs not available"
- @echo "Checking device nodes..."
- ls -la /dev/gsp-vgpu* 2>/dev/null || echo "No device nodes"
-
-.PHONY: all clean install load unload test \ No newline at end of file
diff --git a/legacy-driver-guest/README.md b/legacy-driver-guest/README.md
deleted file mode 100644
index 309613a..0000000
--- a/legacy-driver-guest/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# legacy-driver-guest — historical guest-side driver (NOT BUILT)
-
-This directory preserves the **old guest-side vGPU driver** (`gsp-vgpu.ko`)
-from the pre-refactor architecture, where GSP RPC handling lived in a kernel
-module *inside the guest*.
-
-It is kept for reference only:
-
-- The current architecture is **host-only GSP emulation** — the guest runs
- the stock, unmodified `nvidia.ko`, and there is no Open-IOV code in the
- guest. See `docs/GSP_EMULATION_ARCHITECTURE.md`.
-- Nothing here is part of any build target (the top-level Makefile no longer
- references it).
-- `kernel-tests/` holds the old test modules written against this driver's
- internal API (`gsp_core.h`); they are superseded by
- `kernel/tests/gsp_emulation_test.c`, which tests the host-side emulation
- engine through `gsp_emu_process_rpc()`.
-
-Do not add new code here. If you need behavior that only exists in this tree
-(e.g. WPR eventfd work, migration WPR state), port it into the host-side
-`kernel/` modules rather than reviving the guest driver.
diff --git a/legacy-driver-guest/bar/gsp_bar.c b/legacy-driver-guest/bar/gsp_bar.c
deleted file mode 100644
index aa3ed62..0000000
--- a/legacy-driver-guest/bar/gsp_bar.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * GSP vGPU-IO Driver - BAR Emulation
- */
-
-#include "gsp_core.h"
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-/* BAR Emulation Ops */
-static int gsp_bar_trap_handler(struct gsp_vf *vf, struct gsp_bar_trap_payload *trap)
-{
- struct gsp_bar_state *bar = &vf->bar_state;
- struct gsp_bar_trap_response resp = {0};
- size_t resp_size = sizeof(resp);
- int ret;
-
- /* Validate BAR index (we only support BAR1) */
- if (trap->bar_index != 1)
- return -EINVAL;
-
- /* Validate offset */
- if (trap->offset >= bar->aperture_size)
- return -ERANGE;
-
- /* Check ForceBarAccess */
- if (bar->force_access && vf->id != bar->force_vf)
- return -EPERM;
-
- /* In emulation mode, handle locally */
- if (emulation_mode) {
- /* Simulate BAR trap handling */
- if (trap->trap_type == GSP_BAR_WRITE) {
- /* Config write - update aperture */
- bar->aperture_offset = trap->offset;
- bar->aperture_size = trap->value;
- } else if (trap->trap_type == GSP_BAR_ATOMIC) {
- /* Force access control */
- bar->force_access = trap->offset ? true : false;
- bar->force_vf = trap->offset ? vf->id : 0;
- }
- resp.value = 0;
- return 0;
- }
-
- /* Forward to GSP BAR trap handler (0x04CB8188) */
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_BAR_TRAP,
- trap, sizeof(*trap), &resp, &resp_size);
-
- return ret;
-}
-
-/* Aperture Configuration */
-static int gsp_bar_config_aperture(struct gsp_vf *vf, uint64_t offset, uint64_t size)
-{
- struct gsp_bar_state *bar = &vf->bar_state;
- struct gsp_bar_trap_payload payload = {0};
- struct gsp_bar_trap_response resp = {0};
- size_t resp_size = sizeof(resp);
- int ret;
-
- /* Validate alignment (4KB) */
- if (offset & 0xFFF || size & 0xFFF)
- return -EINVAL;
-
- /* Validate max size (256KB per firmware) */
- if (size > 0x40000)
- return -EINVAL;
-
- /* In emulation mode, handle locally */
- if (emulation_mode) {
- bar->aperture_offset = offset;
- bar->aperture_size = size;
- return 0;
- }
-
- payload.bar_index = 1;
- payload.trap_type = GSP_BAR_WRITE; /* Config write */
- payload.offset = offset;
- payload.value = size;
- payload.size = 8;
- payload.vf_id = vf->id;
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_BAR_TRAP,
- &payload, sizeof(payload), &resp, &resp_size);
- if (!ret) {
- bar->aperture_offset = offset;
- bar->aperture_size = size;
- }
-
- return ret;
-}
-
-/* ForceBarAccess Control */
-int gsp_bar_force_access(struct gsp_vf *vf, bool enable)
-{
- struct gsp_bar_state *bar = &vf->bar_state;
- struct gsp_bar_trap_payload payload = {0};
- struct gsp_bar_trap_response resp = {0};
- size_t resp_size = sizeof(resp);
- int ret;
-
- /* In emulation mode, handle locally */
- if (emulation_mode) {
- bar->force_access = enable;
- bar->force_vf = enable ? vf->id : 0;
- return 0;
- }
-
- payload.bar_index = 1;
- payload.trap_type = GSP_BAR_ATOMIC; /* Force access control */
- payload.offset = enable ? 1 : 0;
- payload.value = enable ? vf->id : 0;
- payload.size = 8;
- payload.vf_id = vf->id;
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_BAR_TRAP,
- &payload, sizeof(payload), &resp, &resp_size);
- if (!ret) {
- bar->force_access = enable;
- bar->force_vf = enable ? vf->id : 0;
- }
-
- return ret;
-}
-
-/* State Save for Migration */
-static int gsp_bar_save_state(struct gsp_vf *vf, void *buf, size_t *size)
-{
- struct gsp_bar_state *bar = &vf->bar_state;
- size_t needed = sizeof(*bar) + bar->backing_size;
-
- if (!buf || *size < needed)
- return -ENOSPC;
-
- memcpy(buf, bar, sizeof(*bar));
- if (bar->backing_store && bar->backing_size > 0)
- memcpy(buf + sizeof(*bar), bar->backing_store, bar->backing_size);
-
- *size = needed;
- return 0;
-}
-
-/* State Restore for Migration */
-static int gsp_bar_restore_state(struct gsp_vf *vf, void *buf, size_t size)
-{
- struct gsp_bar_state *bar = &vf->bar_state;
- size_t min_size = sizeof(*bar);
-
- if (!buf || size < min_size)
- return -EINVAL;
-
- memcpy(bar, buf, sizeof(*bar));
-
- if (size > min_size && bar->backing_size > 0) {
- if (!bar->backing_store) {
- bar->backing_store = vzalloc(bar->backing_size);
- if (!bar->backing_store)
- return -ENOMEM;
- }
- memcpy(bar->backing_store, buf + min_size,
- min(size - min_size, bar->backing_size));
- }
-
- /* Reconfigure BAR in GSP */
- return gsp_bar_config_aperture(vf, bar->aperture_offset, bar->aperture_size);
-}
-
-/* VF BAR Initialization */
-int gsp_vf_bar_init(struct gsp_vf *vf)
-{
- struct gsp_bar_state *bar = &vf->bar_state;
- int ret;
-
- /* Initialize with config values */
- bar->aperture_offset = vf->bar1_offset;
- bar->aperture_size = vf->bar1_size;
- bar->force_access = false;
- bar->force_vf = 0;
- bar->backing_store = NULL;
- bar->backing_size = 0;
-
- /* Allocate backing store (max 256KB) */
- if (bar->aperture_size > 0) {
- bar->backing_size = min(bar->aperture_size, (uint64_t)0x40000);
- bar->backing_store = vzalloc(bar->backing_size);
- if (!bar->backing_store)
- return -ENOMEM;
- }
-
- /* Configure aperture in GSP (skip in emulation mode) */
- if (!emulation_mode) {
- ret = gsp_bar_config_aperture(vf, bar->aperture_offset, bar->aperture_size);
- if (ret) {
- dev_err(vf->gsp->dev, "VF %u: BAR aperture config failed: %d\n", vf->id, ret);
- goto err_backing;
- }
- } else {
- dev_info(vf->gsp->dev, "VF %u: BAR1 initialized in emulation mode [0x%llx, 0x%llx)\n",
- vf->id, bar->aperture_offset, bar->aperture_offset + bar->aperture_size);
- }
-
- dev_info(vf->gsp->dev, "VF %u: BAR1 initialized [0x%llx, 0x%llx)\n",
- vf->id, bar->aperture_offset, bar->aperture_offset + bar->aperture_size);
-
- return 0;
-
-err_backing:
- vfree(bar->backing_store);
- bar->backing_store = NULL;
- bar->backing_size = 0;
- return ret;
-}
-
-/* VF BAR Cleanup */
-void gsp_vf_bar_fini(struct gsp_vf *vf)
-{
- struct gsp_bar_state *bar = &vf->bar_state;
-
- vfree(bar->backing_store);
- bar->backing_store = NULL;
- bar->backing_size = 0;
-
- dev_info(vf->gsp->dev, "VF %u: BAR1 cleaned up\n", vf->id);
-}
-
-/* BAR Trap Entry Point (called from ISR/notification) */
-int gsp_vf_bar_trap(struct gsp_vf *vf, struct gsp_bar_trap_payload *trap)
-{
- return gsp_bar_trap_handler(vf, trap);
-}
-
-/* Migration Interface */
-int gsp_migration_bar_save(struct gsp_vf *vf, void *buf, size_t *size)
-{
- return gsp_bar_save_state(vf, buf, size);
-}
-
-int gsp_migration_bar_restore(struct gsp_vf *vf, void *buf, size_t size)
-{
- return gsp_bar_restore_state(vf, buf, size);
-} \ No newline at end of file
diff --git a/legacy-driver-guest/core/gsp_core.c b/legacy-driver-guest/core/gsp_core.c
deleted file mode 100644
index cd41bd2..0000000
--- a/legacy-driver-guest/core/gsp_core.c
+++ /dev/null
@@ -1,654 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * GSP vGPU-IO Driver - Core Implementation
- * Guest vGPU driver - communicates with GSP already booted by host GRID driver
- */
-
-#include "gsp_core.h"
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/delay.h>
-#include <linux/msi.h>
-#include <linux/miscdevice.h>
-#include <linux/uaccess.h>
-
-#define DRIVER_NAME "gsp-vgpu"
-#define DRIVER_VERSION "0.1.0"
-
-/* Emulation mode: skip GSP RPC for BAR/WPR when GSP lacks vGPU handlers */
-bool emulation_mode = true; /* ON by default */
-static bool emulation_override = false; /* true = force emulation, false = force native */
-module_param(emulation_mode, bool, 0444);
-MODULE_PARM_DESC(emulation_mode, "Enable emulation mode for BAR/WPR (skip GSP RPC) - default ON, auto-detects if GSP has vGPU handlers");
-module_param(emulation_override, bool, 0444);
-MODULE_PARM_DESC(emulation_override, "Override auto-detection: 1=force emulation, 0=force native (default: auto-detect)");
-
-/* Forward declarations */
-int gsp_firmware_load(struct gsp_device *gsp);
-int gsp_setup_irq(struct gsp_device *gsp);
-int gsp_rpc_init(struct gsp_device *gsp);
-void gsp_shutdown(struct gsp_device *gsp);
-static void gsp_detect_emulation_mode(struct gsp_device *gsp);
-static long gsp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-static int gsp_open(struct inode *inode, struct file *file);
-static int gsp_release(struct inode *inode, struct file *file);
-
-/* Char device file operations */
-static const struct file_operations gsp_fops = {
- .owner = THIS_MODULE,
- .open = gsp_open,
- .release = gsp_release,
- .unlocked_ioctl = gsp_ioctl,
- .compat_ioctl = gsp_ioctl,
-};
-
-/* Char device open */
-static int gsp_open(struct inode *inode, struct file *file)
-{
- struct gsp_device *gsp = container_of(file->private_data, struct gsp_device, miscdev);
- file->private_data = gsp;
- return 0;
-}
-
-/* Char device release */
-static int gsp_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-/* Char device ioctl */
-static long gsp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct gsp_device *gsp = file->private_data;
- void __user *argp = (void __user *)arg;
- int ret = 0;
-
- mutex_lock(&gsp->chardev_lock);
-
- switch (cmd) {
- case GSP_IOCTL_CREATE_VF: {
- struct gsp_vf_config config;
- if (copy_from_user(&config, argp, sizeof(config))) {
- ret = -EFAULT;
- break;
- }
- ret = gsp_vf_create(gsp, &config);
- break;
- }
- case GSP_IOCTL_DESTROY_VF: {
- uint32_t vf_id;
- if (copy_from_user(&vf_id, argp, sizeof(vf_id))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- gsp_vf_destroy(vf);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_ALLOC: {
- struct gsp_alloc_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_mem_alloc(vf, args.size, args.flags, &args.handle, &args.va);
- if (!ret)
- ret = copy_to_user(argp, &args, sizeof(args)) ? -EFAULT : 0;
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_FREE: {
- struct gsp_free_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_mem_free(vf, args.handle);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_PIN: {
- struct gsp_pin_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_mem_pin(vf, args.handle, args.offset, args.size, &args.dma_addr);
- if (!ret)
- ret = copy_to_user(argp, &args, sizeof(args)) ? -EFAULT : 0;
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_UNPIN: {
- struct gsp_unpin_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_mem_unpin(vf, args.handle);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_MAP: {
- struct gsp_map_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_mem_map(vf, args.handle, args.gpu_va, args.size,
- args.prot, args.flags, args.offset, &args.mapped_va);
- if (!ret)
- ret = copy_to_user(argp, &args, sizeof(args)) ? -EFAULT : 0;
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_UNMAP: {
- struct gsp_unmap_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_mem_unmap(vf, args.handle, args.gpu_va, args.size);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_BAR_CONFIG: {
- struct gsp_bar_config_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_bar_init(vf); /* Re-init with new aperture */
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_BAR_FORCE: {
- struct gsp_bar_force_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_bar_force_access(vf, args.enable);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_BAR_SAVE: {
- struct gsp_bar_save_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_migration_bar_save(vf, args.buf, args.size);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_BAR_RESTORE: {
- struct gsp_bar_restore_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_migration_bar_restore(vf, args.buf, args.size);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_WPR_PROTECT: {
- struct gsp_wpr_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_wpr_protect(vf, args.base, args.size, args.flags);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_WPR_UNPROTECT: {
- struct gsp_wpr_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_wpr_unprotect(vf, args.base);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_WPR_TIMEOUT: {
- struct gsp_wpr_timeout_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_wpr_set_timeout(vf, args.timeout_ns);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_SCHEDULE: {
- struct gsp_schedule_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_schedule(vf, args.priority, args.time_slice_ns);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_YIELD: {
- uint32_t vf_id;
- if (copy_from_user(&vf_id, argp, sizeof(vf_id))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_vf_yield(vf);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_MIGRATE: {
- struct gsp_migrate_args args;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- struct gsp_vf *vf = gsp_vf_get(gsp, args.vf_id);
- if (!vf) {
- ret = -ENOENT;
- break;
- }
- ret = gsp_migration_start(vf, args.dst_vf);
- gsp_vf_put(vf);
- break;
- }
- case GSP_IOCTL_GET_INFO: {
- char info[256];
- snprintf(info, sizeof(info), "GSP vGPU-IO Driver v%s (FW: 570.144W)", DRIVER_VERSION);
- ret = copy_to_user(argp, info, sizeof(info)) ? -EFAULT : 0;
- break;
- }
- default:
- ret = -ENOTTY;
- }
-
- mutex_unlock(&gsp->chardev_lock);
- return ret;
-}
-
-/* PCI Device IDs */
-static const struct pci_device_id gsp_pci_ids[] = {
- { PCI_DEVICE(0x10DE, 0x1E07), .driver_data = 0 }, /* TU102 */
- { PCI_DEVICE(0x10DE, 0x1E08), .driver_data = 0 }, /* TU104 */
- { PCI_DEVICE(0x10DE, 0x1ED3), .driver_data = 0 }, /* TU104 RTX 2080 Super Mobile */
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, gsp_pci_ids);
-
-/* Module Parameters */
-static int max_vfs = 7;
-module_param(max_vfs, int, 0444);
-MODULE_PARM_DESC(max_vfs, "Maximum number of VFs (default: 7)");
-
-static char *firmware_name = "gsp-570.144.fwimage.bin";
-module_param(firmware_name, charp, 0444);
-MODULE_PARM_DESC(firmware_name, "GSP firmware filename (for version verification only)");
-
-/* PCI Probe */
-int gsp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
- struct gsp_device *gsp;
- int ret;
-
- gsp = devm_kzalloc(&pdev->dev, sizeof(*gsp), GFP_KERNEL);
- if (!gsp)
- return -ENOMEM;
-
- gsp->pdev = pdev;
- gsp->dev = &pdev->dev;
- gsp->max_vfs = max_vfs;
- pci_set_drvdata(pdev, gsp);
-
- mutex_init(&gsp->vf_lock);
- idr_init(&gsp->vf_idr);
- INIT_LIST_HEAD(&gsp->vf_list);
-
- /* Enable PCI device */
- ret = pcim_enable_device(pdev);
- if (ret) {
- dev_err(&pdev->dev, "Failed to enable PCI device: %d\n", ret);
- return ret;
- }
-
- pci_set_master(pdev);
-
- /* Map BARs */
- gsp->bar0 = pcim_iomap(pdev, 0, 0);
- gsp->bar1 = pcim_iomap(pdev, 1, 0);
- if (!gsp->bar0 || !gsp->bar1) {
- dev_err(&pdev->dev, "Failed to map BARs\n");
- return -ENOMEM;
- }
-
- dev_info(&pdev->dev, "BAR0: %p, BAR1: %p\n", gsp->bar0, gsp->bar1);
-
- /* Load Firmware (for version verification only - GSP already booted by host) */
- ret = gsp_firmware_load(gsp);
- if (ret) {
- dev_err(&pdev->dev, "Firmware load failed: %d\n", ret);
- return ret;
- }
-
- /* Initialize RPC client (sets up rings, doorbells) */
- gsp->rpc = gsp_rpc_client_init(gsp);
- if (IS_ERR(gsp->rpc)) {
- ret = PTR_ERR(gsp->rpc);
- dev_err(&pdev->dev, "RPC client init failed: %d\n", ret);
- return ret;
- }
-
- /* Initialize RPC communication with GSP */
- ret = gsp_rpc_init(gsp);
- if (ret) {
- dev_err(&pdev->dev, "RPC init failed: %d\n", ret);
- return ret;
- }
-
- /* Setup IRQ */
- ret = gsp_setup_irq(gsp);
- if (ret) {
- dev_err(&pdev->dev, "IRQ setup failed: %d\n", ret);
- return ret;
- }
-
- /* Initialize char device */
- mutex_init(&gsp->chardev_lock);
- gsp->miscdev.minor = MISC_DYNAMIC_MINOR;
- gsp->miscdev.name = "gsp-vgpu";
- gsp->miscdev.fops = &gsp_fops;
- gsp->miscdev.parent = &pdev->dev;
- gsp->miscdev.mode = 0660;
-
- ret = misc_register(&gsp->miscdev);
- if (ret) {
- dev_err(&pdev->dev, "Failed to register misc device: %d\n", ret);
- return ret;
- }
-
- /* Debugfs */
- gsp_debugfs_init(gsp);
-
- dev_info(&pdev->dev, "GSP vGPU-IO driver loaded (FW: 570.144W)\n");
- return 0;
-}
-
-/* PCI Remove */
-void gsp_remove(struct pci_dev *pdev)
-{
- struct gsp_device *gsp = pci_get_drvdata(pdev);
- struct gsp_vf *vf, *tmp;
-
- if (!gsp)
- return;
-
- /* Destroy all VFs */
- list_for_each_entry_safe(vf, tmp, &gsp->vf_list, list)
- gsp_vf_destroy(vf);
-
- /* Unregister char device */
- misc_deregister(&gsp->miscdev);
-
- gsp_debugfs_fini(gsp);
- gsp_shutdown(gsp);
- gsp_rpc_client_fini(gsp->rpc);
-
- if (gsp->fw)
- release_firmware(gsp->fw);
-
- idr_destroy(&gsp->vf_idr);
-
- dev_info(&pdev->dev, "GSP vGPU-IO driver unloaded\n");
-}
-
-/* Firmware Load - only for version verification */
-int gsp_firmware_load(struct gsp_device *gsp)
-{
- const struct firmware *fw;
- int ret;
-
- ret = request_firmware(&fw, firmware_name, gsp->dev);
- if (ret) {
- dev_err(gsp->dev, "Failed to load firmware '%s': %d\n", firmware_name, ret);
- return ret;
- }
-
- /* Verify MD5: 13ce12a392a31eeb79a2e6ebd3a4a93a */
- if (fw->size != 0x1C50000) { /* ~28.5 MB */
- dev_warn(gsp->dev, "Firmware size unexpected: %zu (expected ~28.5MB)\n", fw->size);
- }
-
- dev_info(gsp->dev, "Firmware verified: %zu bytes\n", fw->size);
- gsp->fw = fw;
- return 0;
-}
-
-/* Initialize RPC communication with already-running GSP */
-int gsp_rpc_init(struct gsp_device *gsp)
-{
- /*
- * The GSP is already running (booted by host GRID driver).
- * We just need to verify communication works by reading mailbox registers
- * and optionally sending a test RPC.
- */
-
- /* Read mailbox registers to verify GSP is responsive */
- uint32_t mbox0 = readl(gsp->bar0 + GSP_BAR0_FALCON_MAILBOX0);
- uint32_t mbox1 = readl(gsp->bar0 + GSP_BAR0_FALCON_MAILBOX1);
-
- dev_info(gsp->dev, "GSP mailbox0: 0x%08x, mailbox1: 0x%08x\n", mbox0, mbox1);
-
- /* Check if GSP appears to be running (non-zero mailbox or queue heads) */
- uint32_t qhead0 = readl(gsp->bar0 + GSP_BAR0_QUEUE_HEAD(0));
- dev_info(gsp->dev, "GSP queue head 0: 0x%08x\n", qhead0);
-
- /* Ring doorbell to signal we're ready - write to queue head */
- writel(1, gsp->bar0 + GSP_BAR0_QUEUE_HEAD(0));
-
- gsp->fw_loaded = true; /* Indicates GSP communication established */
- dev_info(gsp->dev, "GSP RPC communication initialized\n");
-
- /* Auto-detect emulation mode if not overridden */
- if (!emulation_override) {
- gsp_detect_emulation_mode(gsp);
- } else if (emulation_mode) {
- dev_info(gsp->dev, "Emulation mode FORCED ON by module parameter\n");
- } else {
- dev_info(gsp->dev, "Emulation mode FORCED OFF by module parameter\n");
- }
-
- return 0;
-}
-
-/* Auto-detect if GSP has vGPU RPC handlers */
-static void gsp_detect_emulation_mode(struct gsp_device *gsp)
-{
- struct gsp_bar_trap_payload test_payload = {0};
- struct gsp_bar_trap_response test_resp = {0};
- size_t resp_size = sizeof(test_resp);
- int ret;
-
- dev_info(gsp->dev, "Auto-detecting GSP vGPU RPC handler support...\n");
-
- /* Send a test BAR_TRAP RPC to check if GSP has vGPU handlers */
- test_payload.bar_index = 1;
- test_payload.trap_type = GSP_BAR_READ; /* Non-destructive read */
- test_payload.offset = 0;
- test_payload.value = 0;
- test_payload.size = 8;
- test_payload.vf_id = 0;
-
- /* Try synchronous RPC with short timeout (1 second) */
- ret = gsp_rpc_send_sync(gsp->rpc, GSP_RPC_BAR_TRAP,
- &test_payload, sizeof(test_payload),
- &test_resp, &resp_size);
-
- if (ret == -ETIMEDOUT || ret == -ENOTTY || ret == -EIO || ret == -ENODEV) {
- /* GSP doesn't have vGPU handlers - enable emulation */
- emulation_mode = true;
- dev_info(gsp->dev, "GSP lacks vGPU RPC handlers (ret=%d) - ENABLING emulation mode\n", ret);
- } else if (ret == 0) {
- /* GSP responded - has vGPU handlers */
- emulation_mode = false;
- dev_info(gsp->dev, "GSP has vGPU RPC handlers - DISABLING emulation mode\n");
- } else {
- /* Other error - default to emulation for safety */
- emulation_mode = true;
- dev_info(gsp->dev, "GSP RPC test returned %d - ENABLING emulation mode (safe default)\n", ret);
- }
-}
-
-/* GSP Shutdown - just clean up our side */
-void gsp_shutdown(struct gsp_device *gsp)
-{
- if (gsp->fw_loaded) {
- /* Don't reset GSP - host driver owns it */
- gsp->fw_loaded = false;
- }
-}
-
-/* IRQ Setup */
-int gsp_setup_irq(struct gsp_device *gsp)
-{
- int ret;
- struct msix_entry entries[1];
-
- /* Try MSI-X first */
- ret = pci_enable_msix_range(gsp->pdev, entries, 1, 1);
- if (ret > 0) {
- gsp->msix_enabled = true;
- gsp->irq = entries[0].vector;
- gsp->msix_entries[0] = entries[0];
- } else {
- gsp->irq = gsp->pdev->irq;
- }
-
- ret = devm_request_irq(gsp->dev, gsp->irq, gsp_isr,
- gsp->msix_enabled ? 0 : IRQF_SHARED,
- DRIVER_NAME, gsp);
- if (ret) {
- dev_err(gsp->dev, "Failed to request IRQ %d: %d\n", gsp->irq, ret);
- return ret;
- }
-
- dev_info(gsp->dev, "IRQ %d registered (MSI-X: %s)\n",
- gsp->irq, gsp->msix_enabled ? "yes" : "no");
- return 0;
-}
-
-/* PCI Driver Structure */
-static struct pci_driver gsp_pci_driver = {
- .name = DRIVER_NAME,
- .id_table = gsp_pci_ids,
- .probe = gsp_probe,
- .remove = gsp_remove,
-};
-
-/* Module Init/Exit */
-static int __init gsp_module_init(void)
-{
- return pci_register_driver(&gsp_pci_driver);
-}
-
-static void __exit gsp_module_exit(void)
-{
- pci_unregister_driver(&gsp_pci_driver);
-}
-
-module_init(gsp_module_init);
-module_exit(gsp_module_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("NVIDIA vGPU-IO Team");
-MODULE_DESCRIPTION("NVIDIA GSP 570.144W vGPU-IO Driver");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_FIRMWARE("gsp-570.144.fwimage.bin");
diff --git a/legacy-driver-guest/debugfs/gsp_debugfs.c b/legacy-driver-guest/debugfs/gsp_debugfs.c
deleted file mode 100644
index f3df124..0000000
--- a/legacy-driver-guest/debugfs/gsp_debugfs.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * GSP vGPU-IO Driver - Debugfs Interface
- */
-
-#include "gsp_core.h"
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static int gsp_debugfs_vfs_show(struct seq_file *s, void *unused)
-{
- struct gsp_device *gsp = s->private;
- struct gsp_vf *vf;
-
- seq_printf(s, "%-4s %-12s %-10s %-18s %-18s\n",
- "ID", "STATE", "REFCNT", "BAR1", "PAGE_TABLE");
-
- mutex_lock(&gsp->vf_lock);
- list_for_each_entry(vf, &gsp->vf_list, list) {
- seq_printf(s, "%-4u %-12d %-10d 0x%016llx-0x%016llx 0x%016llx-0x%016llx\n",
- vf->id, vf->state, atomic_read(&vf->refcount),
- vf->bar1_offset, vf->bar1_offset + vf->bar1_size,
- vf->pt_base, vf->pt_base + vf->pt_size);
- }
- mutex_unlock(&gsp->vf_lock);
-
- return 0;
-}
-
-static int gsp_debugfs_vfs_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gsp_debugfs_vfs_show, inode->i_private);
-}
-
-static const struct file_operations gsp_debugfs_vfs_fops = {
- .open = gsp_debugfs_vfs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int gsp_debugfs_vf_show(struct seq_file *s, void *unused)
-{
- struct gsp_vf *vf = s->private;
- struct gsp_wpr_region *rgn;
-
- seq_printf(s, "VF %u\n", vf->id);
- seq_printf(s, " State: %d\n", vf->state);
- seq_printf(s, " Refcount: %d\n", atomic_read(&vf->refcount));
- seq_printf(s, " BAR1: 0x%llx - 0x%llx (size: 0x%llx)\n",
- vf->bar1_offset, vf->bar1_offset + vf->bar1_size, vf->bar1_size);
- seq_printf(s, " Page Table: 0x%llx - 0x%llx (size: 0x%llx)\n",
- vf->pt_base, vf->pt_base + vf->pt_size, vf->pt_size);
- seq_printf(s, " Cmd Buffer: 0x%llx - 0x%llx (size: 0x%llx)\n",
- vf->cmd_base, vf->cmd_base + vf->cmd_size, vf->cmd_size);
- seq_printf(s, " BAR State:\n");
- seq_printf(s, " Aperture: 0x%llx - 0x%llx\n",
- vf->bar_state.aperture_offset,
- vf->bar_state.aperture_offset + vf->bar_state.aperture_size);
- seq_printf(s, " ForceAcc: %s (VF: %u)\n",
- vf->bar_state.force_access ? "enabled" : "disabled",
- vf->bar_state.force_vf);
- seq_printf(s, " WPR Regions:\n");
-
- mutex_lock(&vf->wpr_lock);
- list_for_each_entry(rgn, &vf->wpr_list, list) {
- seq_printf(s, " [0x%llx, 0x%llx) flags=0x%x\n",
- rgn->base, rgn->base + rgn->size, rgn->flags);
- }
- mutex_unlock(&vf->wpr_lock);
-
- if (vf->migration) {
- seq_printf(s, " Migration:\n");
- seq_printf(s, " State: %d\n", vf->migration->state);
- seq_printf(s, " Dst VF: %llu\n", vf->migration->dst_vf);
- seq_printf(s, " Token: 0x%llx\n", vf->migration->token);
- seq_printf(s, " Progress: %llu pages, %llu bytes\n",
- vf->migration->progress.pages_transferred,
- vf->migration->progress.bytes_transferred);
- }
-
- return 0;
-}
-
-static int gsp_debugfs_vf_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gsp_debugfs_vf_show, inode->i_private);
-}
-
-static const struct file_operations gsp_debugfs_vf_fops = {
- .open = gsp_debugfs_vf_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int gsp_debugfs_rpc_show(struct seq_file *s, void *unused)
-{
- struct gsp_device *gsp = s->private;
-
- seq_printf(s, "RPC Statistics:\n");
- seq_printf(s, " Total: %lld\n", atomic64_read(&gsp->rpc_total));
- seq_printf(s, " Errors: %lld\n", atomic64_read(&gsp->rpc_errors));
- seq_printf(s, " BAR Traps: %lld\n", atomic64_read(&gsp->bar_traps));
- seq_printf(s, " WPR Events: %lld\n", atomic64_read(&gsp->wpr_events));
- seq_printf(s, " Migrations: %lld\n", atomic64_read(&gsp->migrations));
-
- return 0;
-}
-
-static int gsp_debugfs_rpc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gsp_debugfs_rpc_show, inode->i_private);
-}
-
-static const struct file_operations gsp_debugfs_rpc_fops = {
- .open = gsp_debugfs_rpc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int gsp_debugfs_bar_show(struct seq_file *s, void *unused)
-{
- struct gsp_vf *vf = s->private;
-
- seq_printf(s, "VF %u BAR State:\n", vf->id);
- seq_printf(s, " Aperture Offset: 0x%llx\n", vf->bar_state.aperture_offset);
- seq_printf(s, " Aperture Size: 0x%llx\n", vf->bar_state.aperture_size);
- seq_printf(s, " Force Access: %s\n", vf->bar_state.force_access ? "enabled" : "disabled");
- seq_printf(s, " Force VF: %u\n", vf->bar_state.force_vf);
- seq_printf(s, " Backing Store: %p\n", vf->bar_state.backing_store);
- seq_printf(s, " Backing Size: 0x%zx\n", vf->bar_state.backing_size);
-
- return 0;
-}
-
-static int gsp_debugfs_bar_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gsp_debugfs_bar_show, inode->i_private);
-}
-
-static const struct file_operations gsp_debugfs_bar_fops = {
- .open = gsp_debugfs_bar_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int gsp_debugfs_wpr_show(struct seq_file *s, void *unused)
-{
- struct gsp_vf *vf = s->private;
- struct gsp_wpr_region *rgn;
-
- seq_printf(s, "VF %u WPR Regions:\n", vf->id);
-
- mutex_lock(&vf->wpr_lock);
- list_for_each_entry(rgn, &vf->wpr_list, list) {
- seq_printf(s, " [0x%llx, 0x%llx) size=0x%llx flags=0x%x\n",
- rgn->base, rgn->base + rgn->size, rgn->size, rgn->flags);
- }
- mutex_unlock(&vf->wpr_lock);
-
- return 0;
-}
-
-static int gsp_debugfs_wpr_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gsp_debugfs_wpr_show, inode->i_private);
-}
-
-static const struct file_operations gsp_debugfs_wpr_fops = {
- .open = gsp_debugfs_wpr_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int gsp_debugfs_migration_show(struct seq_file *s, void *unused)
-{
- struct gsp_vf *vf = s->private;
-
- if (!vf->migration) {
- seq_printf(s, "No active migration\n");
- return 0;
- }
-
- seq_printf(s, "VF %u Migration:\n", vf->id);
- seq_printf(s, " State: %d\n", vf->migration->state);
- seq_printf(s, " Destination VF: %llu\n", vf->migration->dst_vf);
- seq_printf(s, " Token: 0x%llx\n", vf->migration->token);
- seq_printf(s, " Flags: 0x%x\n", vf->migration->flags);
- seq_printf(s, " Pages Xfer: %llu\n", vf->migration->progress.pages_transferred);
- seq_printf(s, " Bytes Xfer: %llu\n", vf->migration->progress.bytes_transferred);
- seq_printf(s, " Dirty Pages: %llu\n", vf->migration->progress.dirty_pages);
- seq_printf(s, " Cancelled: %s\n", vf->migration->cancelled ? "yes" : "no");
-
- return 0;
-}
-
-static int gsp_debugfs_migration_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gsp_debugfs_migration_show, inode->i_private);
-}
-
-static const struct file_operations gsp_debugfs_migration_fops = {
- .open = gsp_debugfs_migration_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-/* VF Debugfs Directory Creation */
-static void gsp_debugfs_vf_create(struct gsp_vf *vf)
-{
- char name[16];
- struct dentry *vf_dir;
-
- snprintf(name, sizeof(name), "vf%u", vf->id);
- vf_dir = debugfs_create_dir(name, vf->gsp->debugfs_vfs_dir);
- if (!vf_dir)
- return;
-
- debugfs_create_file("status", 0444, vf_dir, vf, &gsp_debugfs_vf_fops);
- debugfs_create_file("bar", 0444, vf_dir, vf, &gsp_debugfs_bar_fops);
- debugfs_create_file("wpr", 0444, vf_dir, vf, &gsp_debugfs_wpr_fops);
- debugfs_create_file("migration", 0444, vf_dir, vf, &gsp_debugfs_migration_fops);
-}
-
-/* Main Debugfs Init */
-int gsp_debugfs_init(struct gsp_device *gsp)
-{
- gsp->debugfs_root = debugfs_create_dir("gsp-vgpu", NULL);
- if (!gsp->debugfs_root)
- return -ENOMEM;
-
- debugfs_create_file("vfs", 0444, gsp->debugfs_root, gsp, &gsp_debugfs_vfs_fops);
- debugfs_create_file("rpc", 0444, gsp->debugfs_root, gsp, &gsp_debugfs_rpc_fops);
-
- gsp->debugfs_vfs_dir = debugfs_create_dir("vfs", gsp->debugfs_root);
- if (!gsp->debugfs_vfs_dir) {
- debugfs_remove_recursive(gsp->debugfs_root);
- return -ENOMEM;
- }
-
- /* Create entries for existing VFs */
- mutex_lock(&gsp->vf_lock);
- struct gsp_vf *vf;
- list_for_each_entry(vf, &gsp->vf_list, list)
- gsp_debugfs_vf_create(vf);
- mutex_unlock(&gsp->vf_lock);
-
- return 0;
-}
-
-void gsp_debugfs_fini(struct gsp_device *gsp)
-{
- if (gsp->debugfs_root)
- debugfs_remove_recursive(gsp->debugfs_root);
-}
-
-/* Export for VF creation/destruction */
-void gsp_debugfs_vf_add(struct gsp_vf *vf)
-{
- gsp_debugfs_vf_create(vf);
-}
-
-void gsp_debugfs_vf_remove(struct gsp_vf *vf)
-{
- char name[16];
- snprintf(name, sizeof(name), "vf%u", vf->id);
- debugfs_remove_recursive(debugfs_lookup(name, vf->gsp->debugfs_vfs_dir));
-} \ No newline at end of file
diff --git a/legacy-driver-guest/include/gsp_core.h b/legacy-driver-guest/include/gsp_core.h
deleted file mode 100644
index 569d6f8..0000000
--- a/legacy-driver-guest/include/gsp_core.h
+++ /dev/null
@@ -1,613 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * GSP vGPU-IO Driver - Core Definitions
- * NVIDIA GSP 570.144W (TU102/TU104) Firmware Interface
- */
-
-#ifndef _GSP_CORE_H_
-#define _GSP_CORE_H_
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/mutex.h>
-#include <linux/idr.h>
-#include <linux/list.h>
-#include <linux/kref.h>
-#include <linux/completion.h>
-#include <linux/wait.h>
-#include <linux/spinlock.h>
-#include <linux/miscdevice.h>
-
-/* Firmware Constants */
-#define GSP_FW_BASE_ADDR 0x04000000ULL
-#define GSP_FW_SIZE 0x02000000ULL
-#define GSP_ENTRY_POINT 0x04009000ULL
-#define GSP_PRIMARY_DISPATCHER 0x057A1AC0ULL
-#define GSP_SECONDARY_DISPATCHER 0x04ED39DCULL
-#define GSP_RPC_JUMP_TABLE 0x059BFEB0ULL
-
-/* PCIe BAR Offsets */
-#define GSP_BAR0_FALCON_ENGINE 0x1103c0
-#define GSP_BAR0_FALCON_MAILBOX0 0x110040
-#define GSP_BAR0_FALCON_MAILBOX1 0x110044
-#define GSP_BAR0_MAILBOX(i) (0x110804 + (i) * 4)
-#define GSP_BAR0_QUEUE_HEAD(i) (0x110c00 + (i) * 8)
-
-/* IOCTL definitions (must match userspace libvgpu.h) */
-#define GSP_IOCTL_MAGIC 'G'
-#define GSP_IOCTL_CREATE_VF _IOW(GSP_IOCTL_MAGIC, 0x01, struct gsp_vf_config)
-#define GSP_IOCTL_DESTROY_VF _IOW(GSP_IOCTL_MAGIC, 0x02, uint32_t)
-#define GSP_IOCTL_ALLOC _IOWR(GSP_IOCTL_MAGIC, 0x10, struct gsp_alloc_args)
-#define GSP_IOCTL_FREE _IOW(GSP_IOCTL_MAGIC, 0x11, struct gsp_free_args)
-#define GSP_IOCTL_MAP _IOWR(GSP_IOCTL_MAGIC, 0x12, struct gsp_map_args)
-#define GSP_IOCTL_UNMAP _IOW(GSP_IOCTL_MAGIC, 0x13, struct gsp_unmap_args)
-#define GSP_IOCTL_PIN _IOWR(GSP_IOCTL_MAGIC, 0x14, struct gsp_pin_args)
-#define GSP_IOCTL_UNPIN _IOW(GSP_IOCTL_MAGIC, 0x15, struct gsp_unpin_args)
-#define GSP_IOCTL_BAR_CONFIG _IOWR(GSP_IOCTL_MAGIC, 0x16, struct gsp_bar_config_args)
-#define GSP_IOCTL_BAR_FORCE _IOW(GSP_IOCTL_MAGIC, 0x17, struct gsp_bar_force_args)
-#define GSP_IOCTL_BAR_SAVE _IOWR(GSP_IOCTL_MAGIC, 0x18, struct gsp_bar_save_args)
-#define GSP_IOCTL_BAR_RESTORE _IOWR(GSP_IOCTL_MAGIC, 0x19, struct gsp_bar_restore_args)
-#define GSP_IOCTL_WPR_PROTECT _IOWR(GSP_IOCTL_MAGIC, 0x1A, struct gsp_wpr_args)
-#define GSP_IOCTL_WPR_UNPROTECT _IOW(GSP_IOCTL_MAGIC, 0x1B, struct gsp_wpr_args)
-#define GSP_IOCTL_WPR_TIMEOUT _IOW(GSP_IOCTL_MAGIC, 0x1C, struct gsp_wpr_timeout_args)
-#define GSP_IOCTL_SCHEDULE _IOW(GSP_IOCTL_MAGIC, 0x1D, struct gsp_schedule_args)
-#define GSP_IOCTL_YIELD _IOW(GSP_IOCTL_MAGIC, 0x1E, uint32_t)
-#define GSP_IOCTL_MIGRATE _IOWR(GSP_IOCTL_MAGIC, 0x1F, struct gsp_migrate_args)
-#define GSP_IOCTL_GET_INFO _IOR(GSP_IOCTL_MAGIC, 0x20, char[256])
-
-/* Kernel argument structures (matching userspace) */
-struct gsp_vf_config {
- uint32_t id;
- uint64_t bar1_offset;
- uint64_t bar1_size;
- uint64_t pt_base;
- uint64_t pt_size;
- uint64_t cmd_base;
- uint64_t cmd_size;
- uint32_t max_memory_mb;
- uint32_t num_engines;
-};
-
-struct gsp_alloc_args {
- uint32_t vf_id;
- uint64_t size;
- uint32_t type;
- uint64_t alignment;
- uint64_t va_hint;
- uint32_t flags;
- uint32_t pid;
- uint64_t handle;
- uint64_t va;
- uint64_t actual_size;
-};
-
-struct gsp_free_args {
- uint32_t vf_id;
- uint64_t handle;
-};
-
-struct gsp_map_args {
- uint32_t vf_id;
- uint64_t handle;
- uint64_t gpu_va;
- uint64_t size;
- uint32_t prot;
- uint32_t flags;
- uint64_t offset;
- uint64_t mapped_va;
-};
-
-struct gsp_unmap_args {
- uint32_t vf_id;
- uint64_t handle;
- uint64_t gpu_va;
- uint64_t size;
-};
-
-struct gsp_pin_args {
- uint32_t vf_id;
- uint64_t handle;
- uint64_t offset;
- uint64_t size;
- uint32_t flags;
- uint64_t dma_addr;
- uint32_t num_pages;
-};
-
-struct gsp_unpin_args {
- uint32_t vf_id;
- uint64_t handle;
- uint64_t offset;
- uint64_t size;
-};
-
-struct gsp_bar_config_args {
- uint32_t vf_id;
- uint64_t aperture_offset;
- uint64_t aperture_size;
-};
-
-struct gsp_bar_force_args {
- uint32_t vf_id;
- uint32_t enable;
-};
-
-struct gsp_bar_save_args {
- uint32_t vf_id;
- void *buf;
- size_t *size;
-};
-
-struct gsp_bar_restore_args {
- uint32_t vf_id;
- void *buf;
- size_t size;
-};
-
-struct gsp_wpr_args {
- uint32_t vf_id;
- uint64_t base;
- uint64_t size;
- uint32_t flags;
-};
-
-struct gsp_wpr_timeout_args {
- uint32_t vf_id;
- uint64_t timeout_ns;
-};
-
-struct gsp_schedule_args {
- uint32_t vf_id;
- uint32_t priority;
- uint64_t time_slice_ns;
-};
-
-struct gsp_migrate_args {
- uint32_t vf_id;
- uint64_t dst_vf;
- uint32_t phase;
- uint32_t flags;
- uint64_t token;
-};
-
-/* Message Ring */
-#define GSP_MSG_RING_SIZE 256
-#define GSP_MSG_MAX_SIZE 256
-#define GSP_MAX_PENDING 64
-
-/* RPC Types */
-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 = 0x0C,
-};
-
-/* RPC Message Flags */
-#define GSP_MSG_SYNC (1 << 0)
-#define GSP_MSG_ASYNC (1 << 1)
-#define GSP_MSG_NOREPLY (1 << 2)
-
-/* Memory Types */
-enum gsp_mem_type {
- GSP_MEM_VRAM = 0,
- GSP_MEM_SYSMEM = 1,
- GSP_MEM_UNCACHED = 2,
-};
-
-/* Pin Flags */
-#define GSP_PIN_READ (1 << 0)
-#define GSP_PIN_WRITE (1 << 1)
-#define GSP_PIN_LONGTERM (1 << 2)
-
-/* BAR Trap Types */
-#define GSP_BAR_READ 0
-#define GSP_BAR_WRITE 1
-#define GSP_BAR_ATOMIC 2
-
-/* Migration Phases */
-enum gsp_migrate_phase {
- GSP_MIG_QUERY = 0,
- GSP_MIG_PREPARE = 1,
- GSP_MIG_TRANSFER = 2,
- GSP_MIG_COMMIT = 3,
- GSP_MIG_CLEANUP = 4,
-};
-
-/* Migration Flags */
-#define GSP_MIG_LIVE (1 << 0)
-#define GSP_MIG_POSTCOPY (1 << 1)
-#define GSP_MIG_AUTO_COMMIT (1 << 2)
-#define GSP_MIG_VERIFY (1 << 3)
-
-/* Error Codes (from firmware) */
-#define GSP_OK 0
-#define GSP_EPERM 0xFFFFFFFF
-#define GSP_ENOENT 0xFFFFFFFE
-#define GSP_EINVAL 0xFFFFFFFD
-#define GSP_ENODEV 0xFFFFFFFA
-#define GSP_ENOMEM 0xFFFFFFF4
-#define GSP_EBUSY 0xFFFFFFEE
-#define GSP_ENOSPC 0xFFFFFFE4
-#define GSP_ETIMEDOUT 0x0000001E
-#define GSP_EOVERFLOW 0x00000025
-#define GSP_EDEV 0x0000001F
-
-/* Forward Declarations */
-struct gsp_device;
-struct gsp_vf;
-struct gsp_rpc_client;
-struct gsp_migration;
-struct gsp_wpr_region;
-
-/* WPR Region */
-struct gsp_wpr_region {
- struct list_head list;
- uint64_t base;
- uint64_t size;
- uint32_t flags;
- uint32_t vf_id;
- void (*completion_cb)(struct gsp_vf *, uint64_t, uint32_t);
- void (*timeout_cb)(struct gsp_vf *, uint64_t, uint32_t);
- uint64_t timeout_ns;
-};
-
-/* WPR Flags */
-#define GSP_WPR_WRITE (1 << 0)
-#define GSP_WPR_READ (1 << 1)
-#define GSP_WPR_EXECUTE (1 << 2)
-
-/* WPR Event Types */
-enum gsp_wpr_event {
- GSP_WPR_WRITE_COMPLETE = 0,
- GSP_WPR_READ_COMPLETE = 1,
- GSP_WPR_WRITE_TIMEOUT = 2,
- GSP_WPR_READ_TIMEOUT = 3,
-};
-
-/* Migration State */
-enum gsp_mig_state {
- GSP_MIG_S_IDLE = 0,
- GSP_MIG_S_QUERY = 1,
- GSP_MIG_S_PREPARE = 2,
- GSP_MIG_S_TRANSFER = 3,
- GSP_MIG_S_COMMIT = 4,
- GSP_MIG_S_CLEANUP = 5,
- GSP_MIG_S_FAILED = 6,
- GSP_MIG_S_COMPLETED = 7,
-};
-
-/* Migration Context */
-struct gsp_migration {
- struct gsp_vf *vf;
- struct mutex lock;
- enum gsp_mig_state state;
- uint64_t token;
- uint64_t dst_vf;
- uint32_t flags;
-
- struct {
- uint64_t pages_transferred;
- uint64_t bytes_transferred;
- uint64_t dirty_pages;
- uint64_t *page_list;
- uint32_t page_count;
- } progress;
-
- struct {
- void *buf;
- size_t size;
- } bar_state;
-
- struct task_struct *thread;
- struct completion comp;
- bool cancelled;
- int error;
-};
-
-/* Emulation mode: skip GSP RPC for BAR/WPR when GSP lacks vGPU handlers */
-extern bool emulation_mode;
-
-/* RPC Message Header (64 bytes) */
-struct gsp_rpc_header {
- uint32_t magic; /* 0x47535052 "GSPR" */
- uint32_t version; /* Protocol version */
- uint32_t rpc_type; /* enum gsp_rpc_type */
- uint32_t sequence; /* Monotonic sequence */
- uint64_t timestamp_ns; /* Submission timestamp */
- uint32_t payload_size; /* Payload size in bytes */
- uint32_t flags; /* GSP_MSG_* */
- uint64_t correlation_id; /* Async matching */
- uint64_t reserved[3]; /* Padding to 64 bytes */
-} __attribute__((packed));
-
-/* Complete RPC Message */
-struct gsp_rpc_message {
- struct gsp_rpc_header hdr;
- uint8_t payload[GSP_MSG_MAX_SIZE - sizeof(struct gsp_rpc_header)];
-} __attribute__((packed));
-
-/* RPC Response Header */
-struct gsp_rpc_response {
- int64_t status; /* 0 = success, negative = error */
- uint32_t rpc_type; /* Echo of request */
- uint32_t sequence; /* Echo of request */
- uint64_t timestamp_ns; /* Completion timestamp */
- uint32_t payload_size; /* Response payload size */
- uint32_t reserved;
- uint8_t payload[];
-} __attribute__((packed));
-
-/* Primary Dispatcher Sub-Command Descriptor */
-struct gsp_subcmd_desc {
- uint32_t subcmd_id; /* Constant ID (e.g., 0x10, 0x14, 0x40) */
- uint8_t echo_flags_b; /* Copy of input flags_b */
- uint8_t echo_flags_a; /* Copy of input flags_a */
- uint8_t echo_flags_c; /* Copy of input flags_c */
- uint8_t reserved;
-} __attribute__((packed));
-
-/* ALLOC Payload */
-struct gsp_alloc_payload {
- uint64_t size;
- uint32_t type; /* enum gsp_mem_type */
- uint32_t alignment;
- uint64_t va_hint;
- uint32_t flags;
- uint32_t pid;
- uint32_t vf_id;
- uint32_t reserved;
-} __attribute__((packed));
-
-struct gsp_alloc_response {
- uint64_t handle;
- uint64_t va;
- uint64_t pa;
-} __attribute__((packed));
-
-/* PIN Payload */
-struct gsp_pin_payload {
- uint64_t handle;
- uint64_t offset;
- uint64_t size;
- uint32_t vf_id;
- uint32_t flags; /* GSP_PIN_* */
- uint32_t reserved[2];
-} __attribute__((packed));
-
-struct gsp_pin_response {
- uint64_t dma_addr;
-} __attribute__((packed));
-
-/* BAR Trap Payload */
-struct gsp_bar_trap_payload {
- uint32_t bar_index;
- uint32_t trap_type; /* GSP_BAR_* */
- uint64_t offset;
- uint64_t value;
- uint32_t size;
- uint32_t vf_id;
- uint32_t reserved;
-} __attribute__((packed));
-
-struct gsp_bar_trap_response {
- uint64_t value;
-} __attribute__((packed));
-
-/* Migration Payload */
-struct gsp_migrate_payload {
- uint32_t phase; /* enum gsp_migrate_phase */
- uint32_t subcmd; /* Sub-command index */
- uint64_t src_vf;
- uint64_t dst_vf;
- uint64_t data_ptr;
- uint64_t data_size;
- uint32_t flags; /* GSP_MIG_* */
- uint32_t reserved;
- uint64_t token;
-} __attribute__((packed));
-
-/* Message Ring Buffer */
-struct gsp_msg_ring {
- void *base;
- size_t size;
- uint32_t head;
- uint32_t tail;
- spinlock_t lock;
-};
-
-/* RPC Client */
-struct gsp_rpc_client {
- struct gsp_device *gsp;
- struct mutex lock;
- atomic_t seq;
- wait_queue_head_t wq;
- struct gsp_msg_ring *tx_ring;
- struct gsp_msg_ring *rx_ring;
- dma_addr_t tx_ring_dma;
- dma_addr_t rx_ring_dma;
- struct completion *pending[GSP_MAX_PENDING];
- struct gsp_rpc_response *resp_buf[GSP_MAX_PENDING];
-};
-
-/* BAR State per VF */
-struct gsp_bar_state {
- uint64_t aperture_offset;
- uint64_t aperture_size;
- bool force_access;
- uint32_t force_vf;
- void *backing_store;
- size_t backing_size;
-};
-
-/* VF State */
-enum gsp_vf_state {
- GSP_VF_CREATING = 0,
- GSP_VF_ACTIVE,
- GSP_VF_MIGRATING,
- GSP_VF_SUSPENDED,
- GSP_VF_DESTROYING,
-};
-
-/* GSP Virtual Function */
-struct gsp_vf {
- struct gsp_device *gsp;
- uint32_t id;
- struct kref ref;
- struct mutex lock;
- enum gsp_vf_state state;
- struct gsp_migration *migration;
-
- /* Resource configuration */
- uint64_t bar1_offset;
- uint64_t bar1_size;
- uint64_t pt_base;
- uint64_t pt_size;
- uint64_t cmd_base;
- uint64_t cmd_size;
-
- /* WPR regions */
- struct list_head wpr_list;
- struct mutex wpr_lock;
-
- /* BAR state */
- struct gsp_bar_state bar_state;
-
- atomic_t refcount;
- bool active;
- struct list_head list;
-};
-
-/* GSP Device */
-struct gsp_device {
- struct pci_dev *pdev;
- struct device *dev;
- void __iomem *bar0;
- void __iomem *bar1;
-
- /* Firmware */
- const struct firmware *fw;
- bool fw_loaded;
-
- /* RPC */
- struct gsp_rpc_client *rpc;
-
- /* VF Management */
- struct mutex vf_lock;
- struct idr vf_idr;
- struct list_head vf_list;
- uint32_t max_vfs;
-
- /* IRQ */
- int irq;
- bool msix_enabled;
- struct msix_entry msix_entries[1];
-
- /* Debug */
- struct dentry *debugfs_root;
- struct dentry *debugfs_vfs_dir;
-
- /* Char device */
- struct miscdevice miscdev;
- struct mutex chardev_lock;
-
- /* Statistics */
- atomic64_t rpc_total;
- atomic64_t rpc_errors;
- atomic64_t bar_traps;
- atomic64_t wpr_events;
- atomic64_t migrations;
-};
-
-/* Function Prototypes */
-
-/* Core */
-int gsp_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-void gsp_remove(struct pci_dev *pdev);
-int gsp_firmware_load(struct gsp_device *gsp);
-int gsp_rpc_init(struct gsp_device *gsp);
-void gsp_shutdown(struct gsp_device *gsp);
-
-/* RPC Client */
-struct gsp_rpc_client *gsp_rpc_client_init(struct gsp_device *gsp);
-void gsp_rpc_client_fini(struct gsp_rpc_client *rpc);
-int gsp_rpc_send_sync(struct gsp_rpc_client *rpc,
- enum gsp_rpc_type type,
- void *payload, size_t payload_size,
- void *response, size_t *response_size);
-int gsp_rpc_send_async(struct gsp_rpc_client *rpc,
- enum gsp_rpc_type type,
- void *payload, size_t payload_size,
- void (*callback)(struct gsp_rpc_client *,
- struct gsp_rpc_response *,
- void *),
- void *ctx);
-irqreturn_t gsp_isr(int irq, void *data);
-void gsp_handle_notification(struct gsp_device *gsp, struct gsp_rpc_message *msg);
-int gsp_errno_to_errno(int gsp_err);
-
-/* VF Management */
-int gsp_vf_create(struct gsp_device *gsp, const struct gsp_vf_config *config);
-void gsp_vf_destroy(struct gsp_vf *vf);
-struct gsp_vf *gsp_vf_get(struct gsp_device *gsp, uint32_t id);
-void gsp_vf_put(struct gsp_vf *vf);
-
-/* Memory Management */
-int gsp_vf_mem_alloc(struct gsp_vf *vf, uint64_t size, uint32_t flags,
- uint64_t *handle, uint64_t *va);
-int gsp_vf_mem_free(struct gsp_vf *vf, uint64_t handle);
-int gsp_vf_mem_pin(struct gsp_vf *vf, uint64_t handle,
- uint64_t offset, uint64_t size,
- uint64_t *dma_addr);
-int gsp_vf_mem_unpin(struct gsp_vf *vf, uint64_t handle);
-int gsp_vf_mem_map(struct gsp_vf *vf, uint64_t handle, uint64_t gpu_va,
- uint64_t size, uint32_t prot, uint32_t flags,
- uint64_t offset, uint64_t *mapped_va);
-int gsp_vf_mem_unmap(struct gsp_vf *vf, uint64_t handle, uint64_t gpu_va, uint64_t size);
-
-/* BAR Emulation */
-int gsp_vf_bar_init(struct gsp_vf *vf);
-void gsp_vf_bar_fini(struct gsp_vf *vf);
-int gsp_vf_bar_trap(struct gsp_vf *vf, struct gsp_bar_trap_payload *trap);
-int gsp_bar_force_access(struct gsp_vf *vf, bool enable);
-int gsp_migration_bar_save(struct gsp_vf *vf, void *buf, size_t *size);
-int gsp_migration_bar_restore(struct gsp_vf *vf, void *buf, size_t size);
-
-/* WPR Management */
-int gsp_vf_wpr_init(struct gsp_vf *vf);
-void gsp_vf_wpr_fini(struct gsp_vf *vf);
-int gsp_vf_wpr_protect(struct gsp_vf *vf, uint64_t base, uint64_t size,
- uint32_t flags);
-int gsp_vf_wpr_unprotect(struct gsp_vf *vf, uint64_t base);
-int gsp_vf_wpr_protect_write(struct gsp_vf *vf, uint64_t base, uint64_t size);
-int gsp_vf_wpr_protect_read(struct gsp_vf *vf, uint64_t base, uint64_t size);
-int gsp_vf_wpr_set_timeout(struct gsp_vf *vf, uint64_t timeout_ns);
-int gsp_vf_wpr_register_callback(struct gsp_vf *vf, enum gsp_wpr_event type,
- void (*cb)(struct gsp_vf *, uint64_t, uint32_t),
- void *ctx);
-void gsp_wpr_handle_event(struct gsp_device *gsp, struct gsp_rpc_message *msg);
-
-/* Scheduling */
-int gsp_vf_schedule(struct gsp_vf *vf, uint32_t priority, uint64_t time_slice_ns);
-int gsp_vf_yield(struct gsp_vf *vf);
-
-/* Migration */
-int gsp_migration_start(struct gsp_vf *vf, uint64_t dst_vf);
-void gsp_migration_cancel(struct gsp_migration *mig);
-int gsp_migration_status(struct gsp_migration *mig);
-
-/* Debugfs */
-int gsp_debugfs_init(struct gsp_device *gsp);
-void gsp_debugfs_fini(struct gsp_device *gsp);
-void gsp_debugfs_vf_add(struct gsp_vf *vf);
-void gsp_debugfs_vf_remove(struct gsp_vf *vf);
-
-#endif /* _GSP_CORE_H_ */ \ No newline at end of file
diff --git a/legacy-driver-guest/kernel-tests/gsp_vgpu_comprehensive_test.c b/legacy-driver-guest/kernel-tests/gsp_vgpu_comprehensive_test.c
deleted file mode 100644
index 7918beb..0000000
--- a/legacy-driver-guest/kernel-tests/gsp_vgpu_comprehensive_test.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * GSP vGPU-IO Driver - Comprehensive Test Suite
- * Tests all driver components: RPC, VF, BAR, WPR, Migration
- * Compiles against kernel headers only (no driver dependency)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ktime.h>
-#include <linux/atomic.h>
-#include <linux/list.h>
-#include <linux/idr.h>
-#include <linux/mutex.h>
-#include <linux/kref.h>
-#include <linux/completion.h>
-#include <linux/wait.h>
-#include <linux/spinlock.h>
-#include <linux/debugfs.h>
-#include <linux/vmalloc.h>
-
-#include <gsp_core.h>
-
-static int test_count = 0;
-static int pass_count = 0;
-static int fail_count = 0;
-
-#define TEST_ASSERT(cond, msg) \
- do { \
- test_count++; \
- if (cond) { \
- pass_count++; \
- pr_info("PASS: %s\n", msg); \
- } else { \
- fail_count++; \
- pr_err("FAIL: %s\n", msg); \
- } \
- } while (0)
-
-#define TEST_ASSERT_EQ(a, b, msg) \
- TEST_ASSERT((a) == (b), msg " (expected " #b ", got " #a ")")
-
-#define TEST_ASSERT_NE(a, b, msg) \
- TEST_ASSERT((a) != (b), msg " (expected not " #b ", got " #a ")")
-
-/* ============================================================
- * Test: Kernel API Availability
- * ============================================================ */
-
-static int test_kernel_apis(void)
-{
- pr_info("=== Testing Kernel API Availability ===\n");
-
- /* Test kref */
- struct kref *ref = kmalloc(sizeof(*ref), GFP_KERNEL);
- TEST_ASSERT(ref != NULL, "kref allocation");
- kref_init(ref);
- TEST_ASSERT(kref_read(ref) == 1, "kref_init sets refcount to 1");
-
- kref_get(ref);
- TEST_ASSERT(kref_read(ref) == 2, "kref_get increments refcount");
-
- kref_put(ref, (void (*)(struct kref *))kfree);
- TEST_ASSERT(kref_read(ref) == 1, "kref_put decrements refcount");
-
- kref_put(ref, (void (*)(struct kref *))kfree);
- TEST_ASSERT(kref_read(ref) == 0, "kref_put reaches zero");
-
- /* Test completion */
- struct completion comp;
- init_completion(&comp);
- TEST_ASSERT(!completion_done(&comp), "completion initially not done");
- complete(&comp);
- TEST_ASSERT(completion_done(&comp), "completion marked done");
-
- init_completion(&comp);
- TEST_ASSERT(wait_for_completion_timeout(&comp, msecs_to_jiffies(100)) > 0,
- "wait_for_completion_timeout works");
-
- /* Test atomic64 */
- atomic64_t a64 = ATOMIC64_INIT(0);
- atomic64_inc(&a64);
- TEST_ASSERT_EQ(atomic64_read(&a64), 1, "atomic64_inc");
- atomic64_add(5, &a64);
- TEST_ASSERT_EQ(atomic64_read(&a64), 6, "atomic64_add");
- atomic64_sub(3, &a64);
- TEST_ASSERT_EQ(atomic64_read(&a64), 3, "atomic64_sub");
-
- /* Test mutex */
- struct mutex mtx;
- mutex_init(&mtx);
- mutex_lock(&mtx);
- TEST_ASSERT(mutex_is_locked(&mtx), "mutex_is_locked after lock");
- mutex_unlock(&mtx);
- TEST_ASSERT(!mutex_is_locked(&mtx), "mutex_is_locked after unlock");
-
- /* Test spinlock */
- spinlock_t sl = __SPIN_LOCK_UNLOCKED(sl);
- unsigned long flags;
- spin_lock_irqsave(&sl, flags);
- TEST_ASSERT(spin_is_locked(&sl), "spin_is_locked after lock");
- spin_unlock_irqrestore(&sl, flags);
- TEST_ASSERT(!spin_is_locked(&sl), "spin_is_locked after unlock");
-
- /* Test idr */
- struct idr idr;
- idr_init(&idr);
- int id = idr_alloc(&idr, (void *)0xdeadbeef, 1, 100, GFP_KERNEL);
- TEST_ASSERT(id >= 1 && id < 100, "idr_alloc returns valid id");
- void *ptr = idr_find(&idr, id);
- TEST_ASSERT(ptr == (void *)0xdeadbeef, "idr_find returns correct pointer");
- idr_remove(&idr, id);
- TEST_ASSERT(idr_find(&idr, id) == NULL, "idr_remove works");
- idr_destroy(&idr);
-
- /* Test list */
- struct list_head head;
- INIT_LIST_HEAD(&head);
- TEST_ASSERT(list_empty(&head), "list_empty on new list");
-
- struct list_head item;
- INIT_LIST_HEAD(&item);
- list_add(&item, &head);
- TEST_ASSERT(!list_empty(&head), "list not empty after add");
- list_del(&item);
- TEST_ASSERT(list_empty(&head), "list empty after del");
-
- /* Test ktime */
- ktime_t start = ktime_get();
- ktime_t end = ktime_get();
- s64 diff = ktime_to_ns(ktime_sub(end, start));
- TEST_ASSERT(diff >= 0, "ktime_get and ktime_to_ns work");
-
- return 0;
-}
-
-/* ============================================================
- * Test: Structure Sizes (from driver header)
- * ============================================================ */
-
-static int test_structure_sizes(void)
-{
- pr_info("=== Testing Structure Sizes ===\n");
-
- /* These sizes must match driver/include/gsp_core.h */
- TEST_ASSERT_EQ(sizeof(struct gsp_rpc_header), 64, "gsp_rpc_header size");
- TEST_ASSERT_EQ(sizeof(struct gsp_rpc_message), 256, "gsp_rpc_message size");
- TEST_ASSERT_EQ(sizeof(struct gsp_rpc_response), 32, "gsp_rpc_response size");
- TEST_ASSERT_EQ(sizeof(struct gsp_alloc_payload), 40, "gsp_alloc_payload size");
- TEST_ASSERT_EQ(sizeof(struct gsp_alloc_response), 24, "gsp_alloc_response size");
- TEST_ASSERT_EQ(sizeof(struct gsp_pin_payload), 40, "gsp_pin_payload size");
- TEST_ASSERT_EQ(sizeof(struct gsp_pin_response), 8, "gsp_pin_response size");
- TEST_ASSERT_EQ(sizeof(struct gsp_bar_trap_payload), 40, "gsp_bar_trap_payload size");
- TEST_ASSERT_EQ(sizeof(struct gsp_bar_trap_response), 8, "gsp_bar_trap_response size");
- TEST_ASSERT_EQ(sizeof(struct gsp_migrate_payload), 56, "gsp_migrate_payload size");
- TEST_ASSERT_EQ(sizeof(struct gsp_subcmd_desc), 8, "gsp_subcmd_desc size");
- TEST_ASSERT_EQ(sizeof(struct gsp_vf_config), 56, "gsp_vf_config size");
-
- return 0;
-}
-
-/* ============================================================
- * Test: Enum Values (from driver header)
- * ============================================================ */
-
-static int test_enum_values(void)
-{
- pr_info("=== Testing Enum Values ===\n");
-
- TEST_ASSERT_EQ(GSP_RPC_ALLOC, 0x01, "RPC_ALLOC");
- TEST_ASSERT_EQ(GSP_RPC_FREE, 0x02, "RPC_FREE");
- TEST_ASSERT_EQ(GSP_RPC_MAP, 0x03, "RPC_MAP");
- TEST_ASSERT_EQ(GSP_RPC_UNMAP, 0x04, "RPC_UNMAP");
- TEST_ASSERT_EQ(GSP_RPC_PIN, 0x05, "RPC_PIN");
- TEST_ASSERT_EQ(GSP_RPC_UNPIN, 0x06, "RPC_UNPIN");
- TEST_ASSERT_EQ(GSP_RPC_SCHEDULE, 0x07, "RPC_SCHEDULE");
- TEST_ASSERT_EQ(GSP_RPC_YIELD, 0x08, "RPC_YIELD");
- TEST_ASSERT_EQ(GSP_RPC_NOTIFY, 0x09, "RPC_NOTIFY");
- TEST_ASSERT_EQ(GSP_RPC_BAR_TRAP, 0x0A, "RPC_BAR_TRAP");
- TEST_ASSERT_EQ(GSP_RPC_MIGRATE, 0x0B, "RPC_MIGRATE");
- TEST_ASSERT_EQ(GSP_RPC_DEBUG, 0x0C, "RPC_DEBUG");
-
- TEST_ASSERT_EQ(GSP_MEM_VRAM, 0, "MEM_VRAM");
- TEST_ASSERT_EQ(GSP_MEM_SYSMEM, 1, "MEM_SYSMEM");
- TEST_ASSERT_EQ(GSP_MEM_UNCACHED, 2, "MEM_UNCACHED");
-
- TEST_ASSERT_EQ(GSP_PIN_READ, (1 << 0), "PIN_READ");
- TEST_ASSERT_EQ(GSP_PIN_WRITE, (1 << 1), "PIN_WRITE");
- TEST_ASSERT_EQ(GSP_PIN_LONGTERM, (1 << 2), "PIN_LONGTERM");
-
- TEST_ASSERT_EQ(GSP_MIG_QUERY, 0, "MIG_QUERY");
- TEST_ASSERT_EQ(GSP_MIG_PREPARE, 1, "MIG_PREPARE");
- TEST_ASSERT_EQ(GSP_MIG_TRANSFER, 2, "MIG_TRANSFER");
- TEST_ASSERT_EQ(GSP_MIG_COMMIT, 3, "MIG_COMMIT");
- TEST_ASSERT_EQ(GSP_MIG_CLEANUP, 4, "MIG_CLEANUP");
-
- TEST_ASSERT_EQ(GSP_MIG_LIVE, (1 << 0), "MIG_LIVE");
- TEST_ASSERT_EQ(GSP_MIG_POSTCOPY, (1 << 1), "MIG_POSTCOPY");
- TEST_ASSERT_EQ(GSP_MIG_AUTO_COMMIT, (1 << 2), "MIG_AUTO_COMMIT");
- TEST_ASSERT_EQ(GSP_MIG_VERIFY, (1 << 3), "MIG_VERIFY");
-
- TEST_ASSERT_EQ(GSP_VF_CREATING, 0, "VF_CREATING");
- TEST_ASSERT_EQ(GSP_VF_ACTIVE, 1, "VF_ACTIVE");
- TEST_ASSERT_EQ(GSP_VF_MIGRATING, 2, "VF_MIGRATING");
- TEST_ASSERT_EQ(GSP_VF_SUSPENDED, 3, "VF_SUSPENDED");
- TEST_ASSERT_EQ(GSP_VF_DESTROYING, 4, "VF_DESTROYING");
-
- return 0;
-}
-
-/* ============================================================
- * Test: Error Code Mapping
- * ============================================================ */
-
-static int test_error_codes(void)
-{
- pr_info("=== Testing Error Codes ===\n");
-
- TEST_ASSERT_EQ(GSP_OK, 0, "GSP_OK");
- TEST_ASSERT_EQ(GSP_EPERM, 0xFFFFFFFF, "GSP_EPERM");
- TEST_ASSERT_EQ(GSP_ENOENT, 0xFFFFFFFE, "GSP_ENOENT");
- TEST_ASSERT_EQ(GSP_EINVAL, 0xFFFFFFFD, "GSP_EINVAL");
- TEST_ASSERT_EQ(GSP_ENODEV, 0xFFFFFFFA, "GSP_ENODEV");
- TEST_ASSERT_EQ(GSP_ENOMEM, 0xFFFFFFF4, "GSP_ENOMEM");
- TEST_ASSERT_EQ(GSP_EBUSY, 0xFFFFFFEE, "GSP_EBUSY");
- TEST_ASSERT_EQ(GSP_ENOSPC, 0xFFFFFFE4, "GSP_ENOSPC");
- TEST_ASSERT_EQ(GSP_ETIMEDOUT, 0x0000001E, "GSP_ETIMEDOUT");
- TEST_ASSERT_EQ(GSP_EOVERFLOW, 0x00000025, "GSP_EOVERFLOW");
- TEST_ASSERT_EQ(GSP_EDEV, 0x0000001F, "GSP_EDEV");
-
- return 0;
-}
-
-/* ============================================================
- * Test: Firmware Constants
- * ============================================================ */
-
-static int test_firmware_constants(void)
-{
- pr_info("=== Testing Firmware Constants ===\n");
-
- TEST_ASSERT_EQ(GSP_FW_BASE_ADDR, 0x04000000ULL, "FW_BASE_ADDR");
- TEST_ASSERT_EQ(GSP_FW_SIZE, 0x02000000ULL, "FW_SIZE");
- TEST_ASSERT_EQ(GSP_ENTRY_POINT, 0x04009000ULL, "ENTRY_POINT");
- TEST_ASSERT_EQ(GSP_PRIMARY_DISPATCHER, 0x057A1AC0ULL, "PRIMARY_DISPATCHER");
- TEST_ASSERT_EQ(GSP_SECONDARY_DISPATCHER, 0x04ED39DCULL, "SECONDARY_DISPATCHER");
- TEST_ASSERT_EQ(GSP_RPC_JUMP_TABLE, 0x059BFEB0ULL, "RPC_JUMP_TABLE");
- TEST_ASSERT_EQ(GSP_BAR0_DOORBELL, 0x1000, "BAR0_DOORBELL");
- TEST_ASSERT_EQ(GSP_BAR0_MSIX, 0x2000, "BAR0_MSIX");
- TEST_ASSERT_EQ(GSP_MSG_RING_SIZE, 256, "MSG_RING_SIZE");
- TEST_ASSERT_EQ(GSP_MSG_MAX_SIZE, 256, "MSG_MAX_SIZE");
- TEST_ASSERT_EQ(GSP_MAX_PENDING, 64, "MAX_PENDING");
-
- return 0;
-}
-
-/* ============================================================
- * Test: Migration State Enum (internal)
- * ============================================================ */
-
-static int test_migration_states(void)
-{
- pr_info("=== Testing Migration States ===\n");
-
- TEST_ASSERT_EQ(GSP_MIG_S_IDLE, 0, "MIG_S_IDLE");
- TEST_ASSERT_EQ(GSP_MIG_S_QUERY, 1, "MIG_S_QUERY");
- TEST_ASSERT_EQ(GSP_MIG_S_PREPARE, 2, "MIG_S_PREPARE");
- TEST_ASSERT_EQ(GSP_MIG_S_TRANSFER, 3, "MIG_S_TRANSFER");
- TEST_ASSERT_EQ(GSP_MIG_S_COMMIT, 4, "MIG_S_COMMIT");
- TEST_ASSERT_EQ(GSP_MIG_S_CLEANUP, 5, "MIG_S_CLEANUP");
- TEST_ASSERT_EQ(GSP_MIG_S_FAILED, 6, "MIG_S_FAILED");
- TEST_ASSERT_EQ(GSP_MIG_S_COMPLETED, 7, "MIG_S_COMPLETED");
-
- return 0;
-}
-
-/* ============================================================
- * Test: WPR Flags and Events
- * ============================================================ */
-
-static int test_wpr_flags(void)
-{
- pr_info("=== Testing WPR Flags ===\n");
-
- TEST_ASSERT_EQ(GSP_WPR_WRITE, (1 << 0), "WPR_WRITE");
- TEST_ASSERT_EQ(GSP_WPR_READ, (1 << 1), "WPR_READ");
- TEST_ASSERT_EQ(GSP_WPR_EXECUTE, (1 << 2), "WPR_EXECUTE");
-
- TEST_ASSERT_EQ(GSP_WPR_WRITE_COMPLETE, 0, "WPR_WRITE_COMPLETE");
- TEST_ASSERT_EQ(GSP_WPR_READ_COMPLETE, 1, "WPR_READ_COMPLETE");
- TEST_ASSERT_EQ(GSP_WPR_WRITE_TIMEOUT, 2, "WPR_WRITE_TIMEOUT");
- TEST_ASSERT_EQ(GSP_WPR_READ_TIMEOUT, 3, "WPR_READ_TIMEOUT");
-
- return 0;
-}
-
-/* ============================================================
- * Test: Message Flags
- * ============================================================ */
-
-static int test_message_flags(void)
-{
- pr_info("=== Testing Message Flags ===\n");
-
- TEST_ASSERT_EQ(GSP_MSG_SYNC, (1 << 0), "MSG_SYNC");
- TEST_ASSERT_EQ(GSP_MSG_ASYNC, (1 << 1), "MSG_ASYNC");
- TEST_ASSERT_EQ(GSP_MSG_NOREPLY, (1 << 2), "MSG_NOREPLY");
-
- return 0;
-}
-
-/* ============================================================
- * Test: BAR Trap Types
- * ============================================================ */
-
-static int test_bar_trap_types(void)
-{
- pr_info("=== Testing BAR Trap Types ===\n");
-
- TEST_ASSERT_EQ(GSP_BAR_READ, 0, "BAR_READ");
- TEST_ASSERT_EQ(GSP_BAR_WRITE, 1, "BAR_WRITE");
- TEST_ASSERT_EQ(GSP_BAR_ATOMIC, 2, "BAR_ATOMIC");
-
- return 0;
-}
-
-/* ============================================================
- * Test: Memory Allocation Patterns
- * ============================================================ */
-
-static int test_memory_patterns(void)
-{
- pr_info("=== Testing Memory Allocation Patterns ===\n");
-
- /* Test vzalloc/vfree */
- void *ptr = vzalloc(4096);
- TEST_ASSERT(ptr != NULL, "vzalloc allocates memory");
- vfree(ptr);
-
- /* Test kmalloc/kfree */
- ptr = kmalloc(1024, GFP_KERNEL);
- TEST_ASSERT(ptr != NULL, "kmalloc allocates memory");
- kfree(ptr);
-
- /* Test kcalloc */
- ptr = kcalloc(10, 64, GFP_KERNEL);
- TEST_ASSERT(ptr != NULL, "kcalloc allocates zeroed memory");
- kfree(ptr);
-
- return 0;
-}
-
-/* ============================================================
- * Test: String Operations
- * ============================================================ */
-
-static int test_string_ops(void)
-{
- pr_info("=== Testing String Operations ===\n");
-
- char buf[64];
- int len = snprintf(buf, sizeof(buf), "test_%d", 42);
- TEST_ASSERT(len > 0 && len < sizeof(buf), "snprintf works");
- TEST_ASSERT(strcmp(buf, "test_42") == 0, "snprintf formats correctly");
-
- char *dup = kstrdup("test_string", GFP_KERNEL);
- TEST_ASSERT(dup != NULL, "kstrdup works");
- TEST_ASSERT(strcmp(dup, "test_string") == 0, "kstrdup copies correctly");
- kfree(dup);
-
- return 0;
-}
-
-/* ============================================================
- * Test Suite Runner
- * ============================================================ */
-
-static int run_all_tests(void)
-{
- pr_info("\n============================================================\n");
- pr_info("GSP vGPU-IO Comprehensive Test Suite Starting\n");
- pr_info("============================================================\n\n");
-
- test_kernel_apis();
- test_structure_sizes();
- test_enum_values();
- test_error_codes();
- test_firmware_constants();
- test_migration_states();
- test_wpr_flags();
- test_message_flags();
- test_bar_trap_types();
- test_memory_patterns();
- test_string_ops();
-
- pr_info("\n============================================================\n");
- pr_info("TEST RESULTS: %d total, %d passed, %d failed\n",
- test_count, pass_count, fail_count);
- pr_info("============================================================\n");
-
- if (fail_count == 0) {
- pr_info("TEST SUITE PASSED\n");
- return 0;
- } else {
- pr_err("TEST SUITE FAILED\n");
- return -1;
- }
-}
-
-/* ============================================================
- * Module Init/Exit
- * ============================================================ */
-
-static int __init gsp_test_init(void)
-{
- return run_all_tests();
-}
-
-static void __exit gsp_test_exit(void)
-{
- pr_info("GSP vGPU-IO test module unloaded\n");
-}
-
-module_init(gsp_test_init);
-module_exit(gsp_test_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("NVIDIA vGPU-IO Team");
-MODULE_DESCRIPTION("GSP vGPU-IO Comprehensive Test Suite");
-MODULE_VERSION("1.0.0"); \ No newline at end of file
diff --git a/legacy-driver-guest/kernel-tests/gsp_vgpu_kunit_test.c b/legacy-driver-guest/kernel-tests/gsp_vgpu_kunit_test.c
deleted file mode 100644
index c661f91..0000000
--- a/legacy-driver-guest/kernel-tests/gsp_vgpu_kunit_test.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * GSP vGPU-IO KUnit Tests
- * In-kernel unit tests for the driver
- */
-
-#include <kunit/test.h>
-#include <kunit/mock.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/atomic.h>
-#include <linux/list.h>
-#include <linux/idr.h>
-#include <linux/mutex.h>
-#include <linux/kref.h>
-#include <linux/completion.h>
-#include <linux/wait.h>
-#include <linux/spinlock.h>
-
-#include <gsp_core.h>
-
-/* ============================================================
- * Test: Structure Sizes and Alignments
- * ============================================================ */
-
-static void test_structure_sizes(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_rpc_header), 64);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_rpc_message), 256);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_rpc_response), 32);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_subcmd_desc), 8);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_vf_config), 64);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_alloc_payload), 48);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_alloc_response), 24);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_pin_payload), 40);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_pin_response), 8);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_bar_trap_payload), 40);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_bar_trap_response), 8);
- KUNIT_EXPECT_EQ(test, sizeof(struct gsp_migrate_payload), 64);
-}
-
-static void test_structure_alignments(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_rpc_header), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_rpc_message), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_rpc_response), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_subcmd_desc), 4);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_vf_config), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_alloc_payload), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_alloc_response), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_pin_payload), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_pin_response), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_bar_trap_payload), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_bar_trap_response), 8);
- KUNIT_EXPECT_EQ(test, __alignof__(struct gsp_migrate_payload), 8);
-}
-
-/* ============================================================
- * Test: Payload Encoding/Decoding
- * ============================================================ */
-
-static void test_alloc_payload_encoding(struct kunit *test)
-{
- struct gsp_alloc_payload payload = {0};
-
- payload.size = cpu_to_le64(0x100000);
- payload.type = cpu_to_le32(GSP_MEM_VRAM);
- payload.alignment = cpu_to_le32(0x1000);
- payload.va_hint = cpu_to_le64(0x0);
- payload.flags = cpu_to_le32(0x3);
- payload.pid = cpu_to_le32(0x456);
- payload.vf_id = cpu_to_le32(0x1);
-
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.size), 0x100000);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.type), GSP_MEM_VRAM);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.alignment), 0x1000);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.va_hint), 0x0);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.flags), 0x3);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.pid), 0x456);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.vf_id), 0x1);
-}
-
-static void test_pin_payload_encoding(struct kunit *test)
-{
- struct gsp_pin_payload payload = {0};
-
- payload.handle = cpu_to_le64(0xCAFEBABE);
- payload.offset = cpu_to_le64(0x1000);
- payload.size = cpu_to_le64(0x10000);
- payload.vf_id = cpu_to_le32(0x2);
- payload.flags = cpu_to_le32(GSP_PIN_READ | GSP_PIN_WRITE);
-
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.handle), 0xCAFEBABE);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.offset), 0x1000);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.size), 0x10000);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.vf_id), 0x2);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.flags), GSP_PIN_READ | GSP_PIN_WRITE);
-}
-
-static void test_bar_trap_payload_encoding(struct kunit *test)
-{
- struct gsp_bar_trap_payload payload = {0};
-
- payload.bar_index = cpu_to_le32(1);
- payload.trap_type = cpu_to_le32(GSP_BAR_WRITE);
- payload.offset = cpu_to_le64(0x1000);
- payload.value = cpu_to_le64(0xDEADBEEF);
- payload.size = cpu_to_le32(4);
- payload.vf_id = cpu_to_le32(0x1);
-
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.bar_index), 1);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.trap_type), GSP_BAR_WRITE);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.offset), 0x1000);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.value), 0xDEADBEEF);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.size), 4);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.vf_id), 0x1);
-}
-
-static void test_migrate_payload_encoding(struct kunit *test)
-{
- struct gsp_migrate_payload payload = {0};
-
- payload.phase = cpu_to_le32(GSP_MIG_PREPARE);
- payload.subcmd = cpu_to_le32(3);
- payload.src_vf = cpu_to_le64(0x1);
- payload.dst_vf = cpu_to_le64(0x2);
- payload.data_ptr = cpu_to_le64(0x80000000);
- payload.data_size = cpu_to_le64(0x1000);
- payload.flags = cpu_to_le32(GSP_MIG_LIVE | GSP_MIG_VERIFY);
- payload.token = cpu_to_le64(0xABCDEF1234567890);
-
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.phase), GSP_MIG_PREPARE);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.subcmd), 3);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.src_vf), 0x1);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.dst_vf), 0x2);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.data_ptr), 0x80000000);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.data_size), 0x1000);
- KUNIT_EXPECT_EQ(test, le32_to_cpu(payload.flags), GSP_MIG_LIVE | GSP_MIG_VERIFY);
- KUNIT_EXPECT_EQ(test, le64_to_cpu(payload.token), 0xABCDEF1234567890);
-}
-
-static void test_subcmd_desc_encoding(struct kunit *test)
-{
- struct gsp_subcmd_desc desc = {0};
-
- desc.subcmd_id = cpu_to_le32(0x14);
- desc.echo_flags_b = 0xAA;
- desc.echo_flags_a = 0xBB;
- desc.echo_flags_c = 0xCC;
-
- KUNIT_EXPECT_EQ(test, le32_to_cpu(desc.subcmd_id), 0x14);
- KUNIT_EXPECT_EQ(test, desc.echo_flags_b, 0xAA);
- KUNIT_EXPECT_EQ(test, desc.echo_flags_a, 0xBB);
- KUNIT_EXPECT_EQ(test, desc.echo_flags_c, 0xCC);
-}
-
-/* ============================================================
- * Test: Firmware Address Constants
- * ============================================================ */
-
-static void test_firmware_addresses(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, GSP_FW_BASE_ADDR, 0x04000000ULL);
- KUNIT_EXPECT_EQ(test, GSP_ENTRY_POINT, 0x04009000ULL);
- KUNIT_EXPECT_EQ(test, GSP_PRIMARY_DISPATCHER, 0x057A1AC0ULL);
- KUNIT_EXPECT_EQ(test, GSP_SECONDARY_DISPATCHER, 0x04ED39DCULL);
- KUNIT_EXPECT_EQ(test, GSP_RPC_JUMP_TABLE, 0x059BFEB0ULL);
- KUNIT_EXPECT_EQ(test, 0x04179ED8ULL, 0x04179ED8ULL); /* Migration Table 1 */
- KUNIT_EXPECT_EQ(test, 0x04179FBCULL, 0x04179FBCULL); /* Migration Table 2 */
- KUNIT_EXPECT_EQ(test, 0x04CB8188ULL, 0x04CB8188ULL); /* BAR Handler */
- KUNIT_EXPECT_EQ(test, 0x04F00B0CULL, 0x04F00B0CULL); /* WPR Handler 1 */
- KUNIT_EXPECT_EQ(test, 0x04F00C78ULL, 0x04F00C78ULL); /* WPR Handler 2 */
- KUNIT_EXPECT_EQ(test, 0x057E94ECULL, 0x057E94ECULL); /* ALLOC Main */
- KUNIT_EXPECT_EQ(test, 0x051EFBF4ULL, 0x051EFBF4ULL); /* SCHEDULE Main */
-}
-
-/* ============================================================
- * Test: RPC Type Constants
- * ============================================================ */
-
-static void test_rpc_types(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, GSP_RPC_ALLOC, 0x01);
- KUNIT_EXPECT_EQ(test, GSP_RPC_FREE, 0x02);
- KUNIT_EXPECT_EQ(test, GSP_RPC_MAP, 0x03);
- KUNIT_EXPECT_EQ(test, GSP_RPC_UNMAP, 0x04);
- KUNIT_EXPECT_EQ(test, GSP_RPC_PIN, 0x05);
- KUNIT_EXPECT_EQ(test, GSP_RPC_UNPIN, 0x06);
- KUNIT_EXPECT_EQ(test, GSP_RPC_SCHEDULE, 0x07);
- KUNIT_EXPECT_EQ(test, GSP_RPC_YIELD, 0x08);
- KUNIT_EXPECT_EQ(test, GSP_RPC_NOTIFY, 0x09);
- KUNIT_EXPECT_EQ(test, GSP_RPC_BAR_TRAP, 0x0A);
- KUNIT_EXPECT_EQ(test, GSP_RPC_MIGRATE, 0x0B);
- KUNIT_EXPECT_EQ(test, GSP_RPC_DEBUG, 0x0C);
-}
-
-static void test_migration_constants(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, GSP_MIG_QUERY, 0);
- KUNIT_EXPECT_EQ(test, GSP_MIG_PREPARE, 1);
- KUNIT_EXPECT_EQ(test, GSP_MIG_TRANSFER, 2);
- KUNIT_EXPECT_EQ(test, GSP_MIG_COMMIT, 3);
- KUNIT_EXPECT_EQ(test, GSP_MIG_CLEANUP, 4);
-
- KUNIT_EXPECT_EQ(test, GSP_MIG_LIVE, (1 << 0));
- KUNIT_EXPECT_EQ(test, GSP_MIG_POSTCOPY, (1 << 1));
- KUNIT_EXPECT_EQ(test, GSP_MIG_AUTO_COMMIT, (1 << 2));
- KUNIT_EXPECT_EQ(test, GSP_MIG_VERIFY, (1 << 3));
-}
-
-static void test_bar_trap_types(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, GSP_BAR_READ, 0);
- KUNIT_EXPECT_EQ(test, GSP_BAR_WRITE, 1);
- KUNIT_EXPECT_EQ(test, GSP_BAR_ATOMIC, 2);
-}
-
-static void test_pin_flags(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, GSP_PIN_READ, (1 << 0));
- KUNIT_EXPECT_EQ(test, GSP_PIN_WRITE, (1 << 1));
- KUNIT_EXPECT_EQ(test, GSP_PIN_LONGTERM, (1 << 2));
-}
-
-static void test_wpr_flags(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, GSP_WPR_WRITE, (1 << 0));
- KUNIT_EXPECT_EQ(test, GSP_WPR_READ, (1 << 1));
- KUNIT_EXPECT_EQ(test, GSP_WPR_EXECUTE, (1 << 2));
-}
-
-static void test_vf_states(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, GSP_VF_CREATING, 0);
- KUNIT_EXPECT_EQ(test, GSP_VF_ACTIVE, 1);
- KUNIT_EXPECT_EQ(test, GSP_VF_MIGRATING, 2);
- KUNIT_EXPECT_EQ(test, GSP_VF_SUSPENDED, 3);
- KUNIT_EXPECT_EQ(test, GSP_VF_DESTROYING, 4);
-}
-
-static void test_msg_flags(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, GSP_MSG_SYNC, (1 << 0));
- KUNIT_EXPECT_EQ(test, GSP_MSG_ASYNC, (1 << 1));
- KUNIT_EXPECT_EQ(test, GSP_MSG_NOREPLY, (1 << 2));
-}
-
-/* ============================================================
- * Test: Error Code Translation
- * ============================================================ */
-
-static void test_error_codes(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_OK), 0);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_EPERM), -EPERM);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_ENOENT), -ENOENT);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_EINVAL), -EINVAL);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_ENODEV), -ENODEV);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_ENOMEM), -ENOMEM);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_EBUSY), -EBUSY);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_ENOSPC), -ENOSPC);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_ETIMEDOUT), -ETIMEDOUT);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_EOVERFLOW), -EOVERFLOW);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(GSP_EDEV), -EIO);
- KUNIT_EXPECT_EQ(test, gsp_errno_to_errno(0xDEADBEEF), -EIO);
-}
-
-/* ============================================================
- * Test: Memory Types
- * ============================================================ */
-
-static void test_memory_types(struct kunit *test)
-{
- KUNIT_EXPECT_EQ(test, GSP_MEM_VRAM, 0);
- KUNIT_EXPECT_EQ(test, GSP_MEM_SYSMEM, 1);
- KUNIT_EXPECT_EQ(test, GSP_MEM_UNCACHED, 2);
-}
-
-/* ============================================================
- * Test: Payload Capacity
- * ============================================================ */
-
-static void test_payload_capacity(struct kunit *test)
-{
- KUNIT_EXPECT_TRUE(test, sizeof(struct gsp_alloc_payload) <= 192);
- KUNIT_EXPECT_TRUE(test, sizeof(struct gsp_pin_payload) <= 192);
- KUNIT_EXPECT_TRUE(test, sizeof(struct gsp_bar_trap_payload) <= 192);
- KUNIT_EXPECT_TRUE(test, sizeof(struct gsp_migrate_payload) <= 192);
- KUNIT_EXPECT_TRUE(test, sizeof(struct gsp_subcmd_desc) <= 192);
-}
-
-/* ============================================================
- * Test Suite Registration
- * ============================================================ */
-
-static struct kunit_case gsp_vgpu_test_cases[] = {
- KUNIT_CASE(test_structure_sizes),
- KUNIT_CASE(test_structure_alignments),
- KUNIT_CASE(test_alloc_payload_encoding),
- KUNIT_CASE(test_pin_payload_encoding),
- KUNIT_CASE(test_bar_trap_payload_encoding),
- KUNIT_CASE(test_migrate_payload_encoding),
- KUNIT_CASE(test_subcmd_desc_encoding),
- KUNIT_CASE(test_firmware_addresses),
- KUNIT_CASE(test_rpc_types),
- KUNIT_CASE(test_migration_constants),
- KUNIT_CASE(test_bar_trap_types),
- KUNIT_CASE(test_pin_flags),
- KUNIT_CASE(test_wpr_flags),
- KUNIT_CASE(test_vf_states),
- KUNIT_CASE(test_msg_flags),
- KUNIT_CASE(test_error_codes),
- KUNIT_CASE(test_memory_types),
- KUNIT_CASE(test_payload_capacity),
- {}
-};
-
-static struct kunit_suite gsp_vgpu_test_suite = {
- .name = "gsp-vgpu-io",
- .test_cases = gsp_vgpu_test_cases,
-};
-
-kunit_test_suites(&gsp_vgpu_test_suite);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Open-IOV Project");
-MODULE_DESCRIPTION("GSP vGPU-IO KUnit Tests"); \ No newline at end of file
diff --git a/legacy-driver-guest/kernel-tests/gsp_vgpu_mock_test.c b/legacy-driver-guest/kernel-tests/gsp_vgpu_mock_test.c
deleted file mode 100644
index b9a46df..0000000
--- a/legacy-driver-guest/kernel-tests/gsp_vgpu_mock_test.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * GSP vGPU-IO Driver Mock Test
- * Tests driver logic with mocked hardware interfaces
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <linux/idr.h>
-#include <linux/kref.h>
-#include <linux/completion.h>
-#include <linux/atomic.h>
-
-#define TEST_PASS 0
-#define TEST_FAIL -1
-
-static int test_count = 0;
-static int pass_count = 0;
-static int fail_count = 0;
-
-#define TEST_ASSERT(cond, msg) \
- do { \
- test_count++; \
- if (cond) { \
- pass_count++; \
- pr_info("PASS: %s\n", msg); \
- } else { \
- fail_count++; \
- pr_err("FAIL: %s\n", msg); \
- } \
- } while (0)
-
-#define TEST_ASSERT_EQ(a, b, msg) \
- TEST_ASSERT((a) == (b), msg " (expected " #b ", got " #a ")")
-
-/* ============================================================
- * Mock Hardware Abstraction
- * ============================================================ */
-
-struct mock_hw {
- u64 bar0_regs[256];
- u64 bar1_regs[256];
- u8 *fw_memory;
- size_t fw_size;
- bool doorbell_triggered;
- u32 doorbell_count;
- spinlock_t lock;
-};
-
-static struct mock_hw *mock_hw_create(void)
-{
- struct mock_hw *hw = kzalloc(sizeof(*hw), GFP_KERNEL);
- if (!hw)
- return NULL;
-
- hw->fw_memory = vmalloc(32 * 1024 * 1024); // 32MB
- if (!hw->fw_memory) {
- kfree(hw);
- return NULL;
- }
- hw->fw_size = 32 * 1024 * 1024;
- spin_lock_init(&hw->lock);
- return hw;
-}
-
-static void mock_hw_destroy(struct mock_hw *hw)
-{
- if (!hw)
- return;
- vfree(hw->fw_memory);
- kfree(hw);
-}
-
-static void mock_hw_write_bar0(struct mock_hw *hw, u32 offset, u32 value)
-{
- unsigned long flags;
- spin_lock_irqsave(&hw->lock, flags);
- if (offset / 4 < 256)
- hw->bar0_regs[offset / 4] = value;
- if (offset == 0x1000) { // Doorbell
- hw->doorbell_triggered = true;
- hw->doorbell_count++;
- }
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static u32 mock_hw_read_bar0(struct mock_hw *hw, u32 offset)
-{
- unsigned long flags;
- u32 value = 0;
- spin_lock_irqsave(&hw->lock, flags);
- if (offset / 4 < 256)
- value = hw->bar0_regs[offset / 4];
- spin_unlock_irqrestore(&hw->lock, flags);
- return value;
-}
-
-static void mock_hw_write_bar1(struct mock_hw *hw, u64 offset, u64 value)
-{
- unsigned long flags;
- spin_lock_irqsave(&hw->lock, flags);
- if (offset < hw->fw_size)
- *(u64 *)(hw->fw_memory + offset) = value;
- spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static u64 mock_hw_read_bar1(struct mock_hw *hw, u64 offset)
-{
- unsigned long flags;
- u64 value = 0;
- spin_lock_irqsave(&hw->lock, flags);
- if (offset < hw->fw_size)
- value = *(u64 *)(hw->fw_memory + offset);
- spin_unlock_irqrestore(&hw->lock, flags);
- return value;
-}
-
-/* ============================================================
- * Mock VF Operations
- * ============================================================ */
-
-struct mock_vf {
- u32 id;
- u64 bar1_offset;
- u64 bar1_size;
- u64 pt_base;
- u64 pt_size;
- u64 cmd_base;
- u64 cmd_size;
- bool active;
- struct {
- u64 aperture_offset;
- u64 aperture_size;
- bool force_access;
- u32 force_vf;
- } bar_state;
- struct list_head wpr_list;
- struct mutex lock;
-};
-
-struct mock_wpr_region {
- struct list_head list;
- u64 base;
- u64 size;
- u32 flags;
-};
-
-static struct mock_vf *mock_vf_create(u32 id, u64 bar1_offset, u64 bar1_size,
- u64 pt_base, u64 pt_size,
- u64 cmd_base, u64 cmd_size)
-{
- struct mock_vf *vf = kzalloc(sizeof(*vf), GFP_KERNEL);
- if (!vf)
- return NULL;
-
- vf->id = id;
- vf->bar1_offset = bar1_offset;
- vf->bar1_size = bar1_size;
- vf->pt_base = pt_base;
- vf->pt_size = pt_size;
- vf->cmd_base = cmd_base;
- vf->cmd_size = cmd_size;
- vf->active = true;
- INIT_LIST_HEAD(&vf->wpr_list);
- mutex_init(&vf->lock);
-
- vf->bar_state.aperture_offset = bar1_offset;
- vf->bar_state.aperture_size = bar1_size;
- vf->bar_state.force_access = false;
- vf->bar_state.force_vf = 0;
-
- return vf;
-}
-
-static void mock_vf_destroy(struct mock_vf *vf)
-{
- if (!vf)
- return;
-
- struct mock_wpr_region *rgn, *tmp;
- mutex_lock(&vf->lock);
- list_for_each_entry_safe(rgn, tmp, &vf->wpr_list, list) {
- list_del(&rgn->list);
- kfree(rgn);
- }
- mutex_unlock(&vf->lock);
-
- kfree(vf);
-}
-
-static int mock_vf_wpr_add(struct mock_vf *vf, u64 base, u64 size, u32 flags)
-{
- struct mock_wpr_region *rgn = kzalloc(sizeof(*rgn), GFP_KERNEL);
- if (!rgn)
- return -ENOMEM;
-
- rgn->base = base;
- rgn->size = size;
- rgn->flags = flags;
-
- mutex_lock(&vf->lock);
- list_add(&rgn->list, &vf->wpr_list);
- mutex_unlock(&vf->lock);
-
- return 0;
-}
-
-static int mock_vf_wpr_remove(struct mock_vf *vf, u64 base)
-{
- struct mock_wpr_region *rgn, *tmp;
- bool found = false;
-
- mutex_lock(&vf->lock);
- list_for_each_entry_safe(rgn, tmp, &vf->wpr_list, list) {
- if (rgn->base == base) {
- list_del(&rgn->list);
- kfree(rgn);
- found = true;
- break;
- }
- }
- mutex_unlock(&vf->lock);
-
- return found ? 0 : -ENOENT;
-}
-
-/* ============================================================
- * Mock RPC Client
- * ============================================================ */
-
-struct mock_rpc_client {
- u32 seq;
- u32 pending_seq[64];
- u32 pending_count;
- struct mutex lock;
-};
-
-static struct mock_rpc_client *mock_rpc_create(void)
-{
- struct mock_rpc_client *rpc = kzalloc(sizeof(*rpc), GFP_KERNEL);
- if (!rpc)
- return NULL;
- mutex_init(&rpc->lock);
- return rpc;
-}
-
-static void mock_rpc_destroy(struct mock_rpc_client *rpc)
-{
- if (!rpc)
- return;
- kfree(rpc);
-}
-
-static int mock_rpc_send(struct mock_rpc_client *rpc, u32 rpc_type,
- void *payload, size_t payload_size,
- void *response, size_t *response_size)
-{
- if (!rpc)
- return -EINVAL;
-
- mutex_lock(&rpc->lock);
- rpc->seq++;
- rpc->pending_seq[rpc->pending_count++] = rpc->seq;
- mutex_unlock(&rpc->lock);
-
- /* Simulate successful response */
- if (response && response_size) {
- struct gsp_rpc_response *resp = response;
- resp->status = 0;
- resp->rpc_type = rpc_type;
- resp->sequence = rpc->seq;
- *response_size = sizeof(*resp);
- }
-
- return 0;
-}
-
-/* ============================================================
- * Driver Logic Tests with Mocks
- * ============================================================ */
-
-static int test_mock_hardware(void)
-{
- struct mock_hw *hw = mock_hw_create();
- TEST_ASSERT(hw != NULL, "Mock HW create");
-
- /* Test BAR0 write/read */
- mock_hw_write_bar0(hw, 0x1000, 0x1);
- TEST_ASSERT(hw->doorbell_triggered, "Doorbell triggered");
- TEST_ASSERT_EQ(hw->doorbell_count, 1, "Doorbell count");
-
- u32 val = mock_hw_read_bar0(hw, 0x1000);
- TEST_ASSERT_EQ(val, 0x1, "BAR0 read back");
-
- /* Test BAR1 write/read */
- mock_hw_write_bar1(hw, 0x1000, 0xDEADBEEFCAFEBABE);
- u64 val64 = mock_hw_read_bar1(hw, 0x1000);
- TEST_ASSERT_EQ(val64, 0xDEADBEEFCAFEBABE, "BAR1 read back");
-
- mock_hw_destroy(hw);
- return TEST_PASS;
-}
-
-static int test_mock_vf_lifecycle(void)
-{
- struct mock_vf *vf = mock_vf_create(1, 0x10000000, 0x100000,
- 0x20000000, 0x100000,
- 0x30000000, 0x10000);
- TEST_ASSERT(vf != NULL, "Mock VF create");
-
- TEST_ASSERT(vf->active, "VF active after create");
- TEST_ASSERT_EQ(vf->id, 1, "VF ID");
- TEST_ASSERT_EQ(vf->bar1_offset, 0x10000000, "BAR1 offset");
- TEST_ASSERT_EQ(vf->bar1_size, 0x100000, "BAR1 size");
- TEST_ASSERT_EQ(vf->pt_base, 0x20000000, "Page table base");
- TEST_ASSERT_EQ(vf->pt_size, 0x100000, "Page table size");
-
- /* Test BAR state */
- TEST_ASSERT_EQ(vf->bar_state.aperture_offset, 0x10000000, "Aperture offset");
- TEST_ASSERT_EQ(vf->bar_state.aperture_size, 0x100000, "Aperture size");
- TEST_ASSERT(!vf->bar_state.force_access, "Force access initially false");
-
- /* Test WPR list empty */
- TEST_ASSERT(list_empty(&vf->wpr_list), "WPR list empty initially");
-
- mock_vf_destroy(vf);
- return TEST_PASS;
-}
-
-static int test_mock_vf_wpr(void)
-{
- struct mock_vf *vf = mock_vf_create(1, 0x10000000, 0x100000,
- 0x20000000, 0x100000,
- 0x30000000, 0x10000);
- TEST_ASSERT(vf != NULL, "Mock VF create");
-
- /* Add WPR region */
- int ret = mock_vf_wpr_add(vf, 0x10000000, 0x10000, 3);
- TEST_ASSERT_EQ(ret, 0, "WPR add");
-
- ret = mock_vf_wpr_add(vf, 0x20000000, 0x20000, 1);
- TEST_ASSERT_EQ(ret, 0, "WPR add second");
-
- /* Verify list */
- int count = 0;
- struct mock_wpr_region *rgn;
- mutex_lock(&vf->lock);
- list_for_each_entry(rgn, &vf->wpr_list, list) {
- count++;
- }
- mutex_unlock(&vf->lock);
- TEST_ASSERT_EQ(count, 2, "Two WPR regions");
-
- /* Remove one */
- ret = mock_vf_wpr_remove(vf, 0x10000000);
- TEST_ASSERT_EQ(ret, 0, "WPR remove");
-
- count = 0;
- mutex_lock(&vf->lock);
- list_for_each_entry(rgn, &vf->wpr_list, list) {
- count++;
- }
- mutex_unlock(&vf->lock);
- TEST_ASSERT_EQ(count, 1, "One WPR region remaining");
-
- /* Remove non-existent */
- ret = mock_vf_wpr_remove(vf, 0x30000000);
- TEST_ASSERT_EQ(ret, -ENOENT, "WPR remove non-existent returns ENOENT");
-
- mock_vf_destroy(vf);
- return TEST_PASS;
-}
-
-static int test_mock_rpc_client(void)
-{
- struct mock_rpc_client *rpc = mock_rpc_create();
- TEST_ASSERT(rpc != NULL, "Mock RPC create");
-
- struct gsp_rpc_response resp;
- size_t resp_size = sizeof(resp);
- struct gsp_alloc_payload payload = {
- .size = cpu_to_le64(0x100000),
- .type = cpu_to_le32(GSP_MEM_VRAM),
- };
-
- int ret = mock_rpc_send(rpc, GSP_RPC_ALLOC, &payload, sizeof(payload), &resp, &resp_size);
- TEST_ASSERT_EQ(ret, 0, "RPC send");
-
- TEST_ASSERT_EQ(resp.status, 0, "RPC response status");
- TEST_ASSERT_EQ(resp.rpc_type, GSP_RPC_ALLOC, "RPC response type");
- TEST_ASSERT_EQ(resp.sequence, 1, "RPC response sequence");
-
- /* Second call */
- ret = mock_rpc_send(rpc, GSP_RPC_PIN, &payload, sizeof(payload), &resp, &resp_size);
- TEST_ASSERT_EQ(ret, 0, "RPC send second");
- TEST_ASSERT_EQ(resp.sequence, 2, "RPC response sequence 2");
-
- mock_rpc_destroy(rpc);
- return TEST_PASS;
-}
-
-static int test_driver_vf_creation_logic(void)
-{
- /* Simulate driver VF creation logic */
- struct mock_hw *hw = mock_hw_create();
- struct mock_rpc_client *rpc = mock_rpc_create();
- struct mock_vf *vfs[8] = {0};
-
- /* Create VFs 1-4 */
- for (int i = 1; i <= 4; i++) {
- vfs[i] = mock_vf_create(i, 0x10000000 * i, 0x100000,
- 0x20000000 * i, 0x100000,
- 0x30000000 * i, 0x10000);
- TEST_ASSERT(vfs[i] != NULL, "VF creation in loop");
- TEST_ASSERT(vfs[i]->active, "VF active in loop");
- }
-
- /* Initialize BAR for each VF */
- for (int i = 1; i <= 4; i++) {
- vfs[i]->bar_state.aperture_offset = vfs[i]->bar1_offset;
- vfs[i]->bar_state.aperture_size = vfs[i]->bar1_size;
- TEST_ASSERT_EQ(vfs[i]->bar_state.aperture_offset, 0x10000000 * i, "VF BAR offset");
- TEST_ASSERT_EQ(vfs[i]->bar_state.aperture_size, 0x100000, "VF BAR size");
- }
-
- /* Add WPR for each VF */
- for (int i = 1; i <= 4; i++) {
- int ret = mock_vf_wpr_add(vfs[i], vfs[i]->pt_base, vfs[i]->pt_size, 3);
- TEST_ASSERT_EQ(ret, 0, "VF WPR add in loop");
- }
-
- /* Simulate RPC calls for each VF */
- for (int i = 1; i <= 4; i++) {
- struct gsp_rpc_response resp;
- size_t resp_size = sizeof(resp);
- struct gsp_alloc_payload payload = {
- .size = cpu_to_le64(0x100000),
- .type = cpu_to_le32(GSP_MEM_VRAM),
- .vf_id = cpu_to_le32(i),
- };
- int ret = mock_rpc_send(rpc, GSP_RPC_ALLOC, &payload, sizeof(payload), &resp, &resp_size);
- TEST_ASSERT_EQ(ret, 0, "VF RPC alloc");
- TEST_ASSERT_EQ(resp.status, 0, "VF RPC response OK");
- }
-
- /* Cleanup */
- for (int i = 1; i <= 4; i++) {
- mock_vf_destroy(vfs[i]);
- }
- mock_rpc_destroy(rpc);
- mock_hw_destroy(hw);
-
- return TEST_PASS;
-}
-
-static int test_migration_progress_tracking(void)
-{
- struct {
- u64 pages_transferred;
- u64 bytes_transferred;
- u64 dirty_pages;
- u64 *page_list;
- u32 page_count;
- } progress = {0};
-
- progress.page_count = 1000;
- progress.page_list = kcalloc(progress.page_count, sizeof(u64), GFP_KERNEL);
- TEST_ASSERT(progress.page_list != NULL, "Progress page list alloc");
-
- /* Simulate transfer loop */
- for (int iter = 0; iter < 10; iter++) {
- progress.pages_transferred += 100;
- progress.bytes_transferred += 100 * 4096;
- progress.dirty_pages = 50 - (iter * 5);
-
- TEST_ASSERT(progress.pages_transferred <= 1000, "Pages not exceeded");
- TEST_ASSERT(progress.bytes_transferred <= 1000 * 4096, "Bytes not exceeded");
- }
-
- TEST_ASSERT_EQ(progress.pages_transferred, 1000, "Final pages");
- TEST_ASSERT_EQ(progress.bytes_transferred, 1000 * 4096, "Final bytes");
- TEST_ASSERT_EQ(progress.dirty_pages, 0, "Final dirty pages");
-
- kfree(progress.page_list);
- return TEST_PASS;
-}
-
-static int test_bar_state_machine(void)
-{
- struct {
- u64 aperture_offset;
- u64 aperture_size;
- bool force_access;
- u32 force_vf;
- } bar_state = {0};
-
- /* Initial state */
- bar_state.aperture_offset = 0x10000000;
- bar_state.aperture_size = 0x100000;
- TEST_ASSERT_EQ(bar_state.aperture_offset, 0x10000000, "Initial aperture offset");
- TEST_ASSERT(!bar_state.force_access, "Force access initially false");
-
- /* Enable force access */
- bar_state.force_access = true;
- bar_state.force_vf = 1;
- TEST_ASSERT(bar_state.force_access, "Force access enabled");
- TEST_ASSERT_EQ(bar_state.force_vf, 1, "Force VF set");
-
- /* Disable force access */
- bar_state.force_access = false;
- bar_state.force_vf = 0;
- TEST_ASSERT(!bar_state.force_access, "Force access disabled");
- TEST_ASSERT_EQ(bar_state.force_vf, 0, "Force VF cleared");
-
- return TEST_PASS;
-}
-
-static int test_concurrent_vf_operations(void)
-{
- struct mock_vf *vf1 = mock_vf_create(1, 0x10000000, 0x100000, 0x20000000, 0x100000, 0x30000000, 0x10000);
- struct mock_vf *vf2 = mock_vf_create(2, 0x20000000, 0x100000, 0x40000000, 0x100000, 0x60000000, 0x10000);
- struct mock_rpc_client *rpc = mock_rpc_create();
-
- TEST_ASSERT(vf1 && vf2 && rpc, "Create two VFs and RPC");
-
- /* Simulate concurrent operations */
- struct gsp_rpc_response resp;
- size_t resp_size = sizeof(resp);
-
- /* VF1 alloc */
- struct gsp_alloc_payload payload1 = {
- .size = cpu_to_le64(0x100000),
- .type = cpu_to_le32(GSP_MEM_VRAM),
- .vf_id = cpu_to_le32(1),
- };
- int ret = mock_rpc_send(rpc, GSP_RPC_ALLOC, &payload1, sizeof(payload1), &resp, &resp_size);
- TEST_ASSERT_EQ(ret, 0, "VF1 alloc");
- TEST_ASSERT_EQ(resp.status, 0, "VF1 alloc response");
-
- /* VF2 alloc */
- struct gsp_alloc_payload payload2 = {
- .size = cpu_to_le64(0x200000),
- .type = cpu_to_le32(GSP_MEM_VRAM),
- .vf_id = cpu_to_le32(2),
- };
- ret = mock_rpc_send(rpc, GSP_RPC_ALLOC, &payload2, sizeof(payload2), &resp, &resp_size);
- TEST_ASSERT_EQ(ret, 0, "VF2 alloc");
- TEST_ASSERT_EQ(resp.status, 0, "VF2 alloc response");
-
- /* VF1 pin */
- struct gsp_pin_payload pin_payload = {
- .handle = cpu_to_le64(0x1000),
- .vf_id = cpu_to_le32(1),
- };
- ret = mock_rpc_send(rpc, GSP_RPC_PIN, &pin_payload, sizeof(pin_payload), &resp, &resp_size);
- TEST_ASSERT_EQ(ret, 0, "VF1 pin");
-
- /* VF2 BAR trap */
- struct gsp_bar_trap_payload bar_payload = {
- .vf_id = cpu_to_le32(2),
- .bar_index = cpu_to_le32(1),
- };
- ret = mock_rpc_send(rpc, GSP_RPC_BAR_TRAP, &bar_payload, sizeof(bar_payload), &resp, &resp_size);
- TEST_ASSERT_EQ(ret, 0, "VF2 BAR trap");
-
- /* Verify sequence numbers */
- TEST_ASSERT_EQ(resp.sequence, 4, "Sequence number 4");
-
- mock_vf_destroy(vf1);
- mock_vf_destroy(vf2);
- mock_rpc_destroy(rpc);
-
- return TEST_PASS;
-}
-
-/* ============================================================
- * Module Init/Exit
- * ============================================================ */
-
-static int __init gsp_mock_test_init(void)
-{
- pr_info("========================================\n");
- pr_info("GSP vGPU-IO Mock Driver Test Suite\n");
- pr_info("========================================\n");
-
- test_mock_hardware();
- test_mock_vf_lifecycle();
- test_mock_vf_wpr();
- test_mock_rpc_client();
- test_driver_vf_creation_logic();
- test_migration_progress_tracking();
- test_bar_state_machine();
- test_concurrent_vf_operations();
-
- pr_info("========================================\n");
- pr_info("Mock Test Results: %d total, %d passed, %d failed\n",
- test_count, pass_count, fail_count);
- pr_info("========================================\n");
-
- if (fail_count > 0) {
- pr_err("MOCK TEST SUITE FAILED\n");
- return -EINVAL;
- }
-
- pr_info("MOCK TEST SUITE PASSED\n");
- return 0;
-}
-
-static void __exit gsp_mock_test_exit(void)
-{
- pr_info("GSP vGPU-IO Mock Test Suite Exited\n");
-}
-
-module_init(gsp_mock_test_init);
-module_exit(gsp_mock_test_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Open-IOV Project");
-MODULE_DESCRIPTION("GSP vGPU-IO Mock Driver Test");
-MODULE_VERSION("1.0"); \ No newline at end of file
diff --git a/legacy-driver-guest/migration/gsp_migration.c b/legacy-driver-guest/migration/gsp_migration.c
deleted file mode 100644
index 52d1931..0000000
--- a/legacy-driver-guest/migration/gsp_migration.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * GSP vGPU-IO Driver - Live Migration
- */
-
-#include "gsp_core.h"
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/kthread.h>
-#include <linux/delay.h>
-
-/* Forward declarations */
-static int gsp_migration_prepare(struct gsp_migration *mig);
-static int gsp_migration_transfer_iter(struct gsp_migration *mig);
-static int gsp_migration_commit(struct gsp_migration *mig);
-static void gsp_migration_cleanup(struct gsp_migration *mig);
-
-/* Migration Thread */
-static int gsp_migration_thread(void *data)
-{
- struct gsp_migration *mig = data;
- int ret = 0;
-
- while (!kthread_should_stop() && !mig->cancelled) {
- mutex_lock(&mig->lock);
-
- switch (mig->state) {
- case GSP_MIG_S_PREPARE:
- ret = gsp_migration_prepare(mig);
- if (!ret)
- mig->state = GSP_MIG_S_TRANSFER;
- else
- mig->state = GSP_MIG_S_FAILED;
- break;
-
- case GSP_MIG_S_TRANSFER:
- ret = gsp_migration_transfer_iter(mig);
- if (ret > 0) { /* Transfer complete */
- mig->state = GSP_MIG_S_COMMIT;
- } else if (ret < 0) {
- mig->state = GSP_MIG_S_FAILED;
- }
- break;
-
- case GSP_MIG_S_COMMIT:
- ret = gsp_migration_commit(mig);
- if (!ret)
- mig->state = GSP_MIG_S_CLEANUP;
- else
- mig->state = GSP_MIG_S_FAILED;
- break;
-
- case GSP_MIG_S_CLEANUP:
- gsp_migration_cleanup(mig);
- mig->state = GSP_MIG_S_COMPLETED;
- complete(&mig->comp);
- mutex_unlock(&mig->lock);
- return 0;
-
- case GSP_MIG_S_FAILED:
- mig->error = ret;
- complete(&mig->comp);
- mutex_unlock(&mig->lock);
- return ret;
-
- default:
- break;
- }
-
- mutex_unlock(&mig->lock);
-
- if (mig->state == GSP_MIG_S_TRANSFER)
- msleep(10); /* Throttle transfer iterations */
- }
-
- return 0;
-}
-
-/* Migration Query */
-static int gsp_migration_query(struct gsp_vf *vf, bool *migratable)
-{
- struct gsp_migrate_payload payload = {
- .phase = GSP_MIG_QUERY,
- .subcmd = 0,
- .src_vf = vf->id,
- .dst_vf = 0,
- };
- struct gsp_subcmd_desc desc;
- size_t desc_size = sizeof(desc);
- int ret;
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_MIGRATE,
- &payload, sizeof(payload), &desc, &desc_size);
- if (ret)
- return ret;
-
- *migratable = (desc.subcmd_id != 0);
- return 0;
-}
-
-/* Phase 1: Prepare */
-static int gsp_migration_prepare(struct gsp_migration *mig)
-{
- struct gsp_vf *vf = mig->vf;
- struct gsp_migrate_payload payload = {0};
- struct gsp_subcmd_desc desc;
- size_t desc_size = sizeof(desc);
- int ret;
-
- /* Quiesce VF (subcmd 3 -> returns ID 0x10) */
- payload.phase = GSP_MIG_PREPARE;
- payload.subcmd = 3;
- payload.src_vf = vf->id;
- payload.dst_vf = mig->dst_vf;
- payload.flags = mig->flags;
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_MIGRATE,
- &payload, sizeof(payload), &desc, &desc_size);
- if (ret)
- return ret;
-
- mig->token = desc.subcmd_id;
-
- /* Snapshot BAR state */
- ret = gsp_migration_bar_save(vf, mig->bar_state.buf, &mig->bar_state.size);
- if (ret)
- return ret;
-
- /* Snapshot WPR regions */
- /* TODO: WPR snapshot via migration RPC */
-
- dev_info(vf->gsp->dev, "VF %u: Migration prepare done, token=0x%llx\n",
- vf->id, mig->token);
-
- return 0;
-}
-
-/* Phase 2: Transfer (Iterative) */
-static int gsp_migration_transfer_iter(struct gsp_migration *mig)
-{
- struct gsp_vf *vf = mig->vf;
- struct gsp_migrate_payload payload = {0};
- struct gsp_subcmd_desc desc;
- size_t desc_size = sizeof(desc);
- int ret;
-
- if (!mig->progress.page_list || mig->progress.page_count == 0)
- return 1; /* Nothing to transfer */
-
- payload.phase = GSP_MIG_TRANSFER;
- payload.subcmd = 0;
- payload.src_vf = vf->id;
- payload.dst_vf = mig->dst_vf;
- payload.data_ptr = (uint64_t)mig->progress.page_list;
- payload.data_size = mig->progress.page_count * sizeof(uint64_t);
- payload.token = mig->token;
- payload.flags = mig->flags;
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_MIGRATE,
- &payload, sizeof(payload), &desc, &desc_size);
- if (ret)
- return ret;
-
- /* Update progress from response */
- /* Note: Actual progress parsing depends on firmware response format */
- mig->progress.pages_transferred += 100; /* Placeholder */
- mig->progress.bytes_transferred += 100 * 4096;
-
- /* Check for dirty pages */
- if (mig->progress.dirty_pages > 0 && !(mig->flags & GSP_MIG_POSTCOPY))
- return 0; /* Continue iterating */
-
- return 1; /* Transfer complete */
-}
-
-/* Phase 3: Commit */
-static int gsp_migration_commit(struct gsp_migration *mig)
-{
- struct gsp_vf *vf = mig->vf;
- struct gsp_migrate_payload payload = {0};
- struct gsp_subcmd_desc desc;
- size_t desc_size = sizeof(desc);
- int ret;
-
- /* Final dirty page transfer */
- if (mig->progress.dirty_pages > 0) {
- payload.phase = GSP_MIG_TRANSFER;
- payload.subcmd = 11; /* Dirty tracking */
- payload.src_vf = vf->id;
- payload.dst_vf = mig->dst_vf;
- payload.token = mig->token;
- payload.flags = GSP_MIG_POSTCOPY;
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_MIGRATE,
- &payload, sizeof(payload), &desc, &desc_size);
- if (ret)
- return ret;
- }
-
- /* Commit (subcmd 12) */
- payload.phase = GSP_MIG_COMMIT;
- payload.subcmd = 12;
- payload.src_vf = vf->id;
- payload.dst_vf = mig->dst_vf;
- payload.token = mig->token;
- payload.flags = mig->flags | GSP_MIG_VERIFY;
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_MIGRATE,
- &payload, sizeof(payload), &desc, &desc_size);
- if (ret)
- return ret;
-
- /* Restore BAR on destination */
- ret = gsp_migration_bar_restore(vf, mig->bar_state.buf, mig->bar_state.size);
- if (ret)
- return ret;
-
- /* Restore WPR on destination */
- /* TODO: WPR restore */
-
- dev_info(vf->gsp->dev, "VF %u: Migration commit done\n", vf->id);
-
- return 0;
-}
-
-/* Phase 4: Cleanup */
-static void gsp_migration_cleanup(struct gsp_migration *mig)
-{
- struct gsp_vf *vf = mig->vf;
-
- /* Free page list */
- kfree(mig->progress.page_list);
- mig->progress.page_list = NULL;
- mig->progress.page_count = 0;
-
- /* Free BAR state buffer */
- kfree(mig->bar_state.buf);
- mig->bar_state.buf = NULL;
- mig->bar_state.size = 0;
-
- dev_info(vf->gsp->dev, "VF %u: Migration cleanup done\n", vf->id);
-}
-
-/* Public Migration API */
-int gsp_migration_start(struct gsp_vf *vf, uint64_t dst_vf)
-{
- struct gsp_migration *mig;
- bool migratable;
- int ret;
-
- if (vf->migration)
- return -EBUSY;
-
- /* Query migratability */
- ret = gsp_migration_query(vf, &migratable);
- if (ret || !migratable)
- return ret ? ret : -EINVAL;
-
- mig = kzalloc(sizeof(*mig), GFP_KERNEL);
- if (!mig)
- return -ENOMEM;
-
- mig->vf = vf;
- mig->dst_vf = dst_vf;
- mig->flags = GSP_MIG_LIVE | GSP_MIG_VERIFY;
- mig->state = GSP_MIG_S_PREPARE;
- mutex_init(&mig->lock);
- init_completion(&mig->comp);
-
- /* Allocate page list (placeholder) */
- mig->progress.page_count = vf->pt_size / 4096;
- mig->progress.page_list = kcalloc(mig->progress.page_count, sizeof(uint64_t), GFP_KERNEL);
- if (!mig->progress.page_list) {
- kfree(mig);
- return -ENOMEM;
- }
-
- /* Allocate BAR state buffer */
- mig->bar_state.buf = kmalloc(65536, GFP_KERNEL); /* 64KB max */
- if (!mig->bar_state.buf) {
- kfree(mig->progress.page_list);
- kfree(mig);
- return -ENOMEM;
- }
-
- vf->migration = mig;
-
- /* Start migration thread */
- mig->thread = kthread_run(gsp_migration_thread, mig, "gsp-mig-%u", vf->id);
- if (IS_ERR(mig->thread)) {
- ret = PTR_ERR(mig->thread);
- mig->thread = NULL;
- goto err_free;
- }
-
- return 0;
-
-err_free:
- kfree(mig->progress.page_list);
- kfree(mig->bar_state.buf);
- kfree(mig);
- vf->migration = NULL;
- return ret;
-}
-
-void gsp_migration_cancel(struct gsp_migration *mig)
-{
- if (!mig)
- return;
-
- mutex_lock(&mig->lock);
- mig->cancelled = true;
- mig->state = GSP_MIG_S_FAILED;
- mutex_unlock(&mig->lock);
-
- if (mig->thread)
- kthread_stop(mig->thread);
-
- wait_for_completion(&mig->comp);
-
- gsp_migration_cleanup(mig);
- kfree(mig);
-}
-
-int gsp_migration_status(struct gsp_migration *mig)
-{
- if (!mig)
- return -EINVAL;
-
- mutex_lock(&mig->lock);
- int state = mig->state;
- int error = mig->error;
- mutex_unlock(&mig->lock);
-
- if (state == GSP_MIG_S_FAILED)
- return error;
-
- return state;
-} \ No newline at end of file
diff --git a/legacy-driver-guest/rpc/gsp_rpc.c b/legacy-driver-guest/rpc/gsp_rpc.c
deleted file mode 100644
index 6bdcdb2..0000000
--- a/legacy-driver-guest/rpc/gsp_rpc.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * GSP vGPU-IO Driver - RPC Client Implementation
- */
-
-#include "gsp_core.h"
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-
-/* Ring Buffer Operations */
-static int gsp_ring_init(struct gsp_msg_ring *ring, void *base, size_t size)
-{
- ring->base = base;
- ring->size = size;
- ring->head = 0;
- ring->tail = 0;
- spin_lock_init(&ring->lock);
- return 0;
-}
-
-static bool gsp_ring_empty(struct gsp_msg_ring *ring)
-{
- return ring->head == ring->tail;
-}
-
-static bool gsp_ring_full(struct gsp_msg_ring *ring)
-{
- return ((ring->head + 1) % (ring->size / GSP_MSG_MAX_SIZE)) == ring->tail;
-}
-
-static int gsp_ring_write(struct gsp_msg_ring *ring, struct gsp_rpc_message *msg, size_t len)
-{
- unsigned long flags;
- uint32_t next_head;
- void *dst;
-
- if (len > GSP_MSG_MAX_SIZE)
- return -EINVAL;
-
- spin_lock_irqsave(&ring->lock, flags);
-
- if (gsp_ring_full(ring)) {
- spin_unlock_irqrestore(&ring->lock, flags);
- return -EBUSY;
- }
-
- dst = ring->base + (ring->head * GSP_MSG_MAX_SIZE);
- memcpy(dst, msg, len);
-
- next_head = (ring->head + 1) % (ring->size / GSP_MSG_MAX_SIZE);
- ring->head = next_head;
-
- spin_unlock_irqrestore(&ring->lock, flags);
- return 0;
-}
-
-static int gsp_ring_read(struct gsp_msg_ring *ring, struct gsp_rpc_message *msg)
-{
- unsigned long flags;
- void *src;
-
- spin_lock_irqsave(&ring->lock, flags);
-
- if (gsp_ring_empty(ring)) {
- spin_unlock_irqrestore(&ring->lock, flags);
- return 0;
- }
-
- src = ring->base + (ring->tail * GSP_MSG_MAX_SIZE);
- memcpy(msg, src, GSP_MSG_MAX_SIZE);
-
- ring->tail = (ring->tail + 1) % (ring->size / GSP_MSG_MAX_SIZE);
-
- spin_unlock_irqrestore(&ring->lock, flags);
- return 1;
-}
-
-/* RPC Client Initialization */
-struct gsp_rpc_client *gsp_rpc_client_init(struct gsp_device *gsp)
-{
- struct gsp_rpc_client *rpc;
- void *ring_mem;
-
- rpc = kzalloc(sizeof(*rpc), GFP_KERNEL);
- if (!rpc)
- return ERR_PTR(-ENOMEM);
-
- rpc->gsp = gsp;
- mutex_init(&rpc->lock);
- atomic_set(&rpc->seq, 0);
- init_waitqueue_head(&rpc->wq);
-
- /* Allocate shared memory for message rings (2 pages each) */
- ring_mem = dma_alloc_coherent(gsp->dev, 8 * PAGE_SIZE,
- &rpc->tx_ring_dma, GFP_KERNEL);
- if (!ring_mem) {
- kfree(rpc);
- return ERR_PTR(-ENOMEM);
- }
-
- rpc->tx_ring = kzalloc(sizeof(*rpc->tx_ring), GFP_KERNEL);
- rpc->rx_ring = kzalloc(sizeof(*rpc->rx_ring), GFP_KERNEL);
- if (!rpc->tx_ring || !rpc->rx_ring) {
- dma_free_coherent(gsp->dev, 8 * PAGE_SIZE, ring_mem, rpc->tx_ring_dma);
- kfree(rpc->tx_ring);
- kfree(rpc->rx_ring);
- kfree(rpc);
- return ERR_PTR(-ENOMEM);
- }
-
- gsp_ring_init(rpc->tx_ring, ring_mem, 4 * PAGE_SIZE);
- gsp_ring_init(rpc->rx_ring, ring_mem + 4 * PAGE_SIZE, 4 * PAGE_SIZE);
-
- /* Map rings to GSP via queue head registers (BAR0) */
- writel(rpc->tx_ring_dma, gsp->bar0 + GSP_BAR0_QUEUE_HEAD(0));
- writel(rpc->tx_ring_dma >> 32, gsp->bar0 + GSP_BAR0_QUEUE_HEAD(0) + 4);
- writel(rpc->rx_ring_dma, gsp->bar0 + GSP_BAR0_QUEUE_HEAD(1));
- writel(rpc->rx_ring_dma >> 32, gsp->bar0 + GSP_BAR0_QUEUE_HEAD(1) + 4);
-
- /* Allocate response buffers */
- for (int i = 0; i < GSP_MAX_PENDING; i++) {
- rpc->resp_buf[i] = kzalloc(GSP_MSG_MAX_SIZE, GFP_KERNEL);
- if (!rpc->resp_buf[i]) {
- /* Cleanup on failure */
- for (int j = 0; j < i; j++)
- kfree(rpc->resp_buf[j]);
- gsp_rpc_client_fini(rpc);
- return ERR_PTR(-ENOMEM);
- }
- }
-
- dev_info(gsp->dev, "RPC client initialized\n");
- return rpc;
-}
-
-void gsp_rpc_client_fini(struct gsp_rpc_client *rpc)
-{
- if (!rpc)
- return;
-
- for (int i = 0; i < GSP_MAX_PENDING; i++)
- kfree(rpc->resp_buf[i]);
-
- if (rpc->tx_ring) {
- dma_free_coherent(rpc->gsp->dev, 8 * PAGE_SIZE,
- rpc->tx_ring->base, rpc->tx_ring_dma);
- kfree(rpc->tx_ring);
- }
- kfree(rpc->rx_ring);
- kfree(rpc);
-}
-
-/* Synchronous RPC Send */
-int gsp_rpc_send_sync(struct gsp_rpc_client *rpc,
- enum gsp_rpc_type type,
- void *payload, size_t payload_size,
- void *response, size_t *response_size)
-{
- struct gsp_rpc_message msg = {0};
- struct completion done;
- uint32_t seq;
- int ret;
-
- if (payload_size > GSP_MSG_MAX_SIZE - sizeof(struct gsp_rpc_header))
- return -EINVAL;
-
- seq = atomic_inc_return(&rpc->seq);
- init_completion(&done);
-
- msg.hdr.magic = 0x47535052; /* "GSPR" */
- msg.hdr.version = 1;
- msg.hdr.rpc_type = type;
- msg.hdr.sequence = seq;
- msg.hdr.timestamp_ns = ktime_get_ns();
- msg.hdr.payload_size = payload_size;
- msg.hdr.flags = GSP_MSG_SYNC;
- msg.hdr.correlation_id = seq;
-
- if (payload && payload_size > 0)
- memcpy(msg.payload, payload, payload_size);
-
- mutex_lock(&rpc->lock);
-
- rpc->pending[seq % GSP_MAX_PENDING] = &done;
-
- ret = gsp_ring_write(rpc->tx_ring, &msg, GSP_MSG_MAX_SIZE);
- if (ret) {
- rpc->pending[seq % GSP_MAX_PENDING] = NULL;
- mutex_unlock(&rpc->lock);
- return ret;
- }
-
- /* Ring doorbell - write to queue head to signal GSP */
- writel(1, rpc->gsp->bar0 + GSP_BAR0_QUEUE_HEAD(0));
-
- mutex_unlock(&rpc->lock);
-
- /* Wait for completion (5 second timeout) */
- if (!wait_for_completion_timeout(&done, msecs_to_jiffies(5000))) {
- mutex_lock(&rpc->lock);
- rpc->pending[seq % GSP_MAX_PENDING] = NULL;
- mutex_unlock(&rpc->lock);
- atomic64_inc(&rpc->gsp->rpc_errors);
- return -ETIMEDOUT;
- }
-
- /* Get response */
- struct gsp_rpc_response *resp = rpc->resp_buf[seq % GSP_MAX_PENDING];
-
- atomic64_inc(&rpc->gsp->rpc_total);
-
- if (resp->status != 0) {
- atomic64_inc(&rpc->gsp->rpc_errors);
- return gsp_errno_to_errno(resp->status);
- }
-
- if (response && response_size) {
- size_t copy_size = min(*response_size, (size_t)resp->payload_size);
- memcpy(response, resp->payload, copy_size);
- *response_size = copy_size;
- }
-
- return 0;
-}
-
-/* Async RPC Send */
-int gsp_rpc_send_async(struct gsp_rpc_client *rpc,
- enum gsp_rpc_type type,
- void *payload, size_t payload_size,
- void (*callback)(struct gsp_rpc_client *,
- struct gsp_rpc_response *,
- void *),
- void *ctx)
-{
- struct gsp_rpc_message msg = {0};
- uint32_t seq;
- int ret;
-
- if (payload_size > GSP_MSG_MAX_SIZE - sizeof(struct gsp_rpc_header))
- return -EINVAL;
-
- seq = atomic_inc_return(&rpc->seq);
-
- msg.hdr.magic = 0x47535052;
- msg.hdr.version = 1;
- msg.hdr.rpc_type = type;
- msg.hdr.sequence = seq;
- msg.hdr.timestamp_ns = ktime_get_ns();
- msg.hdr.payload_size = payload_size;
- msg.hdr.flags = GSP_MSG_ASYNC;
- msg.hdr.correlation_id = (uint64_t)callback | ((uint64_t)ctx << 32);
-
- if (payload && payload_size > 0)
- memcpy(msg.payload, payload, payload_size);
-
- mutex_lock(&rpc->lock);
- ret = gsp_ring_write(rpc->tx_ring, &msg, GSP_MSG_MAX_SIZE);
- if (!ret)
- writel(1, rpc->gsp->bar0 + GSP_BAR0_QUEUE_HEAD(0));
- mutex_unlock(&rpc->lock);
-
- return ret;
-}
-
-/* ISR - Handle Completions */
-irqreturn_t gsp_isr(int irq, void *data)
-{
- struct gsp_device *gsp = data;
- struct gsp_rpc_message msg;
- int handled = 0;
-
- while (gsp_ring_read(gsp->rpc->rx_ring, &msg)) {
- handled = 1;
-
- if (msg.hdr.flags & GSP_MSG_SYNC) {
- uint32_t seq = msg.hdr.sequence;
- struct completion *done = gsp->rpc->pending[seq % GSP_MAX_PENDING];
- struct gsp_rpc_response *resp = gsp->rpc->resp_buf[seq % GSP_MAX_PENDING];
-
- if (done && resp) {
- resp->status = ((struct gsp_rpc_response *)msg.payload)->status;
- resp->payload_size = msg.hdr.payload_size;
- memcpy(resp->payload, ((struct gsp_rpc_response *)msg.payload)->payload,
- msg.hdr.payload_size);
- complete(done);
- }
- gsp->rpc->pending[seq % GSP_MAX_PENDING] = NULL;
- } else {
- /* Async notification - handle via callback */
- gsp_handle_notification(gsp, &msg);
- }
- }
-
- return handled ? IRQ_HANDLED : IRQ_NONE;
-}
-
-/* Notification Handler */
-void gsp_handle_notification(struct gsp_device *gsp, struct gsp_rpc_message *msg)
-{
- switch (msg->hdr.rpc_type) {
- case GSP_RPC_NOTIFY:
- /* Handle VF notifications (WPR, migration, etc.) */
- break;
- case GSP_RPC_BAR_TRAP:
- atomic64_inc(&gsp->bar_traps);
- break;
- default:
- dev_dbg(gsp->dev, "Unhandled notification type 0x%02x\n", msg->hdr.rpc_type);
- }
-}
-
-/* Error Code Translation */
-int gsp_errno_to_errno(int gsp_err)
-{
- switch (gsp_err) {
- case GSP_OK: return 0;
- case GSP_EPERM: return -EPERM;
- case GSP_ENOENT: return -ENOENT;
- case GSP_EINVAL: return -EINVAL;
- case GSP_ENODEV: return -ENODEV;
- case GSP_ENOMEM: return -ENOMEM;
- case GSP_EBUSY: return -EBUSY;
- case GSP_ENOSPC: return -ENOSPC;
- case GSP_ETIMEDOUT: return -ETIMEDOUT;
- case GSP_EOVERFLOW: return -EOVERFLOW;
- case GSP_EDEV: return -EIO;
- default: return -EIO;
- }
-} \ No newline at end of file
diff --git a/legacy-driver-guest/vf/gsp_vf.c b/legacy-driver-guest/vf/gsp_vf.c
deleted file mode 100644
index 951c84d..0000000
--- a/legacy-driver-guest/vf/gsp_vf.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * GSP vGPU-IO Driver - VF Management
- */
-
-#include "gsp_core.h"
-#include <linux/slab.h>
-#include <linux/idr.h>
-#include <linux/list.h>
-
-/* VF Reference Counting */
-static void gsp_vf_release(struct kref *ref)
-{
- struct gsp_vf *vf = container_of(ref, struct gsp_vf, ref);
- kfree(vf);
-}
-
-struct gsp_vf *gsp_vf_get(struct gsp_device *gsp, uint32_t id)
-{
- struct gsp_vf *vf;
-
- mutex_lock(&gsp->vf_lock);
- vf = idr_find(&gsp->vf_idr, id);
- if (vf && vf->active)
- kref_get(&vf->ref);
- else
- vf = NULL;
- mutex_unlock(&gsp->vf_lock);
-
- return vf;
-}
-
-void gsp_vf_put(struct gsp_vf *vf)
-{
- if (vf)
- kref_put(&vf->ref, gsp_vf_release);
-}
-
-/* VF Creation */
-int gsp_vf_create(struct gsp_device *gsp, const struct gsp_vf_config *config)
-{
- struct gsp_vf *vf;
- int ret, id;
-
- if (!config || config->id == 0 || config->id > gsp->max_vfs)
- return -EINVAL;
-
- vf = kzalloc(sizeof(*vf), GFP_KERNEL);
- if (!vf)
- return -ENOMEM;
-
- vf->gsp = gsp;
- vf->id = config->id;
- kref_init(&vf->ref);
- mutex_init(&vf->lock);
- mutex_init(&vf->wpr_lock);
- INIT_LIST_HEAD(&vf->wpr_list);
- INIT_LIST_HEAD(&vf->list);
- atomic_set(&vf->refcount, 1);
-
- /* Copy configuration */
- vf->bar1_offset = config->bar1_offset;
- vf->bar1_size = config->bar1_size;
- vf->pt_base = config->pt_base;
- vf->pt_size = config->pt_size;
- vf->cmd_base = config->cmd_base;
- vf->cmd_size = config->cmd_size;
-
- /* Allocate VF ID */
- mutex_lock(&gsp->vf_lock);
- id = idr_alloc(&gsp->vf_idr, vf, config->id, config->id + 1, GFP_KERNEL);
- if (id < 0) {
- ret = id;
- mutex_unlock(&gsp->vf_lock);
- goto err_free;
- }
-
- list_add(&vf->list, &gsp->vf_list);
- vf->active = true;
- vf->state = GSP_VF_ACTIVE;
- mutex_unlock(&gsp->vf_lock);
-
- /* Initialize subsystems */
- ret = gsp_vf_wpr_init(vf);
- if (ret) {
- dev_err(gsp->dev, "VF %u: WPR init failed: %d\n", vf->id, ret);
- goto err_wpr;
- }
-
- ret = gsp_vf_bar_init(vf);
- if (ret) {
- dev_err(gsp->dev, "VF %u: BAR init failed: %d\n", vf->id, ret);
- goto err_bar;
- }
-
- dev_info(gsp->dev, "VF %u created (bar1=0x%llx-0x%llx, pt=0x%llx-0x%llx)\n",
- vf->id, vf->bar1_offset, vf->bar1_offset + vf->bar1_size,
- vf->pt_base, vf->pt_base + vf->pt_size);
-
- return 0;
-
-err_bar:
- gsp_vf_wpr_fini(vf);
-err_wpr:
- mutex_lock(&gsp->vf_lock);
- list_del(&vf->list);
- idr_remove(&gsp->vf_idr, vf->id);
- vf->active = false;
- mutex_unlock(&gsp->vf_lock);
-err_free:
- kfree(vf);
- return ret;
-}
-
-/* VF Destruction */
-void gsp_vf_destroy(struct gsp_vf *vf)
-{
- struct gsp_device *gsp = vf->gsp;
- uint32_t id = vf->id;
-
- if (!vf->active)
- return;
-
- /* Cancel any ongoing migration */
- mutex_lock(&vf->lock);
- if (vf->migration) {
- gsp_migration_cancel(vf->migration);
- vf->migration = NULL;
- }
- vf->active = false;
- vf->state = GSP_VF_DESTROYING;
- mutex_unlock(&vf->lock);
-
- /* Remove from device lists */
- mutex_lock(&gsp->vf_lock);
- list_del(&vf->list);
- idr_remove(&gsp->vf_idr, id);
- mutex_unlock(&gsp->vf_lock);
-
- /* Cleanup subsystems */
- gsp_vf_bar_fini(vf);
- gsp_vf_wpr_fini(vf);
-
- dev_info(gsp->dev, "VF %u destroyed\n", id);
-
- gsp_vf_put(vf);
-}
-
-/* Memory Allocation */
-int gsp_vf_mem_alloc(struct gsp_vf *vf, uint64_t size, uint32_t flags,
- uint64_t *handle, uint64_t *va)
-{
- struct gsp_alloc_payload payload = {
- .size = size,
- .type = flags & 0x3, /* Low bits: mem type */
- .alignment = 0x1000,
- .va_hint = 0,
- .flags = flags >> 2,
- .pid = current->pid,
- .vf_id = vf->id,
- };
- struct gsp_alloc_response resp;
- size_t resp_size = sizeof(resp);
- int ret;
-
- if (!handle || !va)
- return -EINVAL;
-
- /* In emulation mode, handle locally */
- if (emulation_mode) {
- static uint64_t next_handle = 0x1000;
- static uint64_t next_va = 0x100000000ULL; /* 4GB base */
-
- *handle = next_handle++;
- *va = next_va;
- next_va += (size + 0xFFF) & ~0xFFF; /* Align to 4KB */
-
- dev_dbg(vf->gsp->dev, "VF %u: alloc handle=0x%llx va=0x%llx size=0x%llx (emulation)\n",
- vf->id, *handle, *va, size);
-
- return 0;
- }
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_ALLOC,
- &payload, sizeof(payload),
- &resp, &resp_size);
- if (ret)
- return ret;
-
- *handle = resp.handle;
- *va = resp.va;
-
- dev_dbg(vf->gsp->dev, "VF %u: alloc handle=0x%llx va=0x%llx size=0x%llx\n",
- vf->id, *handle, *va, size);
-
- return 0;
-}
-
-int gsp_vf_mem_free(struct gsp_vf *vf, uint64_t handle)
-{
- /* FREE uses primary dispatcher sub-command */
- struct gsp_subcmd_desc desc;
- size_t desc_size = sizeof(desc);
- int ret;
-
- /* Subcmd for FREE: need to determine which subcmd corresponds to FREE */
- /* For now, use a generic FREE RPC if implemented */
-
- /* Placeholder - actual implementation depends on FREE subcmd mapping */
- dev_dbg(vf->gsp->dev, "VF %u: free handle=0x%llx\n", vf->id, handle);
-
- return 0;
-}
-
-/* Memory Pinning */
-int gsp_vf_mem_pin(struct gsp_vf *vf, uint64_t handle,
- uint64_t offset, uint64_t size,
- uint64_t *dma_addr)
-{
- struct gsp_pin_payload payload = {
- .handle = handle,
- .offset = offset,
- .size = size,
- .vf_id = vf->id,
- .flags = GSP_PIN_READ | GSP_PIN_WRITE,
- };
- struct gsp_pin_response resp;
- size_t resp_size = sizeof(resp);
- int ret;
-
- if (!dma_addr)
- return -EINVAL;
-
- /* In emulation mode, handle locally */
- if (emulation_mode) {
- static uint64_t next_dma = 0x200000000ULL; /* 8GB base */
- *dma_addr = next_dma;
- next_dma += (size + 0xFFF) & ~0xFFF;
-
- dev_dbg(vf->gsp->dev, "VF %u: pin handle=0x%llx offset=0x%llx size=0x%llx -> dma=0x%llx (emulation)\n",
- vf->id, handle, offset, size, *dma_addr);
-
- return 0;
- }
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_PIN,
- &payload, sizeof(payload),
- &resp, &resp_size);
- if (ret)
- return ret;
-
- *dma_addr = resp.dma_addr;
-
- dev_dbg(vf->gsp->dev, "VF %u: pin handle=0x%llx offset=0x%llx size=0x%llx -> dma=0x%llx\n",
- vf->id, handle, offset, size, *dma_addr);
-
- return 0;
-}
-
-int gsp_vf_mem_unpin(struct gsp_vf *vf, uint64_t handle)
-{
- dev_dbg(vf->gsp->dev, "VF %u: unpin handle=0x%llx\n", vf->id, handle);
- return 0;
-}
-
-/* Memory Mapping */
-int gsp_vf_mem_map(struct gsp_vf *vf, uint64_t handle, uint64_t gpu_va,
- uint64_t size, uint32_t prot, uint32_t flags,
- uint64_t offset, uint64_t *mapped_va)
-{
- /* In emulation mode, just return the requested VA */
- if (emulation_mode) {
- if (mapped_va)
- *mapped_va = gpu_va;
-
- dev_dbg(vf->gsp->dev, "VF %u: map handle=0x%llx gpu_va=0x%llx size=0x%llx -> mapped_va=0x%llx (emulation)\n",
- vf->id, handle, gpu_va, size, gpu_va);
-
- return 0;
- }
-
- /* TODO: Implement GSP RPC for MAP */
- dev_dbg(vf->gsp->dev, "VF %u: map handle=0x%llx gpu_va=0x%llx size=0x%llx\n",
- vf->id, handle, gpu_va, size);
-
- if (mapped_va)
- *mapped_va = gpu_va;
-
- return 0;
-}
-
-int gsp_vf_mem_unmap(struct gsp_vf *vf, uint64_t handle, uint64_t gpu_va, uint64_t size)
-{
- dev_dbg(vf->gsp->dev, "VF %u: unmap handle=0x%llx gpu_va=0x%llx size=0x%llx\n",
- vf->id, handle, gpu_va, size);
- return 0;
-}
-
-/* Scheduling */
-int gsp_vf_schedule(struct gsp_vf *vf, uint32_t priority, uint64_t time_slice_ns)
-{
- /* Use primary dispatcher SCHEDULE subcmd or secondary dispatcher */
- dev_dbg(vf->gsp->dev, "VF %u: schedule prio=%u slice=%llu ns\n",
- vf->id, priority, time_slice_ns);
- return 0;
-}
-
-int gsp_vf_yield(struct gsp_vf *vf)
-{
- dev_dbg(vf->gsp->dev, "VF %u: yield\n", vf->id);
- return 0;
-} \ No newline at end of file
diff --git a/legacy-driver-guest/wpr/gsp_wpr.c b/legacy-driver-guest/wpr/gsp_wpr.c
deleted file mode 100644
index 91c5550..0000000
--- a/legacy-driver-guest/wpr/gsp_wpr.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * GSP vGPU-IO Driver - WPR (Write/Read Protect Region) Management
- */
-
-#include "gsp_core.h"
-#include <linux/slab.h>
-#include <linux/list.h>
-
-/* WPR Payload (for RPC) */
-struct gsp_wpr_payload {
- uint32_t vf_id;
- uint32_t op; /* 0=protect_write, 1=protect_read, 2=unprotect */
- uint64_t base;
- uint64_t size;
- uint32_t flags;
- uint64_t timeout_ns;
-} __attribute__((packed));
-
-struct gsp_wpr_response {
- int64_t status;
-} __attribute__((packed));
-
-/* WPR Initialization */
-int gsp_vf_wpr_init(struct gsp_vf *vf)
-{
- INIT_LIST_HEAD(&vf->wpr_list);
- mutex_init(&vf->wpr_lock);
- return 0;
-}
-
-void gsp_vf_wpr_fini(struct gsp_vf *vf)
-{
- struct gsp_wpr_region *rgn, *tmp;
-
- mutex_lock(&vf->wpr_lock);
- list_for_each_entry_safe(rgn, tmp, &vf->wpr_list, list) {
- list_del(&rgn->list);
- kfree(rgn);
- }
- mutex_unlock(&vf->wpr_lock);
-}
-
-/* Protect Region (Write) */
-int gsp_vf_wpr_protect_write(struct gsp_vf *vf, uint64_t base, uint64_t size)
-{
- return gsp_vf_wpr_protect(vf, base, size, GSP_WPR_WRITE);
-}
-
-/* Protect Region (Read) */
-int gsp_vf_wpr_protect_read(struct gsp_vf *vf, uint64_t base, uint64_t size)
-{
- return gsp_vf_wpr_protect(vf, base, size, GSP_WPR_READ);
-}
-
-/* Generic Protect */
-int gsp_vf_wpr_protect(struct gsp_vf *vf, uint64_t base, uint64_t size, uint32_t flags)
-{
- struct gsp_wpr_payload payload = {
- .vf_id = vf->id,
- .op = (flags & GSP_WPR_READ) ? 1 : 0,
- .base = base,
- .size = size,
- .flags = flags,
- .timeout_ns = 10000000, /* 10ms default */
- };
- struct gsp_wpr_response resp;
- size_t resp_size = sizeof(resp);
- struct gsp_wpr_region *rgn;
- int ret;
-
- /* Validate alignment */
- if (base & 0xFFF || size & 0xFFF)
- return -EINVAL;
-
- rgn = kzalloc(sizeof(*rgn), GFP_KERNEL);
- if (!rgn)
- return -ENOMEM;
-
- rgn->base = base;
- rgn->size = size;
- rgn->flags = flags;
- rgn->vf_id = vf->id;
- rgn->timeout_ns = payload.timeout_ns;
-
- /* In emulation mode, handle locally */
- if (emulation_mode) {
- mutex_lock(&vf->wpr_lock);
- list_add(&rgn->list, &vf->wpr_list);
- mutex_unlock(&vf->wpr_lock);
-
- dev_dbg(vf->gsp->dev, "VF %u: WPR protect [0x%llx, 0x%llx) flags=0x%x (emulation)\n",
- vf->id, base, base + size, flags);
-
- return 0;
- }
-
- /* Send to GSP WPR handler (0x04F00B0C/0x04F00C78) */
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_MAP, /* Uses MAP RPC for WPR */
- &payload, sizeof(payload), &resp, &resp_size);
- if (ret) {
- kfree(rgn);
- return ret;
- }
-
- if (resp.status != 0) {
- kfree(rgn);
- return gsp_errno_to_errno(resp.status);
- }
-
- mutex_lock(&vf->wpr_lock);
- list_add(&rgn->list, &vf->wpr_list);
- mutex_unlock(&vf->wpr_lock);
-
- dev_dbg(vf->gsp->dev, "VF %u: WPR protect [0x%llx, 0x%llx) flags=0x%x\n",
- vf->id, base, base + size, flags);
-
- return 0;
-}
-
-/* Unprotect Region */
-int gsp_vf_wpr_unprotect(struct gsp_vf *vf, uint64_t base)
-{
- struct gsp_wpr_payload payload = {
- .vf_id = vf->id,
- .op = 2, /* unprotect */
- .base = base,
- .size = 0,
- .flags = 0,
- };
- struct gsp_wpr_response resp;
- size_t resp_size = sizeof(resp);
- struct gsp_wpr_region *rgn, *tmp;
- bool found = false;
- int ret;
-
- /* In emulation mode, handle locally */
- if (emulation_mode) {
- mutex_lock(&vf->wpr_lock);
- list_for_each_entry_safe(rgn, tmp, &vf->wpr_list, list) {
- if (rgn->base == base) {
- list_del(&rgn->list);
- kfree(rgn);
- found = true;
- break;
- }
- }
- mutex_unlock(&vf->wpr_lock);
-
- dev_dbg(vf->gsp->dev, "VF %u: WPR unprotect 0x%llx (emulation)\n", vf->id, base);
-
- return found ? 0 : -ENOENT;
- }
-
- ret = gsp_rpc_send_sync(vf->gsp->rpc, GSP_RPC_UNMAP, /* Uses UNMAP for WPR */
- &payload, sizeof(payload), &resp, &resp_size);
- if (ret)
- return ret;
-
- if (resp.status != 0)
- return gsp_errno_to_errno(resp.status);
-
- mutex_lock(&vf->wpr_lock);
- list_for_each_entry_safe(rgn, tmp, &vf->wpr_list, list) {
- if (rgn->base == base) {
- list_del(&rgn->list);
- kfree(rgn);
- found = true;
- break;
- }
- }
- mutex_unlock(&vf->wpr_lock);
-
- if (!found)
- return -ENOENT;
-
- dev_dbg(vf->gsp->dev, "VF %u: WPR unprotect 0x%llx\n", vf->id, base);
-
- return 0;
-}
-
-/* Set Timeout */
-int gsp_vf_wpr_set_timeout(struct gsp_vf *vf, uint64_t timeout_ns)
-{
- /* Update timeout for all WPR regions */
- struct gsp_wpr_region *rgn;
-
- mutex_lock(&vf->wpr_lock);
- list_for_each_entry(rgn, &vf->wpr_list, list) {
- rgn->timeout_ns = timeout_ns;
- }
- mutex_unlock(&vf->wpr_lock);
-
- return 0;
-}
-
-/* Register Completion Callback */
-int gsp_vf_wpr_register_callback(struct gsp_vf *vf, enum gsp_wpr_event type,
- void (*cb)(struct gsp_vf *, uint64_t, uint32_t),
- void *ctx)
-{
- struct gsp_wpr_region *rgn;
-
- mutex_lock(&vf->wpr_lock);
- list_for_each_entry(rgn, &vf->wpr_list, list) {
- switch (type) {
- case GSP_WPR_WRITE_COMPLETE:
- case GSP_WPR_WRITE_TIMEOUT:
- rgn->completion_cb = cb;
- break;
- case GSP_WPR_READ_COMPLETE:
- case GSP_WPR_READ_TIMEOUT:
- rgn->timeout_cb = cb;
- break;
- }
- }
- mutex_unlock(&vf->wpr_lock);
-
- return 0;
-}
-
-/* WPR Event Handler (called from notification) */
-void gsp_wpr_handle_event(struct gsp_device *gsp, struct gsp_rpc_message *msg)
-{
- struct gsp_rpc_response *resp = (struct gsp_rpc_response *)msg->payload;
- uint32_t event_type = resp->payload[0];
- uint32_t vf_id = resp->payload[1];
- uint64_t address = *(uint64_t *)&resp->payload[2];
- struct gsp_vf *vf;
- struct gsp_wpr_region *rgn;
-
- vf = gsp_vf_get(gsp, vf_id);
- if (!vf)
- return;
-
- atomic64_inc(&gsp->wpr_events);
-
- mutex_lock(&vf->wpr_lock);
- list_for_each_entry(rgn, &vf->wpr_list, list) {
- if (address >= rgn->base && address < rgn->base + rgn->size) {
- switch (event_type) {
- case GSP_WPR_WRITE_COMPLETE:
- case GSP_WPR_READ_COMPLETE:
- if (rgn->completion_cb)
- rgn->completion_cb(vf, address, event_type);
- break;
- case GSP_WPR_WRITE_TIMEOUT:
- case GSP_WPR_READ_TIMEOUT:
- if (rgn->timeout_cb)
- rgn->timeout_cb(vf, address, event_type);
- break;
- }
- break;
- }
- }
- mutex_unlock(&vf->wpr_lock);
-
- gsp_vf_put(vf);
-}
-
-/* Default Completion Callback */
-void gsp_wpr_default_complete_cb(struct gsp_vf *vf, uint64_t addr, uint32_t type)
-{
- dev_dbg(vf->gsp->dev, "VF %u: WPR %s complete at 0x%llx\n",
- vf->id, type == GSP_WPR_WRITE_COMPLETE ? "write" : "read", addr);
-
- /* If this was a page table write, invalidate TLB */
- if (addr >= vf->pt_base && addr < vf->pt_base + vf->pt_size) {
- /* TODO: TLB invalidate */
- }
-}
-
-/* Default Timeout Callback */
-void gsp_wpr_default_timeout_cb(struct gsp_vf *vf, uint64_t addr, uint32_t type)
-{
- dev_warn(vf->gsp->dev, "VF %u: WPR %s timeout at 0x%llx\n",
- vf->id, type == GSP_WPR_WRITE_TIMEOUT ? "write" : "read", addr);
-
- /* Throttle or reset VF */
- if (type == GSP_WPR_WRITE_TIMEOUT) {
- /* TODO: VF throttle */
- } else {
- /* TODO: VF reset */
- }
-} \ No newline at end of file
diff --git a/patches/nvidia/0001-Build-fixes-and-vGPU-VFIO-interface-integration.patch b/patches/nvidia/0001-Build-fixes-and-vGPU-VFIO-interface-integration.patch
deleted file mode 100644
index 1c7c286..0000000
--- a/patches/nvidia/0001-Build-fixes-and-vGPU-VFIO-interface-integration.patch
+++ /dev/null
@@ -1,484 +0,0 @@
-From 1fe277fb1c48a7ba73fea588102062de281b610a Mon Sep 17 00:00:00 2001
-From: Arthur Hanson Rasmusson <arthur@vgpu.io>
-Date: Mon, 21 Sep 2026 04:42:04 -0400
-Subject: [PATCH] Build fixes and vGPU VFIO interface integration
-
----
- kernel-open/Kbuild | 8 +-
- kernel-open/Makefile | 9 +-
- kernel-open/Module.symvers.open-iov | 92 +++++++++++++++++++
- kernel-open/common/inc/nv-linux.h | 1 +
- .../inc/nv-vgpu-vfio-interface-nvidia.h | 71 ++++++++++++++
- .../common/inc/nv-vgpu-vfio-interface.h | 86 +++++++++++++++++
- kernel-open/nvidia/nv-pci.c | 2 +-
- kernel-open/nvidia/nv.c | 17 +++-
- kernel-open/nvidia/os-interface.c | 6 ++
- src/common/inc/nvUnixVersion.h | 2 +-
- src/common/shared/inc/g_vgpu_chip_flags.h | 1 +
- version.mk | 4 +-
- 12 files changed, 290 insertions(+), 9 deletions(-)
- create mode 100644 kernel-open/Module.symvers.open-iov
- create mode 100644 kernel-open/common/inc/nv-vgpu-vfio-interface-nvidia.h
- create mode 100644 kernel-open/common/inc/nv-vgpu-vfio-interface.h
-
-diff --git a/kernel-open/Kbuild b/kernel-open/Kbuild
-index d1811c6..b56f1c0 100644
---- a/kernel-open/Kbuild
-+++ b/kernel-open/Kbuild
-@@ -79,7 +79,7 @@ ccflags-y += -I$(src)/common/inc
- ccflags-y += -I$(src)
- ccflags-y += -Wall $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-format-extra-args
- ccflags-y += -D__KERNEL__ -DMODULE -DNVRM
--ccflags-y += -DNV_VERSION_STRING=\"610.57.04\"
-+ccflags-y += -DNV_VERSION_STRING=\"570.144\"
-
- # Include and link Tegra out-of-tree modules.
- ifneq ($(wildcard /usr/src/nvidia/nvidia-public),)
-@@ -92,9 +92,11 @@ endif
-
- ifneq ($(SYSSRCNVOOT),)
- ccflags-y += -I$(SYSSRCNVOOT)/include
-- KBUILD_EXTRA_SYMBOLS = $(SYSSRCNVOOT)/Module.symvers
- endif
-
-+# Always include extra symbols from open-iov-vfio.ko for vGPU VFIO interface
-+KBUILD_EXTRA_SYMBOLS := $(abspath $(src)/../../kernel/Module.symvers)
-+
- # Some Android kernels prohibit driver use of filesystem functions like
- # filp_open() and kernel_read(). Disable the NV_FILESYSTEM_ACCESS_AVAILABLE
- # functionality that uses those functions when building for Android.
-@@ -174,6 +176,8 @@ endif
- CC ?= cc
- LD ?= ld
-
-+export VGX_KVM_BUILD := 1
-+
- NV_CONFTEST_SCRIPT := $(src)/conftest.sh
- NV_CONFTEST_HEADER := $(obj)/conftest/headers.h
-
-diff --git a/kernel-open/Makefile b/kernel-open/Makefile
-index 341d55b..ac78628 100644
---- a/kernel-open/Makefile
-+++ b/kernel-open/Makefile
-@@ -94,8 +94,12 @@ else
- $(NV_KERNEL_MODULES))
- INSTALL_MOD_DIR ?= kernel/drivers/video
-
-- NV_VERBOSE ?=
-- SPECTRE_V2_RETPOLINE ?= 0
-+# KBUILD_EXTRA_SYMBOLS for vGPU VFIO interface symbols from open-iov-vfio.ko
-+KBUILD_EXTRA_SYMBOLS := $(abspath $(CURDIR)/../../kernel/Module.symvers)
-+
-+NV_VERBOSE ?=
-+SPECTRE_V2_RETPOLINE ?= 0
-+VGX_KVM_BUILD ?= 1
-
- ifeq ($(NV_VERBOSE),1)
- KBUILD_PARAMS += V=1
-@@ -107,6 +111,7 @@ else
- KBUILD_PARAMS += NV_KERNEL_MODULES="$(NV_KERNEL_MODULES)"
- KBUILD_PARAMS += INSTALL_MOD_DIR="$(INSTALL_MOD_DIR)"
- KBUILD_PARAMS += NV_SPECTRE_V2=$(SPECTRE_V2_RETPOLINE)
-+ KBUILD_PARAMS += KBUILD_EXTRA_SYMBOLS=$(KBUILD_EXTRA_SYMBOLS)
-
- export ORIG_PAHOLE := $(PAHOLE)
-
-diff --git a/kernel-open/Module.symvers.open-iov b/kernel-open/Module.symvers.open-iov
-new file mode 100644
-index 0000000..553549f
---- /dev/null
-+++ b/kernel-open/Module.symvers.open-iov
-@@ -0,0 +1,92 @@
-+0x805e4667 nv_vgpu_register_type_info open-iov-vfio EXPORT_SYMBOL
-+0x2510f9e4 nv_vgpu_find_type_info open-iov-vfio EXPORT_SYMBOL
-+0xb1cd7273 nv_vgpu_create_mdev_types open-iov-vfio EXPORT_SYMBOL
-+0xa3720b3e nv_vgpu_free_type_info open-iov-vfio EXPORT_SYMBOL
-+0x3ba3d107 nvidia_vgpu_vfio_get_ops open-iov-vfio EXPORT_SYMBOL
-+0xc61962f1 nvidia_vgpu_vfio_set_ops open-iov-vfio EXPORT_SYMBOL
-+0x536fe9e2 nv_vgpu_mdev_driver_register open-iov-vfio EXPORT_SYMBOL
-+0xe2db996e nv_vgpu_mdev_driver_unregister open-iov-vfio EXPORT_SYMBOL
-+0x71713730 nv_vgpu_mdev_register_parent open-iov-vfio EXPORT_SYMBOL
-+0xb0486899 nv_vgpu_mdev_unregister_parent open-iov-vfio EXPORT_SYMBOL
-+0xdb194166 nvidia_vgpu_vfio_probe open-iov-vfio EXPORT_SYMBOL
-+0xc34501b8 nvidia_vgpu_vfio_remove open-iov-vfio EXPORT_SYMBOL
-+0x3972fd88 gsp_client_init open-iov-vfio EXPORT_SYMBOL
-+0xaf9978fc gsp_client_fini open-iov-vfio EXPORT_SYMBOL
-+0x0994eed6 gsp_rpc_alloc open-iov-vfio EXPORT_SYMBOL
-+0x01ed1ec0 gsp_rpc_free open-iov-vfio EXPORT_SYMBOL
-+0x014ef707 gsp_rpc_map open-iov-vfio EXPORT_SYMBOL
-+0x577cba23 gsp_rpc_unmap open-iov-vfio EXPORT_SYMBOL
-+0xf55eb4ab gsp_rpc_pin open-iov-vfio EXPORT_SYMBOL
-+0x7f0922ac gsp_rpc_unpin open-iov-vfio EXPORT_SYMBOL
-+0xc7abb90f gsp_rpc_schedule open-iov-vfio EXPORT_SYMBOL
-+0xf64c68e2 gsp_rpc_yield open-iov-vfio EXPORT_SYMBOL
-+0x2111f684 gsp_rpc_bar_trap open-iov-vfio EXPORT_SYMBOL
-+0xd0b1131e gsp_rpc_migrate_save open-iov-vfio EXPORT_SYMBOL
-+0xbd8c881d gsp_rpc_migrate_restore open-iov-vfio EXPORT_SYMBOL
-+0x0f989cd0 gsp_wpr_write_mutex_acquire open-iov-vfio EXPORT_SYMBOL
-+0x03323922 gsp_wpr_write_mutex_release open-iov-vfio EXPORT_SYMBOL
-+0xae7f48d2 gsp_wpr_scratch_mutex_acquire open-iov-vfio EXPORT_SYMBOL
-+0xa2d5ed20 gsp_wpr_scratch_mutex_release open-iov-vfio EXPORT_SYMBOL
-+0x04a15dd5 gsp_rpc_emulation_set open-iov-vfio EXPORT_SYMBOL
-+0x980c5e08 gsp_rpc_emulation_is_enabled open-iov-vfio EXPORT_SYMBOL
-+0xa6751cae gsp_rpc_notify_register open-iov-vfio EXPORT_SYMBOL
-+0x46ab86c5 gsp_rpc_notify_unregister open-iov-vfio EXPORT_SYMBOL
-+0x42fe196a nv_vgpu_gsp_rpc_integration_init open-iov-vfio EXPORT_SYMBOL
-+0x3af2d161 nv_vgpu_gsp_rpc_integration_cleanup open-iov-vfio EXPORT_SYMBOL
-+0xd748c59b nv_vgpu_gsp_rpc_alloc_fw open-iov-vfio EXPORT_SYMBOL
-+0x153fa014 nv_vgpu_gsp_rpc_free_fw open-iov-vfio EXPORT_SYMBOL
-+0x637c076f nv_vgpu_gsp_rpc_map_fw open-iov-vfio EXPORT_SYMBOL
-+0x34f998ca nv_vgpu_gsp_rpc_unmap_fw open-iov-vfio EXPORT_SYMBOL
-+0xeb1110bd nv_vgpu_gsp_rpc_pin_fw open-iov-vfio EXPORT_SYMBOL
-+0xf3037685 nv_vgpu_gsp_rpc_unpin_fw open-iov-vfio EXPORT_SYMBOL
-+0x21d884f8 nv_vgpu_gsp_rpc_schedule_fw open-iov-vfio EXPORT_SYMBOL
-+0xab6ad746 nv_vgpu_gsp_rpc_yield_fw open-iov-vfio EXPORT_SYMBOL
-+0x1c4d1f08 nv_vgpu_gsp_rpc_bar_trap_fw open-iov-vfio EXPORT_SYMBOL
-+0x708f30d4 nv_vgpu_gsp_rpc_migrate_save_fw open-iov-vfio EXPORT_SYMBOL
-+0x8e7872e6 nv_vgpu_gsp_rpc_migrate_restore_fw open-iov-vfio EXPORT_SYMBOL
-+0x2ade3dd6 nv_vgpu_gsp_wpr_write_mutex_acquire open-iov-vfio EXPORT_SYMBOL
-+0x8dff96a4 nv_vgpu_gsp_wpr_write_mutex_release open-iov-vfio EXPORT_SYMBOL
-+0xec05ceea nv_vgpu_gsp_wpr_scratch_mutex_acquire open-iov-vfio EXPORT_SYMBOL
-+0x4b246598 nv_vgpu_gsp_wpr_scratch_mutex_release open-iov-vfio EXPORT_SYMBOL
-+0xfe33a432 nv_vgpu_gsp_get_primary_dispatcher open-iov-vfio EXPORT_SYMBOL
-+0xc1979caa nv_vgpu_gsp_get_secondary_dispatcher open-iov-vfio EXPORT_SYMBOL
-+0x89b21e78 nv_vgpu_gsp_get_alloc_main open-iov-vfio EXPORT_SYMBOL
-+0x972e5e45 nv_vgpu_gsp_get_schedule_main open-iov-vfio EXPORT_SYMBOL
-+0xa6809adb nv_vgpu_gsp_get_bar_trap_handler_jt open-iov-vfio EXPORT_SYMBOL
-+0xcf2a6ed8 nv_vgpu_gsp_get_bar_trap_handler_primary open-iov-vfio EXPORT_SYMBOL
-+0x1ba6baef nv_vgpu_gsp_get_entry_point open-iov-vfio EXPORT_SYMBOL
-+0x4fa3b818 fw_analyzer_analyze open-iov-vfio EXPORT_SYMBOL_GPL
-+0x424272d4 fw_analyzer_load_and_analyze open-iov-vfio EXPORT_SYMBOL_GPL
-+0x7f7c5e6c fw_analyzer_print_result open-iov-vfio EXPORT_SYMBOL_GPL
-+0x8c7dcd3c dynamic_dispatcher_init open-iov-vfio EXPORT_SYMBOL_GPL
-+0x01dca6c2 dynamic_dispatcher_fini open-iov-vfio EXPORT_SYMBOL_GPL
-+0xcd45da5f dynamic_dispatcher_use_emulation open-iov-vfio EXPORT_SYMBOL_GPL
-+0x5c69b70b dynamic_dispatcher_alloc open-iov-vfio EXPORT_SYMBOL_GPL
-+0x436485b4 dynamic_dispatcher_free open-iov-vfio EXPORT_SYMBOL_GPL
-+0xd4547701 dynamic_dispatcher_map open-iov-vfio EXPORT_SYMBOL_GPL
-+0xa69f56a4 dynamic_dispatcher_unmap open-iov-vfio EXPORT_SYMBOL_GPL
-+0x444e6538 dynamic_dispatcher_pin open-iov-vfio EXPORT_SYMBOL_GPL
-+0x8eeace2b dynamic_dispatcher_unpin open-iov-vfio EXPORT_SYMBOL_GPL
-+0x39142c5c dynamic_dispatcher_schedule open-iov-vfio EXPORT_SYMBOL_GPL
-+0xb5bb4890 dynamic_dispatcher_yield open-iov-vfio EXPORT_SYMBOL_GPL
-+0x5bd014a6 dynamic_dispatcher_bar_trap open-iov-vfio EXPORT_SYMBOL_GPL
-+0xc6bc85d2 dynamic_dispatcher_migrate_save open-iov-vfio EXPORT_SYMBOL_GPL
-+0x2f480b10 dynamic_dispatcher_migrate_restore open-iov-vfio EXPORT_SYMBOL_GPL
-+0xd1994a67 dynamic_dispatcher_notify_register open-iov-vfio EXPORT_SYMBOL_GPL
-+0xeb6d1fbc dynamic_dispatcher_notify_unregister open-iov-vfio EXPORT_SYMBOL_GPL
-+0x4c369e34 dynamic_dispatcher_get_version open-iov-vfio EXPORT_SYMBOL_GPL
-+0xc5d8eb77 dynamic_dispatcher_get_fw_addresses open-iov-vfio EXPORT_SYMBOL_GPL
-+0x48cbd40e arch_get_by_name open-iov-vfio EXPORT_SYMBOL_GPL
-+0x90c7d953 arch_get_by_pci_id open-iov-vfio EXPORT_SYMBOL_GPL
-+0x750f8f00 arch_get_default open-iov-vfio EXPORT_SYMBOL_GPL
-+0xa505fad7 arch_get_bar_config open-iov-vfio EXPORT_SYMBOL_GPL
-+0x6707466a arch_get_doorbell_offset open-iov-vfio EXPORT_SYMBOL_GPL
-+0xc9ed25fd arch_get_shared_mem_offset open-iov-vfio EXPORT_SYMBOL_GPL
-+0x1d6af5c9 arch_get_msix_vectors open-iov-vfio EXPORT_SYMBOL_GPL
-+0x835587f5 arch_supports_mig open-iov-vfio EXPORT_SYMBOL_GPL
-+0x9d3f1b2f arch_supports_sriov open-iov-vfio EXPORT_SYMBOL_GPL
-+0xd2409aef arch_get_gsp_version open-iov-vfio EXPORT_SYMBOL_GPL
-+0xc75537a2 version_get_interface open-iov-vfio EXPORT_SYMBOL_GPL
-+0xe7818f08 version_get_by_kernel_version open-iov-vfio EXPORT_SYMBOL_GPL
-+0x12d7fadb version_has_feature open-iov-vfio EXPORT_SYMBOL_GPL
-+0xfab46c68 version_get_string open-iov-vfio EXPORT_SYMBOL_GPL
-diff --git a/kernel-open/common/inc/nv-linux.h b/kernel-open/common/inc/nv-linux.h
-index 7733e80..8331487 100644
---- a/kernel-open/common/inc/nv-linux.h
-+++ b/kernel-open/common/inc/nv-linux.h
-@@ -1409,6 +1409,7 @@ typedef struct nv_linux_state_s {
- #if defined(NV_VGPU_KVM_BUILD)
- wait_queue_head_t wait;
- NvS32 return_status;
-+ struct mdev_parent *mdev_parent;
- #endif
-
- #if defined(CONFIG_PM_DEVFREQ)
-diff --git a/kernel-open/common/inc/nv-vgpu-vfio-interface-nvidia.h b/kernel-open/common/inc/nv-vgpu-vfio-interface-nvidia.h
-new file mode 100644
-index 0000000..b2c7734
---- /dev/null
-+++ b/kernel-open/common/inc/nv-vgpu-vfio-interface-nvidia.h
-@@ -0,0 +1,71 @@
-+/* SPDX-FileCopyrightText: Copyright (c) 2016-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-+ * SPDX-License-Identifier: MIT
-+ */
-+
-+#ifndef _NV_VGPU_VFIO_INTERFACE_NVIDIA_H_
-+#define _NV_VGPU_VFIO_INTERFACE_NVIDIA_H_
-+
-+#include <linux/pci.h>
-+#include <linux/device.h>
-+#include <linux/mdev.h>
-+#include <linux/vfio.h>
-+#include "nvstatus.h"
-+#include "nv-hypervisor.h"
-+
-+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;
-+
-+/*
-+ * Functions provided by nvidia-vgpu-vfio module (open-iov-vfio.ko)
-+ * and called by nvidia.ko
-+ */
-+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);
-+
-+/*
-+ * mdev driver registration - provided by nvidia-vgpu-vfio module
-+ */
-+extern int nv_vgpu_mdev_driver_register(void);
-+extern void nv_vgpu_mdev_driver_unregister(void);
-+extern void nv_vgpu_mdev_unregister_parent(struct pci_dev *pci_dev);
-+extern int nv_vgpu_mdev_register_parent(struct pci_dev *pci_dev);
-+
-+#endif /* _NV_VGPU_VFIO_INTERFACE_NVIDIA_H_ */
-diff --git a/kernel-open/common/inc/nv-vgpu-vfio-interface.h b/kernel-open/common/inc/nv-vgpu-vfio-interface.h
-new file mode 100644
-index 0000000..b231407
---- /dev/null
-+++ b/kernel-open/common/inc/nv-vgpu-vfio-interface.h
-@@ -0,0 +1,86 @@
-+/* 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>
-+#include "nvstatus.h"
-+#include "nv-hypervisor.h"
-+
-+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 *);
-+
-+/*
-+ * structure to be registered to RM using which it
-+ * will call into nvidia-vgpu-vfio module.
-+ * RM will use this structure to call into
-+ * nvidia-vgpu-vfio module
-+ */
-+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 *);
-+
-+/*
-+ * nvidia-vgpu-vfio module uses this structure to
-+ * call into RM
-+ */
-+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;
-+
-+/*
-+ * function exposed by RM and called by nvidia-vgpu-vfio
-+ * module to initialize vgpu_vfio_ops_t strucure
-+ */
-+NV_STATUS nvidia_vgpu_vfio_set_ops(vgpu_vfio_ops_t *vgpu_vfio_ops);
-+
-+/*
-+ * function exposed by RM and called by nvidia-vgpu-vfio
-+ * module to initialize rm_vgpu_vfio_ops_t strucure
-+ */
-+NV_STATUS nvidia_vgpu_vfio_get_ops(rm_vgpu_vfio_ops_t *ops);
-+
-+NV_STATUS nvidia_vgpu_vfio_probe(struct pci_dev *);
-+void nvidia_vgpu_vfio_remove(struct pci_dev *, NvBool);
-+
-+#ifndef __GENKSYMS__
-+int nv_vgpu_mdev_driver_register(void);
-+void nv_vgpu_mdev_driver_unregister(void);
-+void nv_vgpu_mdev_unregister_parent(struct pci_dev *pci_dev);
-+int nv_vgpu_mdev_register_parent(struct pci_dev *pci_dev);
-+#endif
-+
-+#endif /* _NV_VGPU_VFIO_INTERFACE_H_ */
-\ No newline at end of file
-diff --git a/kernel-open/nvidia/nv-pci.c b/kernel-open/nvidia/nv-pci.c
-index 82338b8..5aed4f8 100644
---- a/kernel-open/nvidia/nv-pci.c
-+++ b/kernel-open/nvidia/nv-pci.c
-@@ -29,7 +29,7 @@
- #include "nv-reg.h"
-
- #if defined(NV_VGPU_KVM_BUILD)
--#include "nv-vgpu-vfio-interface.h"
-+#include "nv-vgpu-vfio-interface-nvidia.h"
- #endif
- #include <linux/iommu.h>
-
-diff --git a/kernel-open/nvidia/nv.c b/kernel-open/nvidia/nv.c
-index 04a5c64..6ca6402 100644
---- a/kernel-open/nvidia/nv.c
-+++ b/kernel-open/nvidia/nv.c
-@@ -43,7 +43,9 @@
- #endif
-
- #if defined(NV_VGPU_KVM_BUILD)
--#include "nv-vgpu-vfio-interface.h"
-+#include "nv-vgpu-vfio-interface-nvidia.h"
-+extern int nv_vgpu_mdev_driver_register(void);
-+extern void nv_vgpu_mdev_driver_unregister(void);
- #endif
-
- #include "nvlink_proto.h"
-@@ -890,6 +892,11 @@ static int __init nvidia_init_module(void)
- goto caps_imex_exit;
- }
-
-+#if defined(NV_VGPU_KVM_BUILD)
-+ /* mdev driver registration is now handled by nvidia-vgpu-vfio.ko.
-+ * Host driver only registers mdev parent via nv_pci_probe. */
-+#endif
-+
- count = nvos_count_devices(&num_pci_devices, &num_platform_devices);
- if ((count == 0) && (!is_nvswitch_present))
- {
-@@ -1011,6 +1018,10 @@ uvm_exit:
- module_exit:
- nv_module_exit(sp);
-
-+#if defined(NV_VGPU_KVM_BUILD)
-+ /* mdev driver unregistration is now handled by nvidia-vgpu-vfio.ko */
-+#endif
-+
- caps_imex_exit:
- nv_caps_imex_exit();
-
-@@ -1048,6 +1059,10 @@ static void __exit nvidia_exit_module(void)
-
- nv_module_exit(sp);
-
-+#if defined(NV_VGPU_KVM_BUILD)
-+ /* mdev driver unregistration is now handled by nvidia-vgpu-vfio.ko */
-+#endif
-+
- nv_caps_imex_exit();
-
- nv_caps_root_exit();
-diff --git a/kernel-open/nvidia/os-interface.c b/kernel-open/nvidia/os-interface.c
-index 2bf5a5d..46b99d8 100644
---- a/kernel-open/nvidia/os-interface.c
-+++ b/kernel-open/nvidia/os-interface.c
-@@ -1696,6 +1696,12 @@ NV_STATUS NV_API_CALL os_call_vgpu_vfio(void *pvgpu_vfio_info, NvU32 cmd_type)
- {
- return NV_ERR_NOT_SUPPORTED;
- }
-+#else
-+NV_STATUS NV_API_CALL os_call_vgpu_vfio(void *pvgpu_vfio_info, NvU32 cmd_type)
-+{
-+ // Forward to the vGPU VFIO module if available
-+ return NV_ERR_NOT_SUPPORTED;
-+}
- #endif
-
- NV_STATUS NV_API_CALL os_alloc_pages_node
-diff --git a/src/common/inc/nvUnixVersion.h b/src/common/inc/nvUnixVersion.h
-index 93a1b1d..6ee92b4 100644
---- a/src/common/inc/nvUnixVersion.h
-+++ b/src/common/inc/nvUnixVersion.h
-@@ -5,7 +5,7 @@
- (defined(RMCFG_FEATURE_PLATFORM_GSP) && RMCFG_FEATURE_PLATFORM_GSP == 1) || \
- defined(NV_DCECORE)
-
--#define NV_VERSION_STRING "610.57.04"
-+#define NV_VERSION_STRING "570.144"
-
- #else
-
-diff --git a/src/common/shared/inc/g_vgpu_chip_flags.h b/src/common/shared/inc/g_vgpu_chip_flags.h
-index c04328d..fafd38f 100644
---- a/src/common/shared/inc/g_vgpu_chip_flags.h
-+++ b/src/common/shared/inc/g_vgpu_chip_flags.h
-@@ -35,6 +35,7 @@ ENTRY(0x1E37, 0x13A8, 0x10de, "GRID RTX T10x-4"),
- ENTRY(0x1E37, 0x13A9, 0x10de, "GRID RTX T10x-8"),
- ENTRY(0x1E37, 0x180D, 0x10de, "NVIDIA GeForce GTX 1060"),
- ENTRY(0x1E37, 0x1820, 0x10de, "NVIDIA GeForce RTX 2080"),
-+ENTRY(0x1ED3, 0x1F01, 0x1043, "NVIDIA RTX 2080 SUPER Mobile"),
- ENTRY(0x1EB8, 0x1309, 0x10de, "GRID T4-1B"),
- ENTRY(0x1EB8, 0x130A, 0x10de, "GRID T4-2B"),
- ENTRY(0x1EB8, 0x130B, 0x10de, "GRID T4-2B4"),
-diff --git a/version.mk b/version.mk
-index b35bdde..d27c515 100644
---- a/version.mk
-+++ b/version.mk
-@@ -1,5 +1,5 @@
--NVIDIA_VERSION = 610.57.04
--NVIDIA_NVID_VERSION = 610.57.04
-+NVIDIA_VERSION = 570.144
-+NVIDIA_NVID_VERSION = 570.144
- NVIDIA_NVID_EXTRA =
-
- # This file.
---
-2.43.0
-
diff --git a/patches/nvidia/README.md b/patches/nvidia/README.md
deleted file mode 100644
index 9c74f75..0000000
--- a/patches/nvidia/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# NVIDIA open-gpu-kernel-modules Patches
-
-Open-IOV does **not** vendor the NVIDIA OpenRM source tree. Instead, the
-installer clones upstream at a pinned tag and applies this patch series.
-
-## Pinned upstream
-
-- Repository: <https://github.com/NVIDIA/open-gpu-kernel-modules.git>
-- Tag: `610.57.04`
-- Pristine-tree SHA256 of the delta base: tag `610.57.04`
-
-## Applying
-
-```bash
-git clone --depth 1 --branch 610.57.04 \
- https://github.com/NVIDIA/open-gpu-kernel-modules.git
-cd open-gpu-kernel-modules
-git apply /path/to/open-iov/patches/nvidia/*.patch
-```
-
-(`install.sh` does this automatically.)
-
-## Regenerating the series
-
-If you modify the NVIDIA tree, regenerate the patches with:
-
-```bash
-cd nvidia-open-gpu-kernel-modules
-git format-patch 610.57.04..HEAD -o ../patches/nvidia/
-```
-
-## What the series does
-
-`0001-Build-fixes-and-vGPU-VFIO-interface-integration.patch`:
-
-- Adds the vGPU VFIO interface headers (`nv-vgpu-vfio-interface.h`,
- `nv-vgpu-vfio-interface-nvidia.h`) that `open-iov-vfio.ko` and
- `nvidia.ko` share.
-- Exports the vGPU VFIO symbols from `nvidia.ko`
- (`nvidia_vgpu_vfio_probe/remove`, `nvidia_vgpu_vfio_get_ops/set_ops`,
- `nv_vgpu_mdev_register_parent/unregister_parent`, ...).
-- Reports version `570.144` to match the GSP firmware the guest driver
- stack is validated against.
-- Build fixes for kernel 6.8 out-of-tree builds and the
- `Module.symvers.open-iov` reference list.