diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-13 18:36:21 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-13 18:36:21 -0400 |
| commit | 00e54c13c7c9030c4d5f7151467f2d85a3730e29 (patch) | |
| tree | 17a45239df8d2e4912ff3697ed06e85a10b969de /userspace/examples | |
| download | open-iov-00e54c13c7c9030c4d5f7151467f2d85a3730e29.tar.gz open-iov-00e54c13c7c9030c4d5f7151467f2d85a3730e29.zip | |
Initial commit: Open-IOV vGPU-IO complete stack
- Firmware decompilation: GSP 570.144W (28.5MB ELF, RV64IMAC), 132 decompiled C files
- Kernel modules: nvidia.ko (34MB, OpenRM), open-iov-vfio.ko (2.8MB, VFIO mdev), gsp-vgpu.ko (1.8MB, guest driver)
- Userspace: libiov.so/libvgpu.so (76KB), example_vgpu (28KB), rpc_emulator.c
- PCI config space emulation (256B with PM, MSI, MSI-X, PCIe caps)
- 12 RPC types fully mapped from firmware decompilation
- BAR trap, WPR, scheduling, notification, migration emulation
- Helper scripts: load_vgpu_stack, create_mdev, launch_qemu_vgpu, test_vgpu_stack, setup_guest_driver, unload_vgpu_stack
- Architecture documentation
- Wiki: 10 technical documents
- Git LFS for large binaries (.ko, .bin, .iso, .img, .o, ghidra repos)
- nvidia-open-gpu-kernel-modules as submodule
Diffstat (limited to 'userspace/examples')
| -rw-r--r-- | userspace/examples/Makefile | 27 | ||||
| -rw-r--r-- | userspace/examples/example_vgpu.c | 173 |
2 files changed, 200 insertions, 0 deletions
diff --git a/userspace/examples/Makefile b/userspace/examples/Makefile new file mode 100644 index 0000000..065e00f --- /dev/null +++ b/userspace/examples/Makefile @@ -0,0 +1,27 @@ +# GSP vGPU-IO Examples Makefile + +PREFIX ?= /usr/local +LIBDIR ?= $(PREFIX)/lib +INCLUDEDIR ?= $(PREFIX)/include + +CC ?= gcc +CFLAGS ?= -O2 -g -Wall -Wextra -I../include +LDFLAGS ?= -L../lib -liov + +EXAMPLES = example_vgpu + +all: $(EXAMPLES) + +example_vgpu: example_vgpu.c ../lib/libiov.so + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) + +clean: + rm -f $(EXAMPLES) + +install: all + install -d $(DESTDIR)$(PREFIX)/bin + for ex in $(EXAMPLES); do \ + install -m 755 $$ex $(DESTDIR)$(PREFIX)/bin/; \ + done + +.PHONY: all clean install
\ No newline at end of file diff --git a/userspace/examples/example_vgpu.c b/userspace/examples/example_vgpu.c new file mode 100644 index 0000000..ede6873 --- /dev/null +++ b/userspace/examples/example_vgpu.c @@ -0,0 +1,173 @@ +/* + * GSP vGPU-IO Example Application + * Demonstrates basic VF creation, memory allocation, and BAR configuration + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <libvgpu.h> + +static volatile bool running = true; + +static void signal_handler(int sig) +{ + (void)sig; + running = false; +} + +int main(int argc, char *argv[]) +{ + const char *device_path = "/dev/gsp-vgpu"; + vgpu_device_t device = NULL; + vgpu_vf_t vf = NULL; + vgpu_handle_t handle = 0; + uint64_t va = 0; + uint64_t dma_addr = 0; + int ret; + + if (argc > 1) + device_path = argv[1]; + + printf("GSP vGPU-IO Example Application\n"); + printf("Device: %s\n", device_path); + + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + /* Open device */ + ret = vgpu_open(device_path, &device); + if (ret != VGPU_OK) { + fprintf(stderr, "Failed to open device: %s\n", vgpu_strerror(ret)); + return 1; + } + printf("Device opened successfully\n"); + + /* Get device info */ + char info[256]; + ret = vgpu_get_info(device, info, sizeof(info)); + if (ret == VGPU_OK) + printf("Device info: %s\n", info); + + /* Create VF */ + vgpu_vf_config_t config = { + .id = 1, + .bar1_offset = 0x10000000, + .bar1_size = 0x40000, + .pt_base = 0, + .pt_size = 0, + .cmd_base = 0, + .cmd_size = 0, + .max_memory_mb = 1024, + .num_engines = 4, + }; + + ret = vgpu_vf_create(device, &config, &vf); + if (ret != VGPU_OK) { + fprintf(stderr, "Failed to create VF: %s\n", vgpu_strerror(ret)); + vgpu_close(device); + return 1; + } + printf("VF %u created\n", config.id); + + /* Configure BAR1 */ + ret = vgpu_bar_config(vf, 0x10000000, 0x40000); + if (ret != VGPU_OK) { + fprintf(stderr, "Failed to configure BAR: %s\n", vgpu_strerror(ret)); + vgpu_vf_destroy(vf); + vgpu_close(device); + return 1; + } + printf("BAR1 configured\n"); + + /* Allocate VRAM */ + const uint64_t alloc_size = 1024 * 1024; /* 1 MB */ + ret = vgpu_mem_alloc(vf, alloc_size, VGPU_MEM_VRAM, 0x1000, 0, + 0, &handle, &va); + if (ret != VGPU_OK) { + fprintf(stderr, "Failed to allocate memory: %s\n", vgpu_strerror(ret)); + vgpu_vf_destroy(vf); + vgpu_close(device); + return 1; + } + printf("Allocated %llu bytes at VA 0x%llx (handle 0x%llx)\n", + (unsigned long long)alloc_size, (unsigned long long)va, + (unsigned long long)handle); + + /* Map memory */ + uint64_t mapped_va = 0; + ret = vgpu_mem_map(vf, handle, va, alloc_size, 0x3, 0, 0, &mapped_va); + if (ret != VGPU_OK) { + fprintf(stderr, "Failed to map memory: %s\n", vgpu_strerror(ret)); + vgpu_mem_free(vf, handle); + vgpu_vf_destroy(vf); + vgpu_close(device); + return 1; + } + printf("Mapped at 0x%llx\n", (unsigned long long)mapped_va); + + /* Pin for DMA */ + ret = vgpu_mem_pin(vf, handle, 0, alloc_size, VGPU_PIN_READ | VGPU_PIN_WRITE, &dma_addr); + if (ret != VGPU_OK) { + fprintf(stderr, "Failed to pin memory: %s\n", vgpu_strerror(ret)); + } else { + printf("Pinned for DMA at 0x%llx\n", (unsigned long long)dma_addr); + } + + /* Protect with WPR (write) */ + ret = vgpu_wpr_protect_write(vf, va, alloc_size); + if (ret != VGPU_OK) { + fprintf(stderr, "Failed to protect with WPR: %s\n", vgpu_strerror(ret)); + } else { + printf("WPR write protection enabled\n"); + } + + /* Set WPR timeout */ + ret = vgpu_wpr_set_timeout(vf, 1000000000ULL); /* 1 second */ + if (ret != VGPU_OK) { + fprintf(stderr, "Failed to set WPR timeout: %s\n", vgpu_strerror(ret)); + } + + /* Schedule work */ + ret = vgpu_schedule(vf, handle, 0, 0, 0, 0); + if (ret != VGPU_OK) { + fprintf(stderr, "Failed to schedule: %s\n", vgpu_strerror(ret)); + } else { + printf("Work scheduled\n"); + } + + /* Run loop */ + printf("\nRunning... Press Ctrl+C to exit\n"); + while (running) { + ret = vgpu_process_events(device, 1000); + if (ret != VGPU_OK && ret != VGPU_ERR_TIMEOUT) { + fprintf(stderr, "Event processing error: %s\n", vgpu_strerror(ret)); + } + } + + printf("\nShutting down...\n"); + + /* Unprotect WPR */ + vgpu_wpr_unprotect(vf, va); + + /* Unpin */ + if (dma_addr) + vgpu_mem_unpin(vf, handle, 0, alloc_size); + + /* Unmap */ + vgpu_mem_unmap(vf, handle, va, alloc_size); + + /* Free memory */ + vgpu_mem_free(vf, handle); + + /* Destroy VF */ + vgpu_vf_destroy(vf); + + /* Close device */ + vgpu_close(device); + + printf("Done\n"); + return 0; +}
\ No newline at end of file |
