From: Alex Williamson <alex.williamson@redhat.com>
To: chrisw@sous-sol.org, aik@au1.ibm.com, pmac@au1.ibm.com,
dwg@au1.ibm.com, joerg.roedel@amd.com, agraf@suse.de,
benve@cisco.com, aafabbri@cisco.com, B08248@freescale.com,
B07421@freescale.com, avi@redhat.com, kvm@vger.kernel.org,
qemu-devel@nongnu.org, iommu@lists.linux-foundation.org,
linux-pci@vger.kernel.org
Cc: alex.williamson@redhat.com
Subject: [Qemu-devel] [RFC PATCH 5/5] VFIO: Simple test tool
Date: Thu, 01 Sep 2011 13:50:57 -0600 [thread overview]
Message-ID: <20110901195057.2391.60205.stgit@s20.home> (raw)
In-Reply-To: <20110901194915.2391.97400.stgit@s20.home>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
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 <alex.williamson@redhat.com>
+ *
+ * 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);
+ }
+ }
+}
next prev parent reply other threads:[~2011-09-01 19:51 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-01 19:50 [Qemu-devel] [RFC PATCH 0/5] VFIO-NG group/device/iommu framework Alex Williamson
2011-09-01 19:50 ` [Qemu-devel] [RFC PATCH 1/5] iommu: Add iommu_device_group callback and iommu_group sysfs entry Alex Williamson
2011-09-01 19:50 ` [Qemu-devel] [RFC PATCH 2/5] intel-iommu: Implement iommu_device_group Alex Williamson
2011-09-01 19:50 ` [Qemu-devel] [RFC PATCH 3/5] VFIO: Base framework for new VFIO driver Alex Williamson
2011-09-07 14:52 ` Konrad Rzeszutek Wilk
2011-09-19 16:42 ` Alex Williamson
2011-09-01 19:50 ` [Qemu-devel] [RFC PATCH 4/5] VFIO: Add PCI device support Alex Williamson
2011-09-07 18:55 ` Konrad Rzeszutek Wilk
2011-09-08 7:52 ` Avi Kivity
2011-09-08 21:52 ` Alex Williamson
2011-09-01 19:50 ` Alex Williamson [this message]
2011-09-07 11:58 ` [Qemu-devel] [RFC PATCH 0/5] VFIO-NG group/device/iommu framework Alexander Graf
2011-09-08 21:54 ` Alex Williamson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110901195057.2391.60205.stgit@s20.home \
--to=alex.williamson@redhat.com \
--cc=B07421@freescale.com \
--cc=B08248@freescale.com \
--cc=aafabbri@cisco.com \
--cc=agraf@suse.de \
--cc=aik@au1.ibm.com \
--cc=avi@redhat.com \
--cc=benve@cisco.com \
--cc=chrisw@sous-sol.org \
--cc=dwg@au1.ibm.com \
--cc=iommu@lists.linux-foundation.org \
--cc=joerg.roedel@amd.com \
--cc=kvm@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=pmac@au1.ibm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).