qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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);
+		}
+	}
+}

  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).