diff options
| author | Open-IOV <dev@open-iov.org> | 2026-09-23 05:44:08 -0400 |
|---|---|---|
| committer | Open-IOV <dev@open-iov.org> | 2026-09-23 05:46:43 -0400 |
| commit | 68cdd7728a7cc6715bbbff7decfe2b11c3bdf558 (patch) | |
| tree | 3dc8ce2e6af313a97ec6852f5c663a9a93665d2e /userspace/examples | |
| download | open-iov-68cdd7728a7cc6715bbbff7decfe2b11c3bdf558.tar.gz open-iov-68cdd7728a7cc6715bbbff7decfe2b11c3bdf558.zip | |
Open-IOV: initial public release
Open-IOV virtualizes NVIDIA GPUs so that unmodified guest drivers run with
real GPU functionality - CUDA first, 3D and video to follow - on unmodified
hosts, without a proprietary vGPU license and without patching any driver,
firmware or hypervisor.
Core principle: emulate the interface, pass through the work.
kernel/ open-iov-vfio.ko - host VFIO mdev driver: virtual GPU device
(PCI config space, BAR shadows, MSI-X), GSP boot emulation,
GSP-RM message-queue/RPC emulation, memory model (GPU-VA to
guest-PA discovery) and the semaphore-completion service that
advances guest UVM progress.
userspace/ libiov.so management API and examples.
tools/ guest diagnostics, firmware analysis wrappers, RM probes.
scripts/ stack manager, VM harness, build/load/test automation.
config/ hardware/version profiles (the portability surface).
docs/ documentation tree - start at docs/README.md.
wiki/ long-form firmware and protocol deep dives.
Status: initialization works end to end for a stock 570.144 Linux guest on
Turing (TU104): driver probe, nvidia-smi, the full GSP-RM control battery,
object creation and the early CUDA/UVM start-up path. GPU work forwarding -
the step that makes CUDA kernels execute on real hardware - is the active
work item; see docs/04-implementation/01-known-knowns-and-unknowns.md.
License: BSD-3-Clause for the project; GPL-2.0 for kernel modules that link
GPL-only kernel interfaces. See LICENSE and docs/09-reference/legal-and-licensing.md.
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 |
