All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
To: kvm-devel <kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: lguest <lguest-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>,
	Jens Axboe <jens.axboe-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>,
	virtualization
	<virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org>
Subject: [PATCH 5/6] virtio console driver
Date: Thu, 20 Sep 2007 22:19:21 +1000	[thread overview]
Message-ID: <1190290761.7262.242.camel@localhost.localdomain> (raw)
In-Reply-To: <1190290606.7262.239.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

This is an hvc-based virtio console driver.  It's suboptimal becuase
hvc expects to have raw access to interrupts and virtio doesn't assume
that, so it currently polls.

There are two solutions: expose hvc's "kick" interface, or wean off hvc.

Signed-off-by: Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
---
 drivers/char/Kconfig           |    4 
 drivers/char/Makefile          |    1 
 drivers/char/virtio_console.c  |  232 ++++++++++++++++++++++++++++++++++++++++
 include/linux/virtio_console.h |   12 ++
 4 files changed, 249 insertions(+)

===================================================================
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -613,6 +613,10 @@ config HVC_XEN
 	help
 	  Xen virtual console device driver
 
+config VIRTIO_CONSOLE
+	bool
+	select HVC_DRIVER
+
 config HVCS
 	tristate "IBM Hypervisor Virtual Console Server support"
 	depends on PPC_PSERIES
===================================================================
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_HVC_BEAT)		+= hvc_beat.o
 obj-$(CONFIG_HVC_BEAT)		+= hvc_beat.o
 obj-$(CONFIG_HVC_DRIVER)	+= hvc_console.o
 obj-$(CONFIG_HVC_XEN)		+= hvc_xen.o
+obj-$(CONFIG_VIRTIO_CONSOLE)	+= virtio_console.o
 obj-$(CONFIG_RAW_DRIVER)	+= raw.o
 obj-$(CONFIG_SGI_SNSC)		+= snsc.o snsc_event.o
 obj-$(CONFIG_MSPEC)		+= mspec.o
===================================================================
--- /dev/null
+++ b/drivers/char/virtio_console.c
@@ -0,0 +1,232 @@
+/*D:300
+ * The Guest console driver
+ *
+ * Writing console drivers is one of the few remaining Dark Arts in Linux.
+ * Fortunately for us, the path of virtual consoles has been well-trodden by
+ * the PowerPC folks, who wrote "hvc_console.c" to generically support any
+ * virtual console.  We use that infrastructure which only requires us to write
+ * the basic put_chars and get_chars functions and call the right register
+ * functions.
+ :*/
+
+/*M:002 The console can be flooded: while the Guest is processing input the
+ * Host can send more.  Buffering in the Host could alleviate this, but it is a
+ * difficult problem in general. :*/
+/* Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/virtio.h>
+#include <linux/virtio_console.h>
+#include "hvc_console.h"
+
+/*D:340 These represent our input and output console queues, and the virtio
+ * operations for them. */
+static struct virtqueue *in_vq, *out_vq;
+static struct virtqueue_ops *vq_ops;
+
+/* This is our input buffer, and how much data is left in it. */
+static unsigned int in_len;
+static char *in, *inbuf;
+
+/* The operations for our console. */
+static struct hv_ops virtio_cons;
+
+/*D:310 The put_chars() callback is pretty straightforward.
+ *
+ * We turn the characters into a scatter-gather list, add it to the output
+ * queue and then kick the Host.  Then we sit here waiting for it to finish:
+ * inefficient in theory, but in practice implementations will do it
+ * immediately (lguest's Launcher does). */
+static int put_chars(u32 vtermno, const char *buf, int count)
+{
+	struct scatterlist sg[1];
+	unsigned int len;
+
+	/* This is a convenient routine to initialize a single-elem sg list */
+	sg_init_one(sg, buf, count);
+
+	/* add_buf wants a token to identify this buffer: we hand it any
+	 * non-NULL pointer, since there's only ever one buffer. */
+	if (vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) == 0) {
+		/* Tell Host to go! */
+		vq_ops->kick(out_vq);
+		/* Chill out until it's done with the buffer. */
+		while (!vq_ops->get_buf(out_vq, &len))
+			cpu_relax();
+	}
+
+	/* We're expected to return the amount of data we wrote: all of it. */
+	return count;
+}
+
+/* Create a scatter-gather list representing our input buffer and put it in the
+ * queue. */
+static void add_inbuf(void)
+{
+	struct scatterlist sg[1];
+	sg_init_one(sg, inbuf, PAGE_SIZE);
+
+	/* We should always be able to add one buffer to an empty queue. */
+	if (vq_ops->add_buf(in_vq, sg, 0, 1, inbuf) != 0)
+		BUG();
+	vq_ops->kick(in_vq);
+}
+
+/*D:350 get_chars() is the callback from the hvc_console infrastructure when
+ * an interrupt is received.
+ *
+ * Most of the code deals with the fact that the hvc_console() infrastructure
+ * only asks us for 16 bytes at a time.  We keep in_offset and in_used fields
+ * for partially-filled buffers. */
+static int get_chars(u32 vtermno, char *buf, int count)
+{
+	/* If we don't have an input queue yet, we can't get input. */
+	BUG_ON(!in_vq);
+
+	/* No buffer?  Try to get one. */
+	if (!in_len) {
+		in = vq_ops->get_buf(in_vq, &in_len);
+		if (!in)
+			return 0;
+	}
+
+	/* You want more than we have to give?  Well, try wanting less! */
+	if (in_len < count)
+		count = in_len;
+
+	/* Copy across to their buffer and increment offset. */
+	memcpy(buf, in, count);
+	in += count;
+	in_len -= count;
+
+	/* Finished?  Re-register buffer so Host will use it again. */
+	if (in_len == 0)
+		add_inbuf();
+
+	return count;
+}
+/*:*/
+
+/*D:320 Console drivers are initialized very early so boot messages can go out,
+ * so we do things slightly differently from the generic virtio initialization
+ * of the net and block drivers.
+ *
+ * At this stage, the console is output-only.  It's too early to set up a
+ * virtqueue, so we let the drivers do some boutique early-output thing. */
+int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
+{
+	virtio_cons.put_chars = put_chars;
+	return hvc_instantiate(0, 0, &virtio_cons);
+}
+
+/* FIXME: This is why we want to wean off hvc: we do nothing when input comes
+ * in. */
+static bool do_nothing(void *data)
+{
+	return true;
+}
+
+/*D:370 Once we're further in boot, we get probed like any other virtio device.
+ * At this stage we set up the output virtqueue.
+ *
+ * To set up and manage our virtual console, we call hvc_alloc().  Since we
+ * never remove the console device we never need this pointer again.
+ *
+ * Finally we put our input buffer in the input queue, ready to receive. */
+static void *virtcons_probe(struct device *device,
+			    struct virtio_config_space *config,
+			    struct virtqueue_ops *new_vq_ops)
+{
+	int err;
+	struct hvc_struct *hvc;
+
+	/* This is the scratch page we use to receive console input */
+	inbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!inbuf) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	vq_ops = new_vq_ops;
+
+	/* Find the input queue. */
+	in_vq = virtio_config_vq(config, vq_ops, device, do_nothing, NULL);
+	if (IS_ERR(in_vq)) {
+		err = PTR_ERR(in_vq);
+		goto free_out_vq;
+	}
+
+	out_vq = virtio_config_vq(config, vq_ops, device, do_nothing, NULL);
+	if (IS_ERR(out_vq)) {
+		err = PTR_ERR(out_vq);
+		goto free;
+	}
+
+	/* Start using the new console output. */
+	virtio_cons.get_chars = get_chars;
+	virtio_cons.put_chars = put_chars;
+
+	/* The first argument of hvc_alloc() is the virtual console number, so
+	 * we use zero.  The second argument is the interrupt number; we
+	 * currently leave this as zero: it would be better not to use the
+	 * hvc mechanism and fix this (FIXME!).
+	 *
+	 * The third argument is a "struct hv_ops" containing the put_chars()
+	 * and get_chars() pointers.  The final argument is the output buffer
+	 * size: we can do any size, so we put PAGE_SIZE here. */
+	hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE);
+	if (IS_ERR(hvc)) {
+		err = PTR_ERR(hvc);
+		goto free_in_vq;
+	}
+
+	/* Register the input buffer the first time. */
+	add_inbuf();
+	return NULL;
+
+free_in_vq:
+	new_vq_ops->free_vq(in_vq);
+free_out_vq:
+	new_vq_ops->free_vq(out_vq);
+free:
+	kfree(inbuf);
+fail:
+	return ERR_PTR(err);
+}
+
+static struct pci_device_id id_table[] = {
+	VIRTIO_DEV_ID(VIRTIO_ID_CONSOLE, PCI_CLASS_COMMUNICATION_SERIAL),
+	{ 0 },
+};
+
+static struct virtio_driver virtio_console = {
+	.name =         KBUILD_MODNAME,
+	.owner =        THIS_MODULE,
+	.id_table =     id_table,
+	.probe =        virtcons_probe,
+};
+
+static int __init init(void)
+{
+	return register_virtio_driver(&virtio_console);
+}
+module_init(init);
+
+MODULE_DEVICE_TABLE(pci, id_table);
+MODULE_DESCRIPTION("Virtio console driver");
+MODULE_LICENSE("GPL");
===================================================================
--- /dev/null
+++ b/include/linux/virtio_console.h
@@ -0,0 +1,12 @@
+#ifndef _LINUX_VIRTIO_CONSOLE_H
+#define _LINUX_VIRTIO_CONSOLE_H
+#include <linux/virtio_config.h>
+
+/* The ID for virtio console */
+#define VIRTIO_ID_CONSOLE	3
+
+#ifdef __KERNEL__
+int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int));
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_VIRTIO_CONSOLE_H */



-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

  parent reply	other threads:[~2007-09-20 12:19 UTC|newest]

Thread overview: 79+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-20 12:03 [PATCH 0/6] virtio with config abstraction and ring implementation Rusty Russell
2007-09-20 12:09 ` [PATCH 1/6] virtio interace Rusty Russell
2007-09-20 13:43 ` [PATCH 0/6] virtio with config abstraction and ring implementation Dor Laor
     [not found] ` <1190289808.7262.223.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-20 12:09   ` [PATCH 1/6] virtio interace Rusty Russell
     [not found]     ` <1190290140.7262.228.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-20 12:12       ` [PATCH 2/6] virtio_config Rusty Russell
2007-09-20 12:14         ` [PATCH 3/6] virtio net driver Rusty Russell
2007-09-20 12:36         ` [kvm-devel] [PATCH 2/6] virtio_config Avi Kivity
     [not found]         ` <1190290369.7262.231.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-20 12:14           ` [PATCH 3/6] virtio net driver Rusty Russell
2007-09-20 12:16             ` [PATCH 4/6] virtio block driver Rusty Russell
2007-09-21 10:48             ` [kvm-devel] [PATCH 3/6] virtio net driver Christian Borntraeger
     [not found]             ` <1190290495.7262.235.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-20 12:16               ` [PATCH 4/6] virtio block driver Rusty Russell
2007-09-20 12:19                 ` [PATCH 5/6] virtio console driver Rusty Russell
     [not found]                 ` <1190290606.7262.239.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-20 12:19                   ` Rusty Russell [this message]
     [not found]                     ` <1190290761.7262.242.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-20 12:27                       ` [PATCH 6/6] virtio ring helper Rusty Russell
     [not found]                         ` <1190291234.7262.246.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-20 12:43                           ` Avi Kivity
     [not found]                             ` <46F26AF6.60904-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-21  2:04                               ` Rusty Russell
2007-09-23 10:05                                 ` [kvm-devel] " Avi Kivity
     [not found]                                 ` <1190340251.19451.36.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-23 10:05                                   ` Avi Kivity
     [not found]                                     ` <46F63A64.9070200-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-23 11:40                                       ` Rusty Russell
     [not found]                                         ` <1190547607.27805.120.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-23 11:46                                           ` Avi Kivity
2007-09-23 11:46                                         ` [kvm-devel] " Avi Kivity
2007-09-23 11:40                                     ` Rusty Russell
2007-09-21  2:04                             ` Rusty Russell
2007-09-20 12:43                         ` Avi Kivity
2007-09-20 12:27                     ` Rusty Russell
2007-09-20 12:27                   ` [PATCH 4/6] virtio block driver Jens Axboe
2007-09-21 12:00                     ` Rusty Russell
     [not found]                     ` <20070920122713.GK2367-tSWWG44O7X1aa/9Udqfwiw@public.gmane.org>
2007-09-21 12:00                       ` Rusty Russell
     [not found]                         ` <1190376007.27805.19.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-21 12:27                           ` Jens Axboe
     [not found]                             ` <20070921122746.GO2367-tSWWG44O7X1aa/9Udqfwiw@public.gmane.org>
2007-09-23  6:47                               ` Rusty Russell
2007-09-23  6:47                             ` Rusty Russell
2007-09-21 12:27                         ` Jens Axboe
2007-09-20 13:05                   ` Jens Axboe
2007-09-21  2:06                     ` Rusty Russell
2007-09-21 11:47                       ` Jens Axboe
     [not found]                       ` <1190340367.19451.40.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-21 11:47                         ` Jens Axboe
2007-09-21 12:30                           ` Rusty Russell
     [not found]                           ` <20070921114703.GN2367-tSWWG44O7X1aa/9Udqfwiw@public.gmane.org>
2007-09-21 12:30                             ` Rusty Russell
2007-09-20 12:27                 ` Jens Axboe
2007-09-20 13:05                 ` Jens Axboe
2007-09-21 10:48               ` [PATCH 3/6] virtio net driver Christian Borntraeger
2007-09-21 11:53                 ` [kvm-devel] " Rusty Russell
     [not found]                 ` <200709211248.11783.borntraeger-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
2007-09-21 11:53                   ` Rusty Russell
2007-09-21 12:36                     ` [kvm-devel] " Christian Borntraeger
     [not found]                     ` <1190375615.27805.9.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-21 12:36                       ` Christian Borntraeger
     [not found]                         ` <200709211436.43964.borntraeger-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
2007-09-21 14:08                           ` Herbert Xu
     [not found]                             ` <20070921140833.GA12242-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org>
2007-09-21 14:42                               ` Christian Borntraeger
     [not found]                                 ` <200709211642.25208.borntraeger-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
2007-09-23  7:13                                   ` Rusty Russell
2007-09-23  7:13                                 ` [kvm-devel] " Rusty Russell
2007-09-21 14:42                             ` Christian Borntraeger
2007-09-21 14:08                         ` Herbert Xu
2007-09-20 12:36           ` [PATCH 2/6] virtio_config Avi Kivity
2007-09-20 12:55             ` [kvm-devel] " Avi Kivity
     [not found]             ` <46F26958.4080102-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-20 12:55               ` Avi Kivity
2007-09-21  1:50                 ` [kvm-devel] " Rusty Russell
     [not found]                 ` <46F26DC7.9040001-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-21  1:50                   ` Rusty Russell
2007-09-22 13:03                     ` [kvm-devel] " Avi Kivity
     [not found]                     ` <1190339435.19451.23.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-22 13:03                       ` Avi Kivity
2007-09-20 12:27       ` [PATCH 1/6] virtio interace Avi Kivity
2007-09-21 11:37         ` [kvm-devel] " Rusty Russell
2007-09-21 12:05       ` Arnd Bergmann
2007-09-21 12:45         ` Rusty Russell
     [not found]         ` <200709211405.32116.arnd-r2nGTMty4D4@public.gmane.org>
2007-09-21 12:45           ` Rusty Russell
     [not found]             ` <1190378736.27805.54.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-21 14:22               ` Arnd Bergmann
2007-09-22  9:55                 ` Rusty Russell
     [not found]                   ` <1190454934.27805.80.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-22 10:01                     ` Arnd Bergmann
2007-09-23  8:33                       ` Rusty Russell
     [not found]                       ` <200709221201.33865.arnd-r2nGTMty4D4@public.gmane.org>
2007-09-23  8:33                         ` Rusty Russell
     [not found]                           ` <1190536431.27805.109.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-23 11:20                             ` Dor Laor
2007-09-23 11:20                           ` Dor Laor
2007-09-22 10:01                   ` Arnd Bergmann
2007-09-21 14:22             ` Arnd Bergmann
2007-09-20 12:12     ` [PATCH 2/6] virtio_config Rusty Russell
2007-09-20 12:27     ` [kvm-devel] [PATCH 1/6] virtio interace Avi Kivity
2007-09-21 12:05     ` Arnd Bergmann
2007-09-20 13:43   ` [PATCH 0/6] virtio with config abstraction and ring implementation Dor Laor
     [not found]     ` <46F2791A.8070601-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-20 13:50       ` [Lguest] [PATCH 0/6] virtio with config abstraction and ringimplementation Dor Laor
2007-09-20 13:50     ` Dor Laor
2007-09-21  3:20     ` [PATCH 0/6] virtio with config abstraction and ring implementation Rusty Russell

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=1190290761.7262.242.camel@localhost.localdomain \
    --to=rusty-8n+1lvoiyb80n/f98k4iww@public.gmane.org \
    --cc=jens.axboe-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org \
    --cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    --cc=lguest-mnsaURCQ41sdnm+yROfE0A@public.gmane.org \
    --cc=virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.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 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.