summaryrefslogtreecommitdiffstats
path: root/userspace/examples
diff options
context:
space:
mode:
Diffstat (limited to 'userspace/examples')
-rw-r--r--userspace/examples/Makefile27
-rw-r--r--userspace/examples/example_vgpu.c173
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