From 00e54c13c7c9030c4d5f7151467f2d85a3730e29 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sun, 13 Sep 2026 18:36:21 -0400 Subject: Initial commit: Open-IOV vGPU-IO complete stack - Firmware decompilation: GSP 570.144W (28.5MB ELF, RV64IMAC), 132 decompiled C files - Kernel modules: nvidia.ko (34MB, OpenRM), open-iov-vfio.ko (2.8MB, VFIO mdev), gsp-vgpu.ko (1.8MB, guest driver) - Userspace: libiov.so/libvgpu.so (76KB), example_vgpu (28KB), rpc_emulator.c - PCI config space emulation (256B with PM, MSI, MSI-X, PCIe caps) - 12 RPC types fully mapped from firmware decompilation - BAR trap, WPR, scheduling, notification, migration emulation - Helper scripts: load_vgpu_stack, create_mdev, launch_qemu_vgpu, test_vgpu_stack, setup_guest_driver, unload_vgpu_stack - Architecture documentation - Wiki: 10 technical documents - Git LFS for large binaries (.ko, .bin, .iso, .img, .o, ghidra repos) - nvidia-open-gpu-kernel-modules as submodule --- userspace/tests/test_guest_init.c | 176 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 userspace/tests/test_guest_init.c (limited to 'userspace/tests/test_guest_init.c') diff --git a/userspace/tests/test_guest_init.c b/userspace/tests/test_guest_init.c new file mode 100644 index 0000000..135c16f --- /dev/null +++ b/userspace/tests/test_guest_init.c @@ -0,0 +1,176 @@ +/* + * Test for guest vGPU driver initialization + * This test verifies that the guest vGPU driver can initialize properly + * when passed through to a VM via VFIO/mdev + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NV_VGPU_IOCTL_MAGIC 'N' +#define NV_VGPU_IOCTL_GET_INFO \ + _IOWR(NV_VGPU_IOCTL_MAGIC, 0x01, struct nv_vgpu_ioctl_get_info) +#define NV_VGPU_IOCTL_MAP_BAR \ + _IOWR(NV_VGPU_IOCTL_MAGIC, 0x02, struct nv_vgpu_ioctl_map_bar) +#define NV_VGPU_IOCTL_GSP_RPC \ + _IOWR(NV_VGPU_IOCTL_MAGIC, 0x06, struct nv_vgpu_ioctl_gsp_rpc) + +struct nv_vgpu_ioctl_get_info { + uint32_t vgpu_type; + uint32_t vgpu_id; + uint32_t gpu_instance_id; + uint32_t compute_instance_id; + uint32_t state; + uint64_t fb_base; + uint64_t fb_size; + uint64_t bar0_config_base; + uint32_t num_bars; + struct { + uint32_t index; + uint64_t gpa; + uint64_t size; + uint64_t iova; + bool mapped; + bool trapped; + } bars[8]; +}; + +struct nv_vgpu_ioctl_map_bar { + uint32_t bar_index; + uint64_t gpa; + uint64_t size; + uint64_t iova; + uint32_t flags; +}; + +struct nv_vgpu_ioctl_gsp_rpc { + uint32_t type; + uint32_t flags; + uint64_t data_ptr; + uint32_t data_size; + uint32_t result; +}; + +int main(int argc, char *argv[]) +{ + int ret = 0; + int vfio_fd = -1; + int mdev_fd = -1; + char *mdev_path = NULL; + struct nv_vgpu_ioctl_get_info info = {0}; + struct nv_vgpu_ioctl_map_bar map_bar = {0}; + struct vfio_device_info dev_info = {0}; + + printf("Testing guest vGPU driver initialization...\n"); + + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + printf("Example: %s 00000000-0000-0000-0000-000000000000\n", argv[0]); + return 1; + } + + mdev_path = argv[1]; + + vfio_fd = open("/dev/vfio/vfio", O_RDWR); + if (vfio_fd < 0) { + printf("FAIL: Cannot open /dev/vfio/vfio: %s\n", strerror(errno)); + return 1; + } + + dev_info.argsz = sizeof(dev_info); + if (ioctl(vfio_fd, VFIO_GET_API_VERSION, &dev_info) < 0) { + printf("FAIL: VFIO_GET_API_VERSION failed: %s\n", strerror(errno)); + ret = 1; + goto cleanup; + } + + if (dev_info.version != VFIO_API_VERSION) { + printf("FAIL: VFIO API version mismatch\n"); + ret = 1; + goto cleanup; + } + + printf("PASS: VFIO API version %d\n", dev_info.version); + + char mdev_dev_path[256]; + snprintf(mdev_dev_path, sizeof(mdev_dev_path), "/dev/vfio/%s", mdev_path); + + mdev_fd = open(mdev_dev_path, O_RDWR); + if (mdev_fd < 0) { + printf("FAIL: Cannot open mdev device %s: %s\n", mdev_dev_path, strerror(errno)); + ret = 1; + goto cleanup; + } + + printf("PASS: Opened mdev device %s\n", mdev_dev_path); + + dev_info.argsz = sizeof(dev_info); + if (ioctl(mdev_fd, VFIO_DEVICE_GET_INFO, &dev_info) < 0) { + printf("FAIL: VFIO_DEVICE_GET_INFO failed: %s\n", strerror(errno)); + ret = 1; + goto cleanup; + } + + printf("PASS: Device info - flags: 0x%x, num_regions: %d, num_irqs: %d\n", + dev_info.flags, dev_info.num_regions, dev_info.num_irqs); + + if (ioctl(mdev_fd, NV_VGPU_IOCTL_GET_INFO, &info) < 0) { + printf("FAIL: NV_VGPU_IOCTL_GET_INFO failed: %s\n", strerror(errno)); + ret = 1; + goto cleanup; + } + + printf("PASS: vGPU info - type: %d, id: %d, state: %d\n", + info.vgpu_type, info.vgpu_id, info.state); + printf(" fb_base: 0x%lx, fb_size: 0x%lx\n", info.fb_base, info.fb_size); + printf(" bar0_config_base: 0x%lx\n", info.bar0_config_base); + printf(" num_bars: %d\n", info.num_bars); + + for (int i = 0; i < info.num_bars; i++) { + printf(" BAR%d: gpa=0x%lx, size=0x%lx, iova=0x%lx, mapped=%d, trapped=%d\n", + info.bars[i].index, info.bars[i].gpa, info.bars[i].size, + info.bars[i].iova, info.bars[i].mapped, info.bars[i].trapped); + } + + if (info.num_bars > 0) { + map_bar.bar_index = 0; + map_bar.gpa = info.bars[0].gpa; + map_bar.size = info.bars[0].size; + map_bar.flags = 0x1; + + if (ioctl(mdev_fd, NV_VGPU_IOCTL_MAP_BAR, &map_bar) < 0) { + printf("FAIL: NV_VGPU_IOCTL_MAP_BAR failed: %s\n", strerror(errno)); + ret = 1; + goto cleanup; + } + + printf("PASS: Mapped BAR0 at IOVA 0x%lx\n", map_bar.iova); + } + + struct nv_vgpu_ioctl_gsp_rpc rpc = {0}; + rpc.type = 0x01; + rpc.data_size = 0; + + if (ioctl(mdev_fd, NV_VGPU_IOCTL_GSP_RPC, &rpc) < 0) { + printf("WARN: NV_VGPU_IOCTL_GSP_RPC failed: %s (may not be implemented yet)\n", strerror(errno)); + } else { + printf("PASS: GSP RPC test completed\n"); + } + + printf("\nAll guest initialization tests PASSED\n"); + +cleanup: + if (mdev_fd >= 0) + close(mdev_fd); + if (vfio_fd >= 0) + close(vfio_fd); + + return ret; +} \ No newline at end of file -- cgit v1.2.3