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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.