From: "Michael S. Tsirkin" <mst@redhat.com>
To: Gregory Haskins <ghaskins@novell.com>,
kvm@vger.kernel.org, avi@redhat.com, mtosatti@redhat.com
Subject: [PATCH 1/3] virt-core: binding together drivers and hypervisors
Date: Sun, 31 May 2009 21:59:01 +0300 [thread overview]
Message-ID: <20090531185901.GB10043@redhat.com> (raw)
In-Reply-To: <cover.1243796281.git.mst@sherwood.(none)>
This adds support for virt-core: generic glue making it possible to implement
kernel-level accelerators (drivers) which are independent of a hypervisor, that
is can in theory work on top of either kvm or lguest.
Each driver and hypervisor registers with core, and then when user adds a
virtual device, drivers can find and interfact with hypervisors through the
virt_dev object.
Users add devices by making a hypervisor-specific system call (e.g. ioctl)
the result of which is a file descriptor controlling the device.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
arch/x86/kvm/Kconfig | 1 +
drivers/Makefile | 1 +
drivers/virt/Kconfig | 5 ++
drivers/virt/Makefile | 1 +
drivers/virt/virt_core.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/virt.h | 94 +++++++++++++++++++++++++++++++++++++++
6 files changed, 213 insertions(+), 0 deletions(-)
create mode 100644 drivers/virt/Kconfig
create mode 100644 drivers/virt/Makefile
create mode 100644 drivers/virt/virt_core.c
create mode 100644 include/linux/virt.h
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index a58504e..693b807 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -71,6 +71,7 @@ config KVM_TRACE
# OK, it's a little counter-intuitive to do this, but it puts it neatly under
# the virtualization menu.
+source drivers/virt/Kconfig
source drivers/lguest/Kconfig
source drivers/virtio/Kconfig
diff --git a/drivers/Makefile b/drivers/Makefile
index 1266ead..9f14b08 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -104,6 +104,7 @@ obj-$(CONFIG_HID) += hid/
obj-$(CONFIG_PPC_PS3) += ps3/
obj-$(CONFIG_OF) += of/
obj-$(CONFIG_SSB) += ssb/
+obj-$(CONFIG_VIRT_CORE) += virt/
obj-$(CONFIG_VIRTIO) += virtio/
obj-$(CONFIG_STAGING) += staging/
obj-y += platform/
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
new file mode 100644
index 0000000..ace7b2e
--- /dev/null
+++ b/drivers/virt/Kconfig
@@ -0,0 +1,5 @@
+config VIRT_CORE
+ tristate "Generic virtual device binding support"
+ ---help---
+ Core support for binding kernel drivers to virtual devices.
+ Make sure to also select any drivers you wish to use.
diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile
new file mode 100644
index 0000000..7a77047
--- /dev/null
+++ b/drivers/virt/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIRT_CORE) += virt_core.o
diff --git a/drivers/virt/virt_core.c b/drivers/virt/virt_core.c
new file mode 100644
index 0000000..89e1f53
--- /dev/null
+++ b/drivers/virt/virt_core.c
@@ -0,0 +1,111 @@
+/*
+ * Virt core support: this is the glue that binds together drivers for virtual devices
+ * and hypervisors.
+ *
+ * Copyright (c) 2009 Red Hat Inc.
+ *
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/anon_inodes.h>
+
+#include <linux/virt.h>
+
+/* virt bus implementation */
+static LIST_HEAD(driver_list);
+static LIST_HEAD(hypervisor_list);
+static DEFINE_MUTEX(driver_lock);
+static DEFINE_MUTEX(hypervisor_lock);
+
+static int virt_close(struct inode *inode, struct file *filp)
+{
+ struct virt_dev *dev = filp->private_data;
+ dev->driver->device_remove(dev->driver, dev);
+ dev->hypervisor->put(dev->hypervisor);
+ kfree(dev);
+ return 0;
+}
+
+void virt_driver_register(struct virt_driver *driver,
+ struct file_operations *fops)
+{
+ BUG_ON(fops->release);
+ BUG_ON(fops->open);
+ driver->f_ops = fops;
+ fops->release = virt_close;
+ mutex_lock(&driver_lock);
+ list_add(&driver->list, &driver_list);
+ mutex_unlock(&driver_lock);
+}
+EXPORT_SYMBOL_GPL(virt_driver_register);
+
+void virt_driver_unregister(struct virt_driver *driver)
+{
+ mutex_lock(&driver_lock);
+ list_del(&driver->list);
+ mutex_unlock(&driver_lock);
+}
+EXPORT_SYMBOL_GPL(virt_driver_unregister);
+
+void virt_hypervisor_register(struct virt_hypervisor *hypervisor)
+{
+ mutex_lock(&hypervisor_lock);
+ list_add(&hypervisor->list, &hypervisor_list);
+ mutex_unlock(&hypervisor_lock);
+}
+EXPORT_SYMBOL_GPL(virt_hypervisor_register);
+
+void virt_hypervisor_unregister(struct virt_hypervisor *hypervisor)
+{
+ mutex_lock(&hypervisor_lock);
+ list_del(&hypervisor->list);
+ mutex_unlock(&hypervisor_lock);
+}
+EXPORT_SYMBOL_GPL(virt_hypervisor_unregister);
+
+int virt_device_create(struct virt_hypervisor *hypervisor, int flags,
+ const u8 *id, int id_len)
+{
+ struct virt_dev *dev = kmalloc(sizeof *dev, GFP_KERNEL);
+ struct virt_driver *driver;
+ const struct file_operations *fops;
+ int ret;
+ if (!dev)
+ return -ENOMEM;
+ dev->hypervisor = hypervisor;
+ hypervisor->get(hypervisor);
+
+ mutex_lock(&driver_lock);
+ ret = -ENODEV;
+ list_for_each_entry(driver, &driver_list, list) {
+ ret = driver->device_probe(driver, dev, id, id_len);
+ if (ret != -ENODEV)
+ break;
+ }
+ mutex_unlock(&driver_lock);
+ if (ret)
+ goto err_probe;
+
+ fops = fops_get(driver->f_ops);
+ if (!fops) {
+ ret = -ENOMEM;
+ goto err_file;
+ }
+
+ ret = anon_inode_getfd(driver->name, fops, dev, flags);
+ if (ret < 0)
+ goto err_file;
+ return ret;
+err_file:
+ driver->device_remove(driver, dev);
+err_probe:
+ hypervisor->put(hypervisor);
+ kfree(dev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(virt_device_create);
diff --git a/include/linux/virt.h b/include/linux/virt.h
new file mode 100644
index 0000000..ecc0aef
--- /dev/null
+++ b/include/linux/virt.h
@@ -0,0 +1,94 @@
+#ifndef LINUX_VIRT_H
+#define LINUX_VIRT_H
+/* Virt core support.
+ * Each driver and hypervisor register with core, and then drivers can find
+ * and interfact with hypervisors through the virt_dev object.
+ */
+
+#include <linux/list.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+
+struct virt_dev;
+
+struct virt_hypervisor {
+ /* Fields set by virt core. */
+ struct list_head list;
+ /* Fields set by hypervisor. */
+ /* Operations supported by this hypervisor. */
+ /* core uses reference counting to make sure hypervisor does not
+ * go away while there are devices attached to it. */
+ void (*get)(struct virt_hypervisor *);
+ void (*put)(struct virt_hypervisor *);
+ /* Optional interrupt injection support */
+ int (*set_irq)(struct virt_hypervisor *,
+ int source, int irq, int level);
+};
+
+struct virt_driver {
+ /* Fields set by virt core. */
+ struct list_head list;
+ const struct file_operations *f_ops;
+ /* Fields set by driver. */
+ const char *name;
+ /* Check whether this driver wants this device,
+ * and bind driver to device if yes.
+ * Return -ENODEV if driver does not match this device,
+ * 0 on success, any other value is an error. */
+ int (*device_probe)(struct virt_driver *, struct virt_dev *,
+ const void *id, int id_len);
+ /* Called on removal of all devices where this driver's probe
+ * returned success */
+ void (*device_remove)(struct virt_driver *, struct virt_dev *);
+};
+
+/* Device objects are allocated and freed by virt core. */
+struct virt_dev {
+ struct virt_driver *driver;
+ void *driver_ctx;
+ struct virt_hypervisor *hypervisor;
+};
+
+/* Utility function for file_operations in drivers. */
+static inline struct virt_dev *virt_dev_get(struct file *file)
+{
+ return file->private_data;
+}
+
+#ifdef CONFIG_VIRT_CORE_MODULE
+void virt_driver_register(struct virt_driver *, struct file_operations *);
+void virt_driver_unregister(struct virt_driver *);
+
+void virt_hypervisor_register(struct virt_hypervisor *);
+void virt_hypervisor_unregister(struct virt_hypervisor *);
+
+
+/* Users add devices by making a hypervisor-specific system call (e.g. ioctl)
+ * the result of which is a file descriptor controlling the device.
+ * Hypervisors implement this by calling virt_device_create to get struct file
+ * and install it in file descriptor table. Device is later released by
+ * closing the file descriptor */
+/* Associate a file descriptor with the device and return it.
+ * Returns a value < 0 on failure. */
+int virt_device_create(struct virt_hypervisor *, int flags,
+ const u8 *id, int id_len);
+#else
+static inline
+void virt_driver_register(struct virt_driver *d, struct file_operations *o) {}
+static inline
+void virt_driver_unregister(struct virt_driver *d) {}
+
+static inline
+void virt_hypervisor_register(struct virt_hypervisor *h) {}
+static inline
+void virt_hypervisor_unregister(struct virt_hypervisor *h) {}
+
+static inline
+struct file *virt_device_create(struct virt_hypervisor *h, int flags,
+ const u8 *id, int id_len)
+{
+ return ERR_PTR(-ENOTTY);
+}
+#endif
+
+#endif
--
1.6.3.1.175.g3be7e0
next parent reply other threads:[~2009-05-31 18:59 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <cover.1243796281.git.mst@sherwood.(none)>
2009-05-31 18:59 ` Michael S. Tsirkin [this message]
2009-05-31 18:59 ` [PATCH 2/3] kvm: virtual device support Michael S. Tsirkin
2009-05-31 18:59 ` [PATCH 3/3] virt_irq: virtual device for injecting interrupts Michael S. Tsirkin
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=20090531185901.GB10043@redhat.com \
--to=mst@redhat.com \
--cc=avi@redhat.com \
--cc=ghaskins@novell.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
/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