All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Gregory Haskins <ghaskins@novell.com>
Cc: kvm@vger.kernel.org, rusty@rustcorp.com.au
Subject: Re: [PATCH] virtio: add a virtio-console to the vbus backend
Date: Sun, 7 Jun 2009 01:02:30 +0300	[thread overview]
Message-ID: <20090606220230.GE28614@redhat.com> (raw)
In-Reply-To: <20090605192648.19271.68909.stgit@dev.haskins.net>

On Fri, Jun 05, 2009 at 03:30:07PM -0400, Gregory Haskins wrote:
> Hi Michael,
>   FYI: This was a patch I started to put together around the time vbus-v3 was
>   released to demonstrate the interface for virtio devices that we needed.  I
>   just wanted to get it out to you so you have a working example to look at
>   what it takes to write something like virtio-net against virtio-vbus.
> 
>   What I will do next is make a minor v3.1 release of vbus on top of kvm.git
>   and get this patch cleaned up so we can actually run it.  Note that v3.1
>   will just a minor port of v3 to kvm.git/HEAD, not the new iosignalfd/irqfd
>   stuff that I have queued for v4.  Thats not ready for prime-time yet.
> 
> ----------------------------
> 
> virtio: add a virtio-console to the vbus backend
> 
> A console probably doesnt need to live in the kernel since it is generally
> not performance limited.  However, its also a very simple example, so lets
> make a vbus backend to demonstrate the virtio interfaces.
> 
> Signed-off-by: Gregory Haskins <ghaskins@novell.com>

I'm a bit confused: does this live on the guest or host side?




> ---
> 
>  drivers/vbus/devices/Kconfig                  |    9 
>  drivers/vbus/devices/Makefile                 |    1 
>  drivers/vbus/devices/virtio-console-backend.c |  461 +++++++++++++++++++++++++
>  3 files changed, 471 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/vbus/devices/virtio-console-backend.c
> 
> diff --git a/drivers/vbus/devices/Kconfig b/drivers/vbus/devices/Kconfig
> index 64e4731..0239e86 100644
> --- a/drivers/vbus/devices/Kconfig
> +++ b/drivers/vbus/devices/Kconfig
> @@ -15,3 +15,12 @@ config VBUS_VENETTAP
>  
>  	If unsure, say N
>  
> +config VBUS_VIRTIO_CONSOLE
> +       tristate "Virtual-Bus Backend for virtio-console drivers"
> +       depends on VBUS_DEVICES
> +       select VBUS_VIRTIO_BACKEND
> +       default n
> +       help
> +        Provides a virtual console device within the vbus infrastructure
> +
> +	If unsure, say N
> diff --git a/drivers/vbus/devices/Makefile b/drivers/vbus/devices/Makefile
> index 2ea7d2a..fd51cb6 100644
> --- a/drivers/vbus/devices/Makefile
> +++ b/drivers/vbus/devices/Makefile
> @@ -1 +1,2 @@
>  obj-$(CONFIG_VBUS_VENETTAP) += venet-tap.o
> +obj-$(CONFIG_VBUS_VIRTIO_CONSOLE) += virtio-console-backend.o
> diff --git a/drivers/vbus/devices/virtio-console-backend.c b/drivers/vbus/devices/virtio-console-backend.c
> new file mode 100644
> index 0000000..bf30016
> --- /dev/null
> +++ b/drivers/vbus/devices/virtio-console-backend.c
> @@ -0,0 +1,461 @@
> +/*
> + * virtio-console for the vbus backend
> + *
> + * Copyright (C) 2009 Novell, Gregory Haskins <ghaskins@novell.com>
> + *
> + * This file is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software Foundation,
> + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/moduleparam.h>
> +
> +#include <linux/cdev.h>
> +#include <linux/fs.h>
> +#include <linux/major.h>
> +
> +#include <linux/vbus_device.h>
> +#include <linux/virtio_vbus.h>
> +#include <linux/virtio_console.h>
> +
> +MODULE_AUTHOR("Gregory Haskins");
> +MODULE_LICENSE("GPL");
> +
> +#undef PDEBUG             /* undef it, just in case */
> +#ifdef VIRTIO_CONSOLE_DEBUG
> +#  define PDEBUG(fmt, args...) printk(KERN_DEBUG "virtio-console: " fmt, ## args)
> +#else
> +#  define PDEBUG(fmt, args...) /* not debugging: nothing */
> +#endif
> +
> +struct _virtio_console {
> +	spinlock_t                     lock;
> +	char                          *name;
> +	dev_t                          devno;
> +	struct cdev                    cdev;
> +	struct vbus_device             dev;
> +	struct virtio_device_interface intf;
> +	struct virtio_connection       conn;
> +	struct vbus_memctx            *ctx;
> +	struct virtqueue              *rx;
> +	struct virtqueue              *tx;
> +	int                            enabled:1;
> +	int                            connected:1;
> +	int                            opened:1;
> +	int                            tty:1;
> +	int                            link:1;
> +};
> +
> +static struct _virtio_console *
> +conn_to_priv(struct virtio_connection *conn)
> +{
> +	return container_of(conn, struct _virtio_console, conn);
> +}
> +
> +static struct _virtio_console *
> +intf_to_priv(struct virtio_device_interface *intf)
> +{
> +	return container_of(intf, struct _virtio_console, intf);
> +}
> +
> +static struct _virtio_console *
> +vdev_to_priv(struct vbus_device *vdev)
> +{
> +	return container_of(vdev, struct _virtio_console, dev);
> +}
> +
> +/*
> + * --------------------------------------------
> + * Driver connection
> + * --------------------------------------------
> + */
> +
> +static void
> +_virtio_console_add_vq(struct virtio_connection *vconn, int index,
> +		       struct virtqueue *vq)
> +{
> +	struct _virtio_console *priv = conn_to_priv(vconn);
> +
> +	switch (index) {
> +	case 0:
> +		if (!priv->rx)
> +			priv->rx = vq;
> +		break;
> +	case 1:
> +		if (!priv->tx)
> +			priv->tx = vq;
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +static void
> +_virtio_console_del_vq(struct virtio_connection *vconn, int index)
> +{
> +	struct _virtio_console *priv = conn_to_priv(vconn);
> +
> +	switch (index) {
> +	case 0:
> +		priv->rx = NULL;
> +		break;
> +	case 1:
> +		priv->tx = NULL;
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +static void
> +_virtio_console_notify_vq(struct virtio_connection *vconn, int index)
> +{
> +
> +}
> +
> +/*
> + * This is called whenever the driver closes all references to our device
> + */
> +static void
> +_virtio_console_release(struct virtio_connection *conn)
> +{
> +	struct _virtio_console *priv = conn_to_priv(conn);
> +
> +	priv->opened = false;
> +	vbus_memctx_put(priv->ctx);
> +}
> +
> +static struct virtio_connection_ops virtio_console_connection_ops = {
> +	.add_vq            = _virtio_console_add_vq,
> +	.del_vq            = _virtio_console_del_vq,
> +	.notify_vq         = _virtio_console_notify_vq,
> +	.release           = _virtio_console_release,
> +};
> +
> +/*
> + * --------------------------------------------
> + * Interface
> + * --------------------------------------------
> + */
> +
> +/*
> + * This is called whenever a driver wants to open our device_interface
> + * for communication.  The connection is represented by a
> + * virtio_connection object.  It is up to the implementation to decide
> + * if it allows more than one connection at a time.  This simple example
> + * does not.
> + */
> +static int
> +virtio_console_intf_open(struct virtio_device_interface *intf,
> +			 struct vbus_memctx *ctx,
> +			 struct virtio_connection **conn)
> +{
> +	struct _virtio_console *priv = intf_to_priv(intf);
> +	unsigned long flags;
> +
> +	PDEBUG("open\n");
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +
> +	/*
> +	 * We only allow one connection to this device
> +	 */
> +	if (priv->opened) {
> +		spin_unlock_irqrestore(&priv->lock, flags);
> +		return -EBUSY;
> +	}
> +
> +	memset(&priv->conn, 0, sizeof(priv->conn));
> +	priv->conn.ops = &virtio_console_connection_ops;
> +
> +	priv->opened = true;
> +	priv->ctx = ctx;
> +
> +	vbus_memctx_get(ctx);
> +
> +	spin_unlock_irqrestore(&priv->lock, flags);
> +
> +	*conn = &priv->conn;
> +
> +	return 0;
> +}
> +
> +static void
> +virtio_console_intf_release(struct virtio_device_interface *intf)
> +{
> +	kobject_put(intf->parent->dev->kobj); /* acquired on bus-connect */
> +}
> +
> +static struct virtio_device_interface_ops virtio_console_intf_ops = {
> +	.open    = virtio_console_intf_open,
> +	.release = virtio_console_intf_release,
> +};
> +
> +/*
> + * --------------------------------------------
> + * Bus+Device interaction
> + * --------------------------------------------
> + */
> +
> +/*
> + * This is called whenever the admin creates a symbolic link between
> + * a bus in /config/vbus/buses and our device.  It represents a bus
> + * connection.  Your device can chose to allow more than one bus to
> + * connect, or it can restrict it to one bus.  It can also choose to
> + * register one or more device_interfaces on each bus that it
> + * successfully connects to.
> + *
> + * This example device only registers a single interface
> + */
> +static int
> +virtio_console_device_bus_connect(struct vbus_device *dev, struct vbus *vbus)
> +{
> +	struct _virtio_console *priv = vdev_to_priv(dev);
> +	struct virtio_device_interface *intf = &priv->intf;
> +
> +	/* We only allow one bus to connect */
> +	if (priv->connected)
> +		return -EBUSY;
> +
> +	kobject_get(dev->kobj); /* released when we release the intf */
> +
> +	intf->id.vendor = 0x1af4;
> +	intf->id.device = VIRTIO_ID_CONSOLE;
> +
> +	intf->ops = &virtio_console_intf_ops;
> +
> +	priv->connected = true;
> +
> +	/*
> +	 * Our example only registers one interface.  If you need
> +	 * more, simply call interface_register() multiple times
> +	 */
> +	return virtio_device_interface_register(dev, vbus, intf);
> +}
> +
> +/*
> + * This is called whenever the admin removes the symbolic link between
> + * a bus in /config/vbus/buses and our device.
> + */
> +static int
> +virtio_console_device_bus_disconnect(struct vbus_device *dev, struct vbus *vbus)
> +{
> +	struct _virtio_console *priv = vdev_to_priv(dev);
> +	struct virtio_device_interface *intf = &priv->intf;
> +
> +	if (!priv->connected)
> +		return -EINVAL;
> +
> +	virtio_device_interface_unregister(intf);
> +
> +	priv->connected = false;
> +
> +	return 0;
> +}
> +
> +static void
> +virtio_console_device_release(struct vbus_device *dev)
> +{
> +	struct _virtio_console *priv = vdev_to_priv(dev);
> +
> +	unregister_chrdev_region(priv->devno, 1);
> +	kfree(priv);
> +
> +	module_put(THIS_MODULE);
> +}
> +
> +
> +static struct vbus_device_ops virtio_console_device_ops = {
> +	.bus_connect    = virtio_console_device_bus_connect,
> +	.bus_disconnect = virtio_console_device_bus_disconnect,
> +	.release        = virtio_console_device_release,
> +};
> +
> +#define VIRTIO_CONSOLE_TYPE "virtio-console"
> +
> +/*
> + * --------------------------------------------
> + * Character Device
> + * --------------------------------------------
> + */
> +
> +static int
> +virtio_console_chardev_open(struct inode *inode, struct file *filp)
> +{
> +	struct _virtio_console *priv;
> +
> +	priv = container_of(inode->i_cdev, struct _virtio_console, cdev);
> +
> +	kobject_get(priv->dev.kobj); /* released when we release the cd */
> +	filp->private_data = priv;
> +
> +	return 0;
> +}
> +
> +static ssize_t
> +virtio_console_chardev_read(struct file *filp, char __user *buf, size_t len,
> +			    loff_t *ppos)
> +{
> +	struct _virtio_console *priv = filp->private_data;
> +
> +	return -EINVAL;
> +}
> +
> +static ssize_t
> +virtio_console_chardev_write(struct file *filp, const char __user *buf,
> +			     size_t len, loff_t *ppos)
> +{
> +	struct _virtio_console *priv = filp->private_data;
> +
> +	return -EINVAL;
> +}
> +
> +static int
> +virtio_console_chardev_release(struct inode *inode, struct file *filp)
> +{
> +	struct _virtio_console *priv = filp->private_data;
> +
> +	kobject_put(priv->dev.kobj);
> +
> +	return 0;
> +}
> +
> +static const struct file_operations virtio_console_chardev_ops = {
> +	.open    = virtio_console_chardev_open,
> +	.read    = virtio_console_chardev_read,
> +	.write   = virtio_console_chardev_write,
> +	.release = virtio_console_chardev_release,
> +};
> +
> +/*
> + * --------------------------------------------
> + * Attributes
> + * --------------------------------------------
> + */
> +
> +/*
> + * Interface attributes show up as files under
> + * /sys/vbus/devices/$devid
> + */
> +
> +static ssize_t
> +devno_show(struct vbus_device *dev, struct vbus_device_attribute *attr,
> +	   char *buf)
> +{
> +	struct _virtio_console *priv = vdev_to_priv(dev);
> +
> +	return snprintf(buf, PAGE_SIZE, "%d:%d\n",
> +			MAJOR(priv->devno), MINOR(priv->devno));
> +}
> +
> +static struct vbus_device_attribute attr_devno =
> +	__ATTR_RO(devno);
> +
> +static struct attribute *attrs[] = {
> +	&attr_devno.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group virtio_console_attr_group = {
> +	.attrs = attrs,
> +};
> +
> +/*
> + * --------------------------------------------
> + * Device
> + * --------------------------------------------
> + */
> +
> +/*
> + * This is called whenever the admin instantiates our devclass via
> + * "mkdir /config/vbus/devices/$(inst)/virtio-console"
> + */
> +static int
> +virtio_console_device_create(struct vbus_devclass *dc,
> +			     struct vbus_device **vdev)
> +{
> +	struct _virtio_console *priv;
> +	struct vbus_device *_vdev;
> +	int ret;
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	spin_lock_init(&priv->lock);
> +
> +	/*
> +	 * cdev init
> +	 */
> +	ret = alloc_chrdev_region(&priv->devno, TTY_MAJOR,
> +				  1, VIRTIO_CONSOLE_TYPE);
> +	if (ret < 0)
> +		goto out_free;
> +
> +	cdev_init(&priv->cdev, &virtio_console_chardev_ops);
> +	priv->cdev.owner = THIS_MODULE;
> +	priv->cdev.ops = &virtio_console_chardev_ops;
> +	ret = cdev_add(&priv->cdev, priv->devno, 1);
> +	if (ret < 0)
> +		goto out;
> +
> +	/*
> +	 * vbus init
> +	 */
> +	_vdev = &priv->dev;
> +
> +	_vdev->type            = VIRTIO_CONSOLE_TYPE;
> +	_vdev->ops             = &virtio_console_device_ops;
> +	_vdev->attrs           = &virtio_console_attr_group;
> +
> +	*vdev = _vdev;
> +
> +	/*
> +	 * We don't need a try_get because the reference is held by the
> +	 * infrastructure during a create() operation.  This is released
> +	 * when our device is released
> +	 */
> +	__module_get(THIS_MODULE);
> +
> +	return 0;
> +
> +out:
> +	unregister_chrdev_region(priv->devno, 1);
> +out_free:
> +	kfree(priv);
> +	return ret;
> +}
> +
> +static struct vbus_devclass_ops virtio_console_devclass_ops = {
> +	.create = virtio_console_device_create,
> +};
> +
> +static struct vbus_devclass virtio_console_devclass = {
> +	.name  = VIRTIO_CONSOLE_TYPE,
> +	.ops   = &virtio_console_devclass_ops,
> +	.owner = THIS_MODULE,
> +};
> +
> +static int __init virtio_console_init(void)
> +{
> +	return vbus_devclass_register(&virtio_console_devclass);
> +}
> +
> +static void __exit virtio_console_cleanup(void)
> +{
> +	vbus_devclass_unregister(&virtio_console_devclass);
> +}
> +
> +module_init(virtio_console_init);
> +module_exit(virtio_console_cleanup);

-- 
MST

  parent reply	other threads:[~2009-06-06 22:03 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-05 19:30 [PATCH] virtio: add a virtio-console to the vbus backend Gregory Haskins
2009-06-06 21:04 ` Michael S. Tsirkin
2009-06-06 22:02 ` Michael S. Tsirkin [this message]
2009-06-07  0:31   ` Gregory Haskins
2009-06-07  1:38     ` Gregory Haskins

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=20090606220230.GE28614@redhat.com \
    --to=mst@redhat.com \
    --cc=ghaskins@novell.com \
    --cc=kvm@vger.kernel.org \
    --cc=rusty@rustcorp.com.au \
    /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.