qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH 5/5] VFIO: Simple test tool


From: Alex Williamson
Subject: [Qemu-devel] [RFC PATCH 5/5] VFIO: Simple test tool
Date: Thu, 01 Sep 2011 13:50:57 -0600
User-agent: StGIT/0.14.3

Signed-off-by: Alex Williamson <address@hidden>
---

 tools/testing/vfio/Makefile    |    4 
 tools/testing/vfio/vfio_test.c |  406 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 410 insertions(+), 0 deletions(-)
 create mode 100644 tools/testing/vfio/Makefile
 create mode 100644 tools/testing/vfio/vfio_test.c

diff --git a/tools/testing/vfio/Makefile b/tools/testing/vfio/Makefile
new file mode 100644
index 0000000..df1fa68
--- /dev/null
+++ b/tools/testing/vfio/Makefile
@@ -0,0 +1,4 @@
+vfio_test : vfio_test.c
+
+clean :
+       rm -f vfio_test
diff --git a/tools/testing/vfio/vfio_test.c b/tools/testing/vfio/vfio_test.c
new file mode 100644
index 0000000..66eef81
--- /dev/null
+++ b/tools/testing/vfio/vfio_test.c
@@ -0,0 +1,406 @@
+/*
+ * Simple user test program for vfio group/device/iommu framework
+ *
+ * Copyright (C) 2011 Red Hat, Inc.  All rights reserved.
+ *     Author: Alex Williamson <address@hidden>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "../../../include/linux/vfio.h"
+
+struct group {
+       int fd;
+       unsigned int number;
+       struct group *next;
+};
+
+struct group *group_list = NULL;
+
+struct device {
+       int fd;
+       char *name;
+       struct device *next;
+};
+
+struct device *device_list = NULL;
+
+struct iommu {
+       int fd;
+       struct device *next;
+};
+
+struct iommu *iommu_list = NULL;
+
+void print_group(unsigned int number)
+{
+       struct group *group = group_list;
+       char buf[4096];
+       int ret;
+
+       for (; group && group->number != number; group = group->next);
+
+       if (!group) {
+               fprintf(stderr, "Group %u not found\n", number);
+       } else {
+               ret = pread(group->fd, buf, sizeof(buf), 0);
+               if (ret < 0) {
+                       fprintf(stderr, "Error reading group %u (%s)\n",
+                               group, strerror(errno));
+                       return;
+               }
+               fprintf(stdout, "---- Group %u (fd %d) begin ----\n",
+                       number, group->fd);
+               fprintf(stdout, "%s", buf);
+               fprintf(stdout, "---- Group %u end ----\n", number);
+       }
+}
+
+void print_device(struct device *device)
+{
+       fprintf(stdout, "---- Device %s (fd %d) ----\n",
+               device->name, device->fd);
+}
+
+int do_device()
+{
+       char cmd[256];
+       int ret;
+
+       while (1) {
+               fprintf(stdout, "device command: ");
+               fscanf(stdin, "%s", cmd);
+
+               if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") ||
+                   !strcmp(cmd, "q"))
+                       return 0;
+
+               if (!strcmp(cmd, "help") || !strcmp(cmd, "h")) {
+                       fprintf(stdout, "[h]elp - this message\n");
+                       fprintf(stdout, "[o]pen - open device\n");
+                       fprintf(stdout, "[c]lose - close device\n");
+                       fprintf(stdout, "[l]ist - list devices\n");
+
+               } else if (!strcmp(cmd, "open") || !strcmp(cmd, "o")) {
+                       int fd;
+                       struct device *device;
+
+                       fprintf(stdout, "group fd #: ");
+                       fscanf(stdin, "%d", &fd);
+
+                       fprintf(stdout, "device name: ");
+                       fscanf(stdin, "%s", cmd);
+
+                       ret = ioctl(fd, VFIO_GROUP_GET_DEVICE_FD, cmd);
+                       if (ret < 0) {
+                               fprintf(stderr, "get device failed (%s)\n",
+                                       strerror(errno));
+                               return ret;
+                       }
+
+                       device = malloc(sizeof(*device));
+                       if (!device) {
+                               fprintf(stderr, "malloc device failed (%s)\n",
+                                       strerror(errno));
+                               return -1;
+                       }
+
+                       device->fd = ret;
+                       device->name = strdup(cmd);
+                       device->next = device_list;
+                       device_list = device;
+                       print_device(device);
+                       return 0;
+
+               } else if (!strcmp(cmd, "close") || !strcmp(cmd, "c")) {
+                       struct device *device;
+
+                       fprintf(stdout, "device name: ");
+                       fscanf(stdin, "%s", cmd);
+
+                       for (device = device_list;
+                            device && strcmp(device->name, cmd);
+                            device = device->next);
+
+                       if (!device) {
+                               fprintf(stderr, "device not found\n");
+                               return 0;
+                       }
+
+                       ret = close(device->fd);
+                       if (ret) {
+                               fprintf(stderr, "Error closing device (%s)\n",
+                                       strerror(errno));
+                               return ret;
+                       }
+                       
+                       if (device == device_list)
+                               device_list = device->next;
+                       else {
+                               struct device *prev;
+
+                               for (prev = device_list; prev->next != device;
+                                    prev = prev->next);
+
+                               prev->next = device->next;
+                       }
+                       free(device->name);
+                       free(device);
+                       return 0;
+
+               } else if (!strcmp(cmd, "list") || !strcmp(cmd, "l")) {
+                       struct device *device;
+
+                       for (device = device_list;
+                            device; device = device->next)
+                               print_device(device);
+
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+void do_iommu()
+{
+
+}
+
+int main(int argc, char **argv)
+{
+       char cmd[256];
+       int ret;
+
+       while (1) {
+               fprintf(stdout, "command: ");
+               fscanf(stdin, "%s", cmd);
+
+               if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") ||
+                   !strcmp(cmd, "q"))
+                       return 0;
+
+               if (!strcmp(cmd, "help") || !strcmp(cmd, "h")) {
+                       fprintf(stdout, "[h]elp - this message\n");
+                       fprintf(stdout, "[p]rint - print group\n");
+                       fprintf(stdout, "[o]pen - open group\n");
+                       fprintf(stdout, "[c]lose - close group\n");
+                       fprintf(stdout, "close[f]d - close fd\n");
+                       fprintf(stdout, "[m]erge - merge group\n");
+                       fprintf(stdout, "[u]nmerge - unmerge group\n");
+                       fprintf(stdout, "[d]evice - device commands\n");
+                       fprintf(stdout, "[i]ommu - iommu commands\n");
+                       fprintf(stdout, "[l]ist - list groups\n");
+
+               } else if (!strcmp(cmd, "print") || !strcmp(cmd, "p")) {
+                       unsigned int number;
+
+                       fprintf(stdout, "group #: ");
+                       fscanf(stdin, "%u", &number);
+
+                       print_group(number);
+
+               } else if (!strcmp(cmd, "device") || !strcmp(cmd, "d")) {
+                       do_device();
+
+               } else if (!strcmp(cmd, "iommu") || !strcmp(cmd, "i")) {
+                       do_iommu();
+
+               } else if (!strcmp(cmd, "list") || !strcmp(cmd, "l")) {
+                       struct group *group;
+
+                       for (group = group_list; group; group = group->next)
+                               print_group(group->number);
+
+               } else if (!strcmp(cmd, "open") || !strcmp(cmd, "o")) {
+                       unsigned int number;
+                       struct group *group;
+                       char path[256];
+
+                       fprintf(stdout, "group #: ");
+                       fscanf(stdin, "%u", &number);
+
+                       group = malloc(sizeof(*group));
+                       if (!group) {
+                               fprintf(stderr, "Failed to alloc group\n");
+                               return -1;
+                       }
+
+                       snprintf(path, sizeof(path), "/dev/vfio/%u", number);
+                       group->fd = open(path, O_RDWR);
+                       if (group->fd < 0) {
+                               fprintf(stderr, "Failed to open %s (%s)\n",
+                                       path, strerror(errno));
+                               free(group);
+                               continue;
+                       }
+                       group->number = number;
+                       group->next = group_list;
+                       group_list = group;
+
+                       print_group(number);
+
+               } else if (!strcmp(cmd, "close") || !strcmp(cmd, "c")) {
+                       unsigned int number;
+                       struct group *group;
+                       int ret;
+
+                       fprintf(stdout, "group #: ");
+                       fscanf(stdin, "%u", &number);
+
+                       for (group = group_list;
+                            group && group->number != number;
+                            group = group->next);
+
+                       if (!group) {
+                               fprintf(stderr, "group not open, open first\n");
+                               continue;
+                       }
+
+                       ret = close(group->fd);
+                       if (ret) {
+                               fprintf(stderr, "close failed (%s)\n",
+                                       strerror(errno));
+                               continue;
+                       }
+
+                       if (group == group_list)
+                               group_list = group->next;
+                       else {
+                               struct group *prev;
+
+                               for (prev = group_list; prev->next != group;
+                                    prev = prev->next);
+
+                               prev->next = group->next;
+                       }
+                       free(group);
+
+               } else if (!strcmp(cmd, "closefd") || !strcmp(cmd, "f")) {
+                       int fd;
+                       struct group *group;
+                       int ret;
+
+                       fprintf(stdout, "fd #: ");
+                       fscanf(stdin, "%d", &fd);
+
+                       for (group = group_list;
+                            group && group->fd != fd;
+                            group = group->next);
+
+                       if (!group) {
+                               fprintf(stderr, "group not open, open first\n");
+                               continue;
+                       }
+
+                       ret = close(group->fd);
+                       if (ret) {
+                               fprintf(stderr, "close failed (%s)\n",
+                                       strerror(errno));
+                               continue;
+                       }
+
+                       if (group == group_list)
+                               group_list = group->next;
+                       else {
+                               struct group *prev;
+
+                               for (prev = group_list; prev->next != group;
+                                    prev = prev->next);
+
+                               prev->next = group->next;
+                       }
+                       free(group);
+
+               } else if (!strcmp(cmd, "merge") || !strcmp(cmd, "m")) {
+                       unsigned int numberA, numberB;
+                       struct group *groupA, *groupB;
+                       int ret;
+
+                       fprintf(stdout, "base group #: ");
+                       fscanf(stdin, "%u", &numberA);
+
+                       for (groupA = group_list;
+                            groupA && groupA->number != numberA;
+                            groupA = groupA->next);
+
+                       if (!groupA) {
+                               fprintf(stderr, "group not open, open first\n");
+                               continue;
+                       }
+
+                       fprintf(stdout, "merge group #: ");
+                       fscanf(stdin, "%u", &numberB);
+
+                       for (groupB = group_list;
+                            groupB && groupB->number != numberB;
+                            groupB = groupB->next);
+
+                       if (!groupB) {
+                               fprintf(stderr, "group not open, open first\n");
+                               continue;
+                       }
+
+                       ret = ioctl(groupA->fd, VFIO_GROUP_MERGE, &groupB->fd);
+                       if (ret) {
+                               fprintf(stderr, "group merge failed (%s)\n",
+                                       strerror(errno));
+                                       continue;
+                       }
+
+                       print_group(numberA);
+                       print_group(numberB);
+
+               } else if (!strcmp(cmd, "unmerge") || !strcmp(cmd, "u")) {
+                       unsigned int numberA, numberB;
+                       struct group *groupA, *groupB;
+                       int ret;
+
+                       fprintf(stdout, "base group #: ");
+                       fscanf(stdin, "%u", &numberA);
+
+                       for (groupA = group_list;
+                            groupA && groupA->number != numberA;
+                            groupA = groupA->next);
+
+                       if (!groupA) {
+                               fprintf(stderr, "group not open, open first\n");
+                               continue;
+                       }
+
+                       fprintf(stdout, "unmerge group #: ");
+                       fscanf(stdin, "%u", &numberB);
+
+                       for (groupB = group_list;
+                            groupB && groupB->number != numberB;
+                            groupB = groupB->next);
+
+                       if (!groupB) {
+                               fprintf(stderr, "group not open, open first\n");
+                               continue;
+                       }
+
+                       ret = ioctl(groupA->fd,
+                                   VFIO_GROUP_UNMERGE, &groupB->fd);
+                       if (ret) {
+                               fprintf(stderr, "group unmerge failed (%s)\n",
+                                       strerror(errno));
+                                       continue;
+                       }
+
+                       print_group(numberA);
+                       print_group(numberB);
+               }
+       }
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]