From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LNYJy-0007Sf-IQ for qemu-devel@nongnu.org; Thu, 15 Jan 2009 14:56:06 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LNYJx-0007SO-Rm for qemu-devel@nongnu.org; Thu, 15 Jan 2009 14:56:06 -0500 Received: from [199.232.76.173] (port=43812 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LNYJx-0007SJ-L4 for qemu-devel@nongnu.org; Thu, 15 Jan 2009 14:56:05 -0500 Received: from mail-qy0-f20.google.com ([209.85.221.20]:40213) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LNYJx-0008Ae-5o for qemu-devel@nongnu.org; Thu, 15 Jan 2009 14:56:05 -0500 Received: by qyk13 with SMTP id 13so1887590qyk.10 for ; Thu, 15 Jan 2009 11:56:03 -0800 (PST) Message-ID: <496F94C7.4080304@codemonkey.ws> Date: Thu, 15 Jan 2009 13:55:51 -0600 From: Anthony Liguori MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH 1 of 4] kvm-userpace: add virtio-console support References: <50f40bc14f793a5f4ce6.1231861065@HelionPrime> In-Reply-To: <50f40bc14f793a5f4ce6.1231861065@HelionPrime> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: ehrhardt@linux.vnet.ibm.com, aliguori@us.ibm.com, borntraeger@de.ibm.com Christian Ehrhardt wrote: > # HG changeset patch > # User Christian Ehrhardt > # Date 1231855865 -3600 > # Node ID 50f40bc14f793a5f4ce6d91c36a3f3b19b507d42 > # Parent 89ed96e77993639b89d41a1a113ccbef979adfb9 > kvm-userpace: add virtio-console support > > This patch adds the virtio console to qemu. This console can be found after the > serial and parallel outputs as another virtual console. In the -nographic case > it is redirected to the null output by default. > > Signed-off-by: Christian Ehrhardt > Please submit this against QEMU, not kvm-userspace. Regards, Anthony Liguori > --- > Makefile.target | 2 > hw/virtio-console.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > hw/virtio-console.h | 22 +++++++ > sysemu.h | 6 ++ > vl.c | 26 +++++++++ > 5 files changed, 202 insertions(+), 1 deletion(-) > > diff --git a/Makefile.target b/Makefile.target > --- a/Makefile.target > +++ b/Makefile.target > @@ -559,7 +559,7 @@ OBJS=vl.o osdep.o monitor.o pci.o loader > OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o > # virtio has to be here due to weird dependency between PCI and virtio-net. > # need to fix this properly > -OBJS+=virtio.o virtio-blk.o virtio-balloon.o virtio-net.o > +OBJS+=virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o > OBJS+=fw_cfg.o > ifdef CONFIG_KVM > OBJS+=kvm.o kvm-all.o > diff --git a/hw/virtio-console.c b/hw/virtio-console.c > new file mode 100644 > --- /dev/null > +++ b/hw/virtio-console.c > @@ -0,0 +1,147 @@ > +/* > + * Virtio Console Device > + * > + * Copyright IBM, Corp. 2008 > + * > + * Authors: > + * Christian Ehrhardt > + * > + * This work is licensed under the terms of the GNU GPL, version 2. See > + * the COPYING file in the top-level directory. > + * > + */ > + > +#include "hw.h" > +#include "qemu-char.h" > +#include "virtio.h" > +#include "virtio-console.h" > + > + > +typedef struct VirtIOConsole > +{ > + VirtIODevice vdev; > + VirtQueue *ivq, *dvq; > + CharDriverState *chr; > +} VirtIOConsole; > + > +static VirtIOConsole *to_virtio_console(VirtIODevice *vdev) > +{ > + return (VirtIOConsole *)vdev; > +} > + > +static void virtio_console_handle_output(VirtIODevice *vdev, VirtQueue *vq) > +{ > + VirtIOConsole *s = to_virtio_console(vdev); > + VirtQueueElement elem; > + > + while (virtqueue_pop(vq, &elem)) { > + ssize_t len = 0; > + int d; > + > + for (d=0; d < elem.out_num; d++) > + len += qemu_chr_write(s->chr, elem.out_sg[d].iov_base,elem.out_sg[d].iov_len); > + virtqueue_push(vq, &elem, len); > + virtio_notify(vdev, vq); > + } > +} > + > +static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq) > +{ > +} > + > +static uint32_t virtio_console_get_features(VirtIODevice *vdev) > +{ > + return 0; > +} > + > +static int vcon_can_read(void *opaque) > +{ > + VirtIOConsole *s = (VirtIOConsole *) opaque; > + > + if (!virtio_queue_ready(s->ivq) || > + !(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) || > + virtio_queue_empty(s->ivq)) > + return 0; > + > + /* current implementations have a page sized buffer. > + * We fall back to a one byte per read if there is not enough room. > + * It would be cool to have a function that returns the available byte > + * instead of checking for a limit */ > + if (virtqueue_avail_bytes(s->ivq, TARGET_PAGE_SIZE, 0)) > + return TARGET_PAGE_SIZE; > + if (virtqueue_avail_bytes(s->ivq, 1, 0)) > + return 1; > + return 0; > +} > + > +static void vcon_read(void *opaque, const uint8_t *buf, int size) > +{ > + VirtIOConsole *s = (VirtIOConsole *) opaque; > + VirtQueueElement elem; > + int offset = 0; > + > + /* The current kernel implementation has only one outstanding input > + * buffer of PAGE_SIZE. Nevertheless, this function is prepared to > + * handle multiple buffers with multiple sg element for input */ > + while (offset < size) { > + int i = 0; > + if (!virtqueue_pop(s->ivq, &elem)) > + break; > + while (offset < size && i < elem.in_num) { > + int len = MIN(elem.in_sg[i].iov_len, size - offset); > + memcpy(elem.in_sg[i].iov_base, buf + offset, len); > + offset += len; > + i++; > + } > + virtqueue_push(s->ivq, &elem, size); > + } > + virtio_notify(&s->vdev, s->ivq); > +} > + > +static void vcon_event(void *opaque, int event) > +{ > + /* we will ignore any event for the time being */ > +} > + > +static void virtio_console_save(QEMUFile *f, void *opaque) > +{ > + VirtIOConsole *s = opaque; > + > + virtio_save(&s->vdev, f); > +} > + > +static int virtio_console_load(QEMUFile *f, void *opaque, int version_id) > +{ > + VirtIOConsole *s = opaque; > + > + if (version_id != 1) > + return -EINVAL; > + > + virtio_load(&s->vdev, f); > + return 0; > +} > + > +void *virtio_console_init(PCIBus *bus, CharDriverState *chr) > +{ > + VirtIOConsole *s; > + > + s = (VirtIOConsole *)virtio_init_pci(bus, "virtio-console", > + 6900, 0x1003, > + 0, VIRTIO_ID_CONSOLE, > + 0x03, 0x80, 0x00, > + 0, sizeof(VirtIOConsole)); > + if (s == NULL) > + return NULL; > + > + s->vdev.get_features = virtio_console_get_features; > + > + s->ivq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_input); > + s->dvq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_output); > + > + s->chr = chr; > + qemu_chr_add_handlers(chr, vcon_can_read, vcon_read, vcon_event, s); > + > + register_savevm("virtio-console", -1, 1, virtio_console_save, virtio_console_load, s); > + > + return &s->vdev; > +} > diff --git a/hw/virtio-console.h b/hw/virtio-console.h > new file mode 100644 > --- /dev/null > +++ b/hw/virtio-console.h > @@ -0,0 +1,22 @@ > +/* > + * Virtio Console Support > + * > + * Copyright IBM, Corp. 2008 > + * > + * Authors: > + * Christian Ehrhardt > + * > + * This work is licensed under the terms of the GNU GPL, version 2. See > + * the COPYING file in the top-level directory. > + * > + */ > +#ifndef _QEMU_VIRTIO_CONSOLE_H > +#define _QEMU_VIRTIO_CONSOLE_H > + > +/* The ID for virtio console */ > +#define VIRTIO_ID_CONSOLE 3 > + > +/* Creates a virtio console */ > +void *virtio_console_init(PCIBus *bus, CharDriverState *chr); > + > +#endif > diff --git a/sysemu.h b/sysemu.h > --- a/sysemu.h > +++ b/sysemu.h > @@ -158,6 +158,12 @@ extern CharDriverState *serial_hds[MAX_S > > extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; > > +/* virtio consoles */ > + > +#define MAX_VIRTIO_CONSOLES 1 > + > +extern CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; > + > #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) > > #ifdef NEED_CPU_H > diff --git a/vl.c b/vl.c > --- a/vl.c > +++ b/vl.c > @@ -209,6 +209,7 @@ int no_quit = 0; > int no_quit = 0; > CharDriverState *serial_hds[MAX_SERIAL_PORTS]; > CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; > +CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; > #ifdef TARGET_I386 > int win2k_install_hack = 0; > #endif > @@ -4502,6 +4503,8 @@ int main(int argc, char **argv, char **e > int serial_device_index; > const char *parallel_devices[MAX_PARALLEL_PORTS]; > int parallel_device_index; > + const char *virtio_consoles[MAX_VIRTIO_CONSOLES]; > + int virtio_console_index; > const char *loadvm = NULL; > QEMUMachine *machine; > const char *cpu_model; > @@ -4574,6 +4577,11 @@ int main(int argc, char **argv, char **e > for(i = 1; i < MAX_PARALLEL_PORTS; i++) > parallel_devices[i] = NULL; > parallel_device_index = 0; > + > + virtio_consoles[0] = "vc:80Cx24C"; > + for(i = 1; i < MAX_VIRTIO_CONSOLES; i++) > + virtio_consoles[i] = NULL; > + virtio_console_index = 0; > > usb_devices_index = 0; > > @@ -5170,6 +5178,8 @@ int main(int argc, char **argv, char **e > parallel_devices[0] = "null"; > if (strncmp(monitor_device, "vc", 2) == 0) > monitor_device = "stdio"; > + if (virtio_console_index == 0) > + virtio_consoles[0] = "null"; > } > > #ifndef _WIN32 > @@ -5464,6 +5474,22 @@ int main(int argc, char **argv, char **e > } > } > > + for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { > + const char *devname = virtio_consoles[i]; > + if (devname && strcmp(devname, "none")) { > + char label[32]; > + snprintf(label, sizeof(label), "virtcon%d", i); > + virtcon_hds[i] = qemu_chr_open(label, devname); > + if (!virtcon_hds[i]) { > + fprintf(stderr, "qemu: could not open virtio console '%s'\n", > + devname); > + exit(1); > + } > + if (strstart(devname, "vc", 0)) > + qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i); > + } > + } > + > if (kvm_enabled()) { > int ret; > > > >