qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 1 of 4] kvm-userpace: add virtio-console support


From: Christian Ehrhardt
Subject: [Qemu-devel] [PATCH 1 of 4] kvm-userpace: add virtio-console support
Date: Tue, 13 Jan 2009 16:37:45 +0100

# HG changeset patch
# User Christian Ehrhardt <address@hidden>
# 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 <address@hidden>
---
 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 <address@hidden>
+ *
+ * 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 <address@hidden>
+ *
+ * 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;
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]