* [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
@ 2009-11-02 22:11 ` Alexander Graf
0 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-02 22:11 UTC (permalink / raw)
To: kvm; +Cc: qemu-devel, linux-fbdev-devel, anthony
Since Linux now understands how to talk to us graphics over VirtIO, let's
add support for it in qemu.
The good part about graphics over VirtIO is that you don't need PCI to use
it. So if there's any platform out there trying to use graphics, but not
capable of MMIO, it can use this one!
Signed-off-by: Alexander Graf <agraf@suse.de>
---
Makefile.target | 1 +
hw/virtio-fb.c | 434 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio.h | 1 +
3 files changed, 436 insertions(+), 0 deletions(-)
create mode 100644 hw/virtio-fb.c
diff --git a/Makefile.target b/Makefile.target
index fefd7ac..260a6a8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -158,6 +158,7 @@ obj-y = vl.o async.o monitor.o pci.o machine.o gdbstub.o
# virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
+obj-y += virtio-fb.o
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
LIBS+=-lz
diff --git a/hw/virtio-fb.c b/hw/virtio-fb.c
new file mode 100644
index 0000000..c41d3bb
--- /dev/null
+++ b/hw/virtio-fb.c
@@ -0,0 +1,434 @@
+/*
+ * Virtio Frame Buffer Device
+ *
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
+ *
+ * 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 "console.h"
+#include "virtio.h"
+
+#define VIRTIO_ID_FB 6
+
+typedef struct VirtIOFB
+{
+ VirtIODevice vdev;
+ DisplayState *ds;
+ VirtQueue *vq_in;
+ VirtQueue *vq_out;
+} VirtIOFB;
+
+/* guest -> Host commands */
+#define VIRTIO_FB_CMD_RESIZE 0x01
+#define VIRTIO_FB_CMD_FILL 0x02
+#define VIRTIO_FB_CMD_BLIT 0x03
+#define VIRTIO_FB_CMD_COPY 0x04
+#define VIRTIO_FB_CMD_WRITE 0x05
+
+/* host -> guest commands */
+#define VIRTIO_FB_CMD_REFRESH 0x81
+
+#define ROP_COPY 0
+#define ROP_XOR 1
+
+#define BITS_PER_PIXEL 32
+#define BYTES_PER_PIXEL (BITS_PER_PIXEL / 8)
+
+struct virtio_fb_cmd {
+ uint8_t cmd;
+ union {
+ struct {
+ uint16_t width;
+ uint16_t height;
+ } resize __attribute__ ((packed));
+ struct {
+ uint16_t x;
+ uint16_t y;
+ uint16_t width;
+ uint16_t height;
+ } blit __attribute__ ((packed));
+ struct {
+ uint16_t x1;
+ uint16_t y1;
+ uint16_t x2;
+ uint16_t y2;
+ uint16_t width;
+ uint16_t height;
+ } copy_area __attribute__ ((packed));
+ struct {
+ uint8_t rop;
+ uint16_t x;
+ uint16_t y;
+ uint16_t width;
+ uint16_t height;
+ uint32_t color;
+ } fill __attribute__ ((packed));
+ struct {
+ uint64_t offset;
+ uint64_t count;
+ } write __attribute__ ((packed));
+ uint8_t pad[31];
+ };
+
+ uint8_t data[];
+} __attribute__ ((packed));
+
+static VirtIOFB *to_virtio_fb(VirtIODevice *vdev)
+{
+ return (VirtIOFB *)vdev;
+}
+
+static uint32_t virtio_fb_get_features(VirtIODevice *vdev)
+{
+ return 0;
+}
+
+static int virtio_fb_send(struct VirtIOFB *s, struct virtio_fb_cmd *cmd,
+ uint8_t *data, int len_data)
+{
+ int len_cmd = sizeof(*cmd);
+ int len_all = len_cmd + len_data;
+ VirtQueueElement elem;
+ int i = 0;
+
+ if (!virtio_queue_ready(s->vq_in))
+ return -1;
+
+ if (!virtqueue_pop(s->vq_in, &elem)) {
+ fprintf(stderr, "virtio-fb: queue lacking elements\n");
+ return -1;
+ }
+
+ if (elem.in_num < 1) {
+ fprintf(stderr, "virtio-fb: queue lacking sg's\n");
+ return -1;
+ }
+
+ if (elem.in_sg[i].iov_len < len_all) {
+ fprintf(stderr, "virtio-fb: buffer too small\n");
+ return -1;
+ }
+
+ if (len_data && !data) {
+ fprintf(stderr, "virtio-fb: passed no data but data length?!\n");
+ return -EINVAL;
+ }
+
+ memcpy(elem.in_sg[i].iov_base, cmd, len_cmd);
+ if (len_data)
+ memcpy(elem.in_sg[i].iov_base + len_cmd, data, len_data);
+
+ virtqueue_push(s->vq_in, &elem, len_all);
+ virtio_notify(&s->vdev, s->vq_in);
+
+ return 0;
+}
+
+/* QEMU display state changed, so refresh the framebuffer copy */
+static void virtio_fb_invalidate(void *opaque)
+{
+ struct VirtIOFB *s = opaque;
+ struct virtio_fb_cmd cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = VIRTIO_FB_CMD_REFRESH;
+
+ virtio_fb_send(s, &cmd, NULL, 0);
+ dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_width(s->ds));
+}
+
+static void virtio_fb_save(QEMUFile *f, void *opaque)
+{
+ VirtIOFB *s = opaque;
+
+ virtio_save(&s->vdev, f);
+}
+
+static int virtio_fb_load(QEMUFile *f, void *opaque, int version_id)
+{
+ VirtIOFB *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ virtio_load(&s->vdev, f);
+ return 0;
+}
+
+static void virtio_fb_handle_input(VirtIODevice *vdev, VirtQueue *vq)
+{
+}
+
+static void virtio_fb_handle_resize(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+ uint16_t width = tswap16(cmd->resize.width);
+ uint16_t height = tswap16(cmd->resize.height);
+
+ qemu_free_displaysurface(s->ds);
+ s->ds->surface = qemu_create_displaysurface_from(width, height,
+ sizeof(uint32_t) * 8, width * sizeof(uint32_t),
+ qemu_malloc(width * height * BYTES_PER_PIXEL));
+ s->ds->surface->flags |= QEMU_ALLOCATED_FLAG;
+
+ dpy_resize(s->ds);
+
+ if (s->ds->surface->pf.bits_per_pixel != 32) {
+ fprintf(stderr, "virtio-fb only supports 32 bit ...\n");
+ exit(1);
+ }
+}
+
+static void virtio_fb_handle_fill(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+ uint16_t x = tswap16(cmd->fill.x);
+ uint16_t y = tswap16(cmd->fill.y);
+ uint16_t width = tswap16(cmd->fill.width);
+ uint16_t height = tswap16(cmd->fill.height);
+ uint32_t color = tswap32(cmd->fill.color);
+ uint8_t rop = cmd->fill.rop;
+
+ int ds_depth = ds_get_bytes_per_pixel(s->ds);
+ int ds_linesize = ds_get_linesize(s->ds);
+
+ uint8_t *ds_data = ds_get_data(s->ds);
+ uint32_t *src32;
+ uint8_t *src;
+ uint8_t *dst;
+
+ int i, len;
+
+ if (ds_depth != sizeof(uint32_t)) {
+ fprintf(stderr, "ds depth invalid\n");
+ exit(1);
+ }
+
+ if (rop == ROP_XOR) {
+ fprintf(stderr, "XOR\n");
+ exit(1);
+ }
+
+ if (x > ds_get_width(s->ds))
+ return;
+
+ if (y > ds_get_height(s->ds))
+ return;
+
+ if ((x + width) > ds_get_width(s->ds))
+ return;
+
+ if ((y + height) > ds_get_height(s->ds))
+ return;
+
+ len = width * ds_depth;
+ src = qemu_malloc(width * ds_depth);
+ src32 = (uint32_t *)src;
+
+ for (i = 0; i < width; i++) {
+ src32[i] = color;
+ }
+
+ dst = ds_data + (y * ds_linesize) + (x * ds_depth);
+
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, len);
+ dst += ds_linesize;
+ }
+
+ qemu_free(src);
+
+ dpy_update(s->ds, x, y, width, height);
+}
+
+static void virtio_fb_handle_blit(VirtIOFB *s, struct virtio_fb_cmd *cmd,
+ int len)
+{
+ uint16_t x = tswap16(cmd->blit.x);
+ uint16_t y = tswap16(cmd->blit.y);
+ uint16_t width = tswap16(cmd->blit.width);
+ uint16_t height = tswap16(cmd->blit.height);
+
+ int ds_linesize = ds_get_linesize(s->ds);
+ int ds_bpp = ds_get_bytes_per_pixel(s->ds);
+
+ int linesize = width * ds_bpp;
+ uint8_t *ds_data = ds_get_data(s->ds);
+ uint8_t *dst, *src;
+ int i;
+
+ if (x > ds_get_width(s->ds)) return;
+ if (y > ds_get_height(s->ds)) return;
+ if ((x + width) > ds_get_width(s->ds)) return;
+ if ((y + height) > ds_get_height(s->ds)) return;
+ if ((height * linesize) > len) return;
+
+ dst = ds_data + (y * ds_linesize) + (x * ds_bpp);
+ src = cmd->data;
+
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, linesize);
+ dst += ds_linesize;
+ src += linesize;
+ }
+
+ dpy_update(s->ds, x, y, width, height);
+}
+
+static void virtio_fb_handle_copy(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+ uint16_t x1 = tswap16(cmd->copy_area.x1);
+ uint16_t y1 = tswap16(cmd->copy_area.y1);
+ uint16_t x2 = tswap16(cmd->copy_area.x2);
+ uint16_t y2 = tswap16(cmd->copy_area.y2);
+ uint16_t width = tswap16(cmd->copy_area.width);
+ uint16_t height = tswap16(cmd->copy_area.height);
+
+ int ds_width = ds_get_width(s->ds);
+ int ds_depth = ds_get_bytes_per_pixel(s->ds);
+ int ds_linesize = ds_get_linesize(s->ds);
+ uint8_t *ds_data = ds_get_data(s->ds);
+ uint8_t *bkp;
+ uint8_t *dst;
+ uint8_t *src;
+ int i, len;
+
+ if (ds_depth != sizeof(uint32_t)) {
+ fprintf(stderr, "ds depth invalid\n");
+ exit(1);
+ }
+
+ if (x1 > ds_get_width(s->ds)) return;
+ if (y1 > ds_get_height(s->ds)) return;
+ if (x2 > ds_get_width(s->ds)) return;
+ if (y2 > ds_get_height(s->ds)) return;
+ if ((x1 + width) > ds_get_width(s->ds)) return;
+ if ((y1 + height) > ds_get_height(s->ds)) return;
+ if ((x2 + width) > ds_get_width(s->ds)) return;
+ if ((y2 + height) > ds_get_height(s->ds)) return;
+
+ len = (ds_width * ds_depth) + (height * ds_linesize);
+ bkp = qemu_malloc(len);
+ memcpy(bkp, ds_data + (x1 * ds_depth) + (y1 * ds_linesize), len);
+
+ src = bkp;
+ dst = ds_data + (x2 * ds_depth) + (y2 * ds_linesize);
+
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, width * ds_depth);
+ dst += ds_linesize;
+ src += ds_linesize;
+ }
+
+ qemu_console_copy(s->ds, x1, y1, x2, y2, width, height);
+ dpy_update(s->ds, x2, y2, width, height);
+
+ qemu_free(bkp);
+}
+
+static void virtio_fb_handle_write(VirtIOFB *s, struct virtio_fb_cmd *cmd,
+ int len)
+{
+ uint64_t offset = tswap64(cmd->write.offset);
+ uint64_t count = tswap64(cmd->write.count);
+ uint8_t *ds_data = ds_get_data(s->ds);
+ int ds_width = ds_get_width(s->ds);
+ int ds_size = ds_width * ds_get_height(s->ds) * ds_get_bytes_per_pixel(s->ds);
+
+ uint16_t y1 = (offset / sizeof(uint32_t)) / ds_width;
+ uint16_t y2 = (((offset + count) / sizeof(uint32_t)) / ds_width) + 2;
+
+ if ((offset > ds_size) || (count > len))
+ return;
+
+ if ((offset + count) > ds_size)
+ count = ds_size - offset;
+
+ memcpy(ds_data + offset, cmd->data, count);
+
+ dpy_update(s->ds, 0, y1, ds_get_width(s->ds), y2 - y1);
+}
+
+static void virtio_fb_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtIOFB *s = to_virtio_fb(vdev);
+ VirtQueueElement elem;
+ bool notify = false;
+
+ if (!virtio_queue_ready(vq))
+ return;
+
+ while (virtqueue_pop(vq, &elem)) {
+ int d;
+ struct virtio_fb_cmd *cmd;
+ char *data, *p;
+ int data_len = 0;
+
+ for (d = 0; d < elem.out_num; d++) {
+ data_len += elem.out_sg[d].iov_len;
+ }
+
+ data = qemu_malloc(data_len);
+ p = data;
+
+ for (d = 0; d < elem.out_num; d++) {
+ memcpy(p, elem.out_sg[d].iov_base, elem.out_sg[d].iov_len);
+ p += elem.out_sg[d].iov_len;
+ }
+
+ data_len -= sizeof(*cmd);
+ cmd = (struct virtio_fb_cmd *)data;
+
+ /* We can have a text console on our display. Don't draw then */
+ if (!is_graphic_console()) {
+ goto next_item;
+ }
+
+ switch (cmd->cmd) {
+ case VIRTIO_FB_CMD_RESIZE:
+ virtio_fb_handle_resize(s, cmd);
+ break;
+ case VIRTIO_FB_CMD_FILL:
+ virtio_fb_handle_fill(s, cmd);
+ break;
+ case VIRTIO_FB_CMD_BLIT:
+ virtio_fb_handle_blit(s, cmd, data_len);
+ break;
+ case VIRTIO_FB_CMD_COPY:
+ virtio_fb_handle_copy(s, cmd);
+ break;
+ case VIRTIO_FB_CMD_WRITE:
+ virtio_fb_handle_write(s, cmd, data_len);
+ break;
+ }
+
+next_item:
+
+ qemu_free(data);
+ virtqueue_push(vq, &elem, 0);
+ notify = true;
+ }
+
+ if (notify)
+ virtio_notify(vdev, vq);
+}
+
+VirtIODevice *virtio_fb_init(DeviceState *dev)
+{
+ VirtIOFB *s;
+ s = (VirtIOFB *)virtio_common_init("virtio-fb", VIRTIO_ID_FB,
+ 0, sizeof(VirtIOFB));
+ s->vdev.get_features = virtio_fb_get_features;
+
+ s->vq_in = virtio_add_queue(&s->vdev, 128, virtio_fb_handle_input);
+ s->vq_out = virtio_add_queue(&s->vdev, 512, virtio_fb_handle_output);
+
+ s->ds = graphic_console_init(NULL, virtio_fb_invalidate,
+ NULL, NULL, s);
+
+ register_savevm("virtio-fb", -1, 1, virtio_fb_save, virtio_fb_load, s);
+
+ return &s->vdev;
+}
diff --git a/hw/virtio.h b/hw/virtio.h
index 15ad910..9055f60 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -167,6 +167,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo);
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
VirtIODevice *virtio_console_init(DeviceState *dev);
VirtIODevice *virtio_balloon_init(DeviceState *dev);
+VirtIODevice *virtio_fb_init(DeviceState *dev);
void virtio_net_exit(VirtIODevice *vdev);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
@ 2009-11-02 22:11 ` Alexander Graf
0 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-02 22:11 UTC (permalink / raw)
To: kvm; +Cc: linux-fbdev-devel, qemu-devel
Since Linux now understands how to talk to us graphics over VirtIO, let's
add support for it in qemu.
The good part about graphics over VirtIO is that you don't need PCI to use
it. So if there's any platform out there trying to use graphics, but not
capable of MMIO, it can use this one!
Signed-off-by: Alexander Graf <agraf@suse.de>
---
Makefile.target | 1 +
hw/virtio-fb.c | 434 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio.h | 1 +
3 files changed, 436 insertions(+), 0 deletions(-)
create mode 100644 hw/virtio-fb.c
diff --git a/Makefile.target b/Makefile.target
index fefd7ac..260a6a8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -158,6 +158,7 @@ obj-y = vl.o async.o monitor.o pci.o machine.o gdbstub.o
# virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
+obj-y += virtio-fb.o
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
LIBS+=-lz
diff --git a/hw/virtio-fb.c b/hw/virtio-fb.c
new file mode 100644
index 0000000..c41d3bb
--- /dev/null
+++ b/hw/virtio-fb.c
@@ -0,0 +1,434 @@
+/*
+ * Virtio Frame Buffer Device
+ *
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
+ *
+ * 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 "console.h"
+#include "virtio.h"
+
+#define VIRTIO_ID_FB 6
+
+typedef struct VirtIOFB
+{
+ VirtIODevice vdev;
+ DisplayState *ds;
+ VirtQueue *vq_in;
+ VirtQueue *vq_out;
+} VirtIOFB;
+
+/* guest -> Host commands */
+#define VIRTIO_FB_CMD_RESIZE 0x01
+#define VIRTIO_FB_CMD_FILL 0x02
+#define VIRTIO_FB_CMD_BLIT 0x03
+#define VIRTIO_FB_CMD_COPY 0x04
+#define VIRTIO_FB_CMD_WRITE 0x05
+
+/* host -> guest commands */
+#define VIRTIO_FB_CMD_REFRESH 0x81
+
+#define ROP_COPY 0
+#define ROP_XOR 1
+
+#define BITS_PER_PIXEL 32
+#define BYTES_PER_PIXEL (BITS_PER_PIXEL / 8)
+
+struct virtio_fb_cmd {
+ uint8_t cmd;
+ union {
+ struct {
+ uint16_t width;
+ uint16_t height;
+ } resize __attribute__ ((packed));
+ struct {
+ uint16_t x;
+ uint16_t y;
+ uint16_t width;
+ uint16_t height;
+ } blit __attribute__ ((packed));
+ struct {
+ uint16_t x1;
+ uint16_t y1;
+ uint16_t x2;
+ uint16_t y2;
+ uint16_t width;
+ uint16_t height;
+ } copy_area __attribute__ ((packed));
+ struct {
+ uint8_t rop;
+ uint16_t x;
+ uint16_t y;
+ uint16_t width;
+ uint16_t height;
+ uint32_t color;
+ } fill __attribute__ ((packed));
+ struct {
+ uint64_t offset;
+ uint64_t count;
+ } write __attribute__ ((packed));
+ uint8_t pad[31];
+ };
+
+ uint8_t data[];
+} __attribute__ ((packed));
+
+static VirtIOFB *to_virtio_fb(VirtIODevice *vdev)
+{
+ return (VirtIOFB *)vdev;
+}
+
+static uint32_t virtio_fb_get_features(VirtIODevice *vdev)
+{
+ return 0;
+}
+
+static int virtio_fb_send(struct VirtIOFB *s, struct virtio_fb_cmd *cmd,
+ uint8_t *data, int len_data)
+{
+ int len_cmd = sizeof(*cmd);
+ int len_all = len_cmd + len_data;
+ VirtQueueElement elem;
+ int i = 0;
+
+ if (!virtio_queue_ready(s->vq_in))
+ return -1;
+
+ if (!virtqueue_pop(s->vq_in, &elem)) {
+ fprintf(stderr, "virtio-fb: queue lacking elements\n");
+ return -1;
+ }
+
+ if (elem.in_num < 1) {
+ fprintf(stderr, "virtio-fb: queue lacking sg's\n");
+ return -1;
+ }
+
+ if (elem.in_sg[i].iov_len < len_all) {
+ fprintf(stderr, "virtio-fb: buffer too small\n");
+ return -1;
+ }
+
+ if (len_data && !data) {
+ fprintf(stderr, "virtio-fb: passed no data but data length?!\n");
+ return -EINVAL;
+ }
+
+ memcpy(elem.in_sg[i].iov_base, cmd, len_cmd);
+ if (len_data)
+ memcpy(elem.in_sg[i].iov_base + len_cmd, data, len_data);
+
+ virtqueue_push(s->vq_in, &elem, len_all);
+ virtio_notify(&s->vdev, s->vq_in);
+
+ return 0;
+}
+
+/* QEMU display state changed, so refresh the framebuffer copy */
+static void virtio_fb_invalidate(void *opaque)
+{
+ struct VirtIOFB *s = opaque;
+ struct virtio_fb_cmd cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = VIRTIO_FB_CMD_REFRESH;
+
+ virtio_fb_send(s, &cmd, NULL, 0);
+ dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_width(s->ds));
+}
+
+static void virtio_fb_save(QEMUFile *f, void *opaque)
+{
+ VirtIOFB *s = opaque;
+
+ virtio_save(&s->vdev, f);
+}
+
+static int virtio_fb_load(QEMUFile *f, void *opaque, int version_id)
+{
+ VirtIOFB *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ virtio_load(&s->vdev, f);
+ return 0;
+}
+
+static void virtio_fb_handle_input(VirtIODevice *vdev, VirtQueue *vq)
+{
+}
+
+static void virtio_fb_handle_resize(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+ uint16_t width = tswap16(cmd->resize.width);
+ uint16_t height = tswap16(cmd->resize.height);
+
+ qemu_free_displaysurface(s->ds);
+ s->ds->surface = qemu_create_displaysurface_from(width, height,
+ sizeof(uint32_t) * 8, width * sizeof(uint32_t),
+ qemu_malloc(width * height * BYTES_PER_PIXEL));
+ s->ds->surface->flags |= QEMU_ALLOCATED_FLAG;
+
+ dpy_resize(s->ds);
+
+ if (s->ds->surface->pf.bits_per_pixel != 32) {
+ fprintf(stderr, "virtio-fb only supports 32 bit ...\n");
+ exit(1);
+ }
+}
+
+static void virtio_fb_handle_fill(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+ uint16_t x = tswap16(cmd->fill.x);
+ uint16_t y = tswap16(cmd->fill.y);
+ uint16_t width = tswap16(cmd->fill.width);
+ uint16_t height = tswap16(cmd->fill.height);
+ uint32_t color = tswap32(cmd->fill.color);
+ uint8_t rop = cmd->fill.rop;
+
+ int ds_depth = ds_get_bytes_per_pixel(s->ds);
+ int ds_linesize = ds_get_linesize(s->ds);
+
+ uint8_t *ds_data = ds_get_data(s->ds);
+ uint32_t *src32;
+ uint8_t *src;
+ uint8_t *dst;
+
+ int i, len;
+
+ if (ds_depth != sizeof(uint32_t)) {
+ fprintf(stderr, "ds depth invalid\n");
+ exit(1);
+ }
+
+ if (rop == ROP_XOR) {
+ fprintf(stderr, "XOR\n");
+ exit(1);
+ }
+
+ if (x > ds_get_width(s->ds))
+ return;
+
+ if (y > ds_get_height(s->ds))
+ return;
+
+ if ((x + width) > ds_get_width(s->ds))
+ return;
+
+ if ((y + height) > ds_get_height(s->ds))
+ return;
+
+ len = width * ds_depth;
+ src = qemu_malloc(width * ds_depth);
+ src32 = (uint32_t *)src;
+
+ for (i = 0; i < width; i++) {
+ src32[i] = color;
+ }
+
+ dst = ds_data + (y * ds_linesize) + (x * ds_depth);
+
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, len);
+ dst += ds_linesize;
+ }
+
+ qemu_free(src);
+
+ dpy_update(s->ds, x, y, width, height);
+}
+
+static void virtio_fb_handle_blit(VirtIOFB *s, struct virtio_fb_cmd *cmd,
+ int len)
+{
+ uint16_t x = tswap16(cmd->blit.x);
+ uint16_t y = tswap16(cmd->blit.y);
+ uint16_t width = tswap16(cmd->blit.width);
+ uint16_t height = tswap16(cmd->blit.height);
+
+ int ds_linesize = ds_get_linesize(s->ds);
+ int ds_bpp = ds_get_bytes_per_pixel(s->ds);
+
+ int linesize = width * ds_bpp;
+ uint8_t *ds_data = ds_get_data(s->ds);
+ uint8_t *dst, *src;
+ int i;
+
+ if (x > ds_get_width(s->ds)) return;
+ if (y > ds_get_height(s->ds)) return;
+ if ((x + width) > ds_get_width(s->ds)) return;
+ if ((y + height) > ds_get_height(s->ds)) return;
+ if ((height * linesize) > len) return;
+
+ dst = ds_data + (y * ds_linesize) + (x * ds_bpp);
+ src = cmd->data;
+
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, linesize);
+ dst += ds_linesize;
+ src += linesize;
+ }
+
+ dpy_update(s->ds, x, y, width, height);
+}
+
+static void virtio_fb_handle_copy(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+ uint16_t x1 = tswap16(cmd->copy_area.x1);
+ uint16_t y1 = tswap16(cmd->copy_area.y1);
+ uint16_t x2 = tswap16(cmd->copy_area.x2);
+ uint16_t y2 = tswap16(cmd->copy_area.y2);
+ uint16_t width = tswap16(cmd->copy_area.width);
+ uint16_t height = tswap16(cmd->copy_area.height);
+
+ int ds_width = ds_get_width(s->ds);
+ int ds_depth = ds_get_bytes_per_pixel(s->ds);
+ int ds_linesize = ds_get_linesize(s->ds);
+ uint8_t *ds_data = ds_get_data(s->ds);
+ uint8_t *bkp;
+ uint8_t *dst;
+ uint8_t *src;
+ int i, len;
+
+ if (ds_depth != sizeof(uint32_t)) {
+ fprintf(stderr, "ds depth invalid\n");
+ exit(1);
+ }
+
+ if (x1 > ds_get_width(s->ds)) return;
+ if (y1 > ds_get_height(s->ds)) return;
+ if (x2 > ds_get_width(s->ds)) return;
+ if (y2 > ds_get_height(s->ds)) return;
+ if ((x1 + width) > ds_get_width(s->ds)) return;
+ if ((y1 + height) > ds_get_height(s->ds)) return;
+ if ((x2 + width) > ds_get_width(s->ds)) return;
+ if ((y2 + height) > ds_get_height(s->ds)) return;
+
+ len = (ds_width * ds_depth) + (height * ds_linesize);
+ bkp = qemu_malloc(len);
+ memcpy(bkp, ds_data + (x1 * ds_depth) + (y1 * ds_linesize), len);
+
+ src = bkp;
+ dst = ds_data + (x2 * ds_depth) + (y2 * ds_linesize);
+
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, width * ds_depth);
+ dst += ds_linesize;
+ src += ds_linesize;
+ }
+
+ qemu_console_copy(s->ds, x1, y1, x2, y2, width, height);
+ dpy_update(s->ds, x2, y2, width, height);
+
+ qemu_free(bkp);
+}
+
+static void virtio_fb_handle_write(VirtIOFB *s, struct virtio_fb_cmd *cmd,
+ int len)
+{
+ uint64_t offset = tswap64(cmd->write.offset);
+ uint64_t count = tswap64(cmd->write.count);
+ uint8_t *ds_data = ds_get_data(s->ds);
+ int ds_width = ds_get_width(s->ds);
+ int ds_size = ds_width * ds_get_height(s->ds) * ds_get_bytes_per_pixel(s->ds);
+
+ uint16_t y1 = (offset / sizeof(uint32_t)) / ds_width;
+ uint16_t y2 = (((offset + count) / sizeof(uint32_t)) / ds_width) + 2;
+
+ if ((offset > ds_size) || (count > len))
+ return;
+
+ if ((offset + count) > ds_size)
+ count = ds_size - offset;
+
+ memcpy(ds_data + offset, cmd->data, count);
+
+ dpy_update(s->ds, 0, y1, ds_get_width(s->ds), y2 - y1);
+}
+
+static void virtio_fb_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtIOFB *s = to_virtio_fb(vdev);
+ VirtQueueElement elem;
+ bool notify = false;
+
+ if (!virtio_queue_ready(vq))
+ return;
+
+ while (virtqueue_pop(vq, &elem)) {
+ int d;
+ struct virtio_fb_cmd *cmd;
+ char *data, *p;
+ int data_len = 0;
+
+ for (d = 0; d < elem.out_num; d++) {
+ data_len += elem.out_sg[d].iov_len;
+ }
+
+ data = qemu_malloc(data_len);
+ p = data;
+
+ for (d = 0; d < elem.out_num; d++) {
+ memcpy(p, elem.out_sg[d].iov_base, elem.out_sg[d].iov_len);
+ p += elem.out_sg[d].iov_len;
+ }
+
+ data_len -= sizeof(*cmd);
+ cmd = (struct virtio_fb_cmd *)data;
+
+ /* We can have a text console on our display. Don't draw then */
+ if (!is_graphic_console()) {
+ goto next_item;
+ }
+
+ switch (cmd->cmd) {
+ case VIRTIO_FB_CMD_RESIZE:
+ virtio_fb_handle_resize(s, cmd);
+ break;
+ case VIRTIO_FB_CMD_FILL:
+ virtio_fb_handle_fill(s, cmd);
+ break;
+ case VIRTIO_FB_CMD_BLIT:
+ virtio_fb_handle_blit(s, cmd, data_len);
+ break;
+ case VIRTIO_FB_CMD_COPY:
+ virtio_fb_handle_copy(s, cmd);
+ break;
+ case VIRTIO_FB_CMD_WRITE:
+ virtio_fb_handle_write(s, cmd, data_len);
+ break;
+ }
+
+next_item:
+
+ qemu_free(data);
+ virtqueue_push(vq, &elem, 0);
+ notify = true;
+ }
+
+ if (notify)
+ virtio_notify(vdev, vq);
+}
+
+VirtIODevice *virtio_fb_init(DeviceState *dev)
+{
+ VirtIOFB *s;
+ s = (VirtIOFB *)virtio_common_init("virtio-fb", VIRTIO_ID_FB,
+ 0, sizeof(VirtIOFB));
+ s->vdev.get_features = virtio_fb_get_features;
+
+ s->vq_in = virtio_add_queue(&s->vdev, 128, virtio_fb_handle_input);
+ s->vq_out = virtio_add_queue(&s->vdev, 512, virtio_fb_handle_output);
+
+ s->ds = graphic_console_init(NULL, virtio_fb_invalidate,
+ NULL, NULL, s);
+
+ register_savevm("virtio-fb", -1, 1, virtio_fb_save, virtio_fb_load, s);
+
+ return &s->vdev;
+}
diff --git a/hw/virtio.h b/hw/virtio.h
index 15ad910..9055f60 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -167,6 +167,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo);
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
VirtIODevice *virtio_console_init(DeviceState *dev);
VirtIODevice *virtio_balloon_init(DeviceState *dev);
+VirtIODevice *virtio_fb_init(DeviceState *dev);
void virtio_net_exit(VirtIODevice *vdev);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] Add PCI virtio support for frame buffer
2009-11-02 22:11 ` [Qemu-devel] " Alexander Graf
@ 2009-11-02 22:11 ` Alexander Graf
-1 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-02 22:11 UTC (permalink / raw)
To: kvm; +Cc: qemu-devel, linux-fbdev-devel, anthony
We now know how to use a frame buffer on VirtIO, but we still can't use it on
x86. In order to leverage the power of VirtIO FB, we need to wrap it through
virtio-pci.
So let's add all the shiny wrappers and add a -vga option.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/pc.c | 5 +++++
hw/pci.h | 1 +
hw/virtio-pci.c | 29 +++++++++++++++++++++++++++++
sysemu.h | 3 ++-
vl.c | 2 ++
5 files changed, 39 insertions(+), 1 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index bf4718e..4b0d019 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1190,6 +1190,11 @@ static void pc_init1(ram_addr_t ram_size,
} else {
isa_vga_init();
}
+ } else if (virtio_fb_enabled) {
+ if (pci_enabled)
+ pci_create_simple(pci_bus, -1, "virtio-fb-pci");
+ else
+ fprintf(stderr, "%s: virtio_fb: no PCI bus\n", __FUNCTION__);
}
rtc_state = rtc_init(2000);
diff --git a/hw/pci.h b/hw/pci.h
index 93f93fb..b65a6df 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -70,6 +70,7 @@ extern target_phys_addr_t pci_mem_base;
#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001
#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
#define PCI_DEVICE_ID_VIRTIO_CONSOLE 0x1003
+#define PCI_DEVICE_ID_VIRTIO_FB 0x1004
typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
uint32_t address, uint32_t data, int len);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 1665b59..34937de 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -490,6 +490,25 @@ static int virtio_console_init_pci(PCIDevice *pci_dev)
return 0;
}
+static int virtio_fb_init_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ VirtIODevice *vdev;
+
+ if (proxy->class_code != PCI_CLASS_DISPLAY_OTHER)
+ proxy->class_code = PCI_CLASS_DISPLAY_OTHER;
+
+ vdev = virtio_fb_init(&pci_dev->qdev);
+ if (!vdev) {
+ return -1;
+ }
+ virtio_init_pci(proxy, vdev,
+ PCI_VENDOR_ID_REDHAT_QUMRANET,
+ PCI_DEVICE_ID_VIRTIO_FB,
+ proxy->class_code, 0x00);
+ return 0;
+}
+
static int virtio_net_init_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -574,6 +593,16 @@ static PCIDeviceInfo virtio_info[] = {
},
.qdev.reset = virtio_pci_reset,
},{
+ .qdev.name = "virtio-fb-pci",
+ .qdev.size = sizeof(VirtIOPCIProxy),
+ .init = virtio_fb_init_pci,
+ .exit = virtio_exit_pci,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+ .qdev.reset = virtio_pci_reset,
+ },{
.qdev.name = "virtio-balloon-pci",
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_balloon_init_pci,
diff --git a/sysemu.h b/sysemu.h
index 96804b4..c1bc5a3 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -104,13 +104,14 @@ extern int autostart;
extern int bios_size;
typedef enum {
- VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB
+ VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_VIRTIO
} VGAInterfaceType;
extern int vga_interface_type;
#define cirrus_vga_enabled (vga_interface_type == VGA_CIRRUS)
#define std_vga_enabled (vga_interface_type == VGA_STD)
#define xenfb_enabled (vga_interface_type == VGA_XENFB)
+#define virtio_fb_enabled (vga_interface_type == VGA_VIRTIO)
#define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
extern int graphic_width;
diff --git a/vl.c b/vl.c
index e57f58f..f999514 100644
--- a/vl.c
+++ b/vl.c
@@ -4297,6 +4297,8 @@ static void select_vgahw (const char *p)
vga_interface_type = VGA_VMWARE;
} else if (strstart(p, "xenfb", &opts)) {
vga_interface_type = VGA_XENFB;
+ } else if (strstart(p, "virtio", &opts)) {
+ vga_interface_type = VGA_VIRTIO;
} else if (!strstart(p, "none", &opts)) {
invalid_vga:
fprintf(stderr, "Unknown vga type: %s\n", p);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 2/2] Add PCI virtio support for frame buffer
@ 2009-11-02 22:11 ` Alexander Graf
0 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-02 22:11 UTC (permalink / raw)
To: kvm; +Cc: linux-fbdev-devel, qemu-devel
We now know how to use a frame buffer on VirtIO, but we still can't use it on
x86. In order to leverage the power of VirtIO FB, we need to wrap it through
virtio-pci.
So let's add all the shiny wrappers and add a -vga option.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/pc.c | 5 +++++
hw/pci.h | 1 +
hw/virtio-pci.c | 29 +++++++++++++++++++++++++++++
sysemu.h | 3 ++-
vl.c | 2 ++
5 files changed, 39 insertions(+), 1 deletions(-)
diff --git a/hw/pc.c b/hw/pc.c
index bf4718e..4b0d019 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1190,6 +1190,11 @@ static void pc_init1(ram_addr_t ram_size,
} else {
isa_vga_init();
}
+ } else if (virtio_fb_enabled) {
+ if (pci_enabled)
+ pci_create_simple(pci_bus, -1, "virtio-fb-pci");
+ else
+ fprintf(stderr, "%s: virtio_fb: no PCI bus\n", __FUNCTION__);
}
rtc_state = rtc_init(2000);
diff --git a/hw/pci.h b/hw/pci.h
index 93f93fb..b65a6df 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -70,6 +70,7 @@ extern target_phys_addr_t pci_mem_base;
#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001
#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
#define PCI_DEVICE_ID_VIRTIO_CONSOLE 0x1003
+#define PCI_DEVICE_ID_VIRTIO_FB 0x1004
typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
uint32_t address, uint32_t data, int len);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 1665b59..34937de 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -490,6 +490,25 @@ static int virtio_console_init_pci(PCIDevice *pci_dev)
return 0;
}
+static int virtio_fb_init_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ VirtIODevice *vdev;
+
+ if (proxy->class_code != PCI_CLASS_DISPLAY_OTHER)
+ proxy->class_code = PCI_CLASS_DISPLAY_OTHER;
+
+ vdev = virtio_fb_init(&pci_dev->qdev);
+ if (!vdev) {
+ return -1;
+ }
+ virtio_init_pci(proxy, vdev,
+ PCI_VENDOR_ID_REDHAT_QUMRANET,
+ PCI_DEVICE_ID_VIRTIO_FB,
+ proxy->class_code, 0x00);
+ return 0;
+}
+
static int virtio_net_init_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -574,6 +593,16 @@ static PCIDeviceInfo virtio_info[] = {
},
.qdev.reset = virtio_pci_reset,
},{
+ .qdev.name = "virtio-fb-pci",
+ .qdev.size = sizeof(VirtIOPCIProxy),
+ .init = virtio_fb_init_pci,
+ .exit = virtio_exit_pci,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+ .qdev.reset = virtio_pci_reset,
+ },{
.qdev.name = "virtio-balloon-pci",
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_balloon_init_pci,
diff --git a/sysemu.h b/sysemu.h
index 96804b4..c1bc5a3 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -104,13 +104,14 @@ extern int autostart;
extern int bios_size;
typedef enum {
- VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB
+ VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_VIRTIO
} VGAInterfaceType;
extern int vga_interface_type;
#define cirrus_vga_enabled (vga_interface_type == VGA_CIRRUS)
#define std_vga_enabled (vga_interface_type == VGA_STD)
#define xenfb_enabled (vga_interface_type == VGA_XENFB)
+#define virtio_fb_enabled (vga_interface_type == VGA_VIRTIO)
#define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
extern int graphic_width;
diff --git a/vl.c b/vl.c
index e57f58f..f999514 100644
--- a/vl.c
+++ b/vl.c
@@ -4297,6 +4297,8 @@ static void select_vgahw (const char *p)
vga_interface_type = VGA_VMWARE;
} else if (strstart(p, "xenfb", &opts)) {
vga_interface_type = VGA_XENFB;
+ } else if (strstart(p, "virtio", &opts)) {
+ vga_interface_type = VGA_VIRTIO;
} else if (!strstart(p, "none", &opts)) {
invalid_vga:
fprintf(stderr, "Unknown vga type: %s\n", p);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
2009-11-02 22:11 ` [Qemu-devel] " Alexander Graf
@ 2009-11-03 6:22 ` Avi Kivity
-1 siblings, 0 replies; 8+ messages in thread
From: Avi Kivity @ 2009-11-03 6:22 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm, qemu-devel, linux-fbdev-devel, anthony
On 11/03/2009 12:11 AM, Alexander Graf wrote:
> Since Linux now understands how to talk to us graphics over VirtIO, let's
> add support for it in qemu.
>
> The good part about graphics over VirtIO is that you don't need PCI to use
> it. So if there's any platform out there trying to use graphics, but not
> capable of MMIO, it can use this one!
>
Which platforms are these?
--
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] Re: [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
@ 2009-11-03 6:22 ` Avi Kivity
0 siblings, 0 replies; 8+ messages in thread
From: Avi Kivity @ 2009-11-03 6:22 UTC (permalink / raw)
To: Alexander Graf; +Cc: linux-fbdev-devel, qemu-devel, kvm
On 11/03/2009 12:11 AM, Alexander Graf wrote:
> Since Linux now understands how to talk to us graphics over VirtIO, let's
> add support for it in qemu.
>
> The good part about graphics over VirtIO is that you don't need PCI to use
> it. So if there's any platform out there trying to use graphics, but not
> capable of MMIO, it can use this one!
>
Which platforms are these?
--
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
2009-11-03 6:22 ` [Qemu-devel] " Avi Kivity
@ 2009-11-03 6:23 ` Alexander Graf
-1 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-03 6:23 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, qemu-devel, linux-fbdev-devel, anthony
On 03.11.2009, at 07:22, Avi Kivity wrote:
> On 11/03/2009 12:11 AM, Alexander Graf wrote:
>> Since Linux now understands how to talk to us graphics over VirtIO,
>> let's
>> add support for it in qemu.
>>
>> The good part about graphics over VirtIO is that you don't need PCI
>> to use
>> it. So if there's any platform out there trying to use graphics,
>> but not
>> capable of MMIO, it can use this one!
>>
>
> Which platforms are these?
For now S390 comes to mind first ... :-). I'd use and improve the
spice stuff, but that hasn't exactly been open-source friendly so far...
Alex
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] Re: [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
@ 2009-11-03 6:23 ` Alexander Graf
0 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-03 6:23 UTC (permalink / raw)
To: Avi Kivity; +Cc: linux-fbdev-devel, qemu-devel, kvm
On 03.11.2009, at 07:22, Avi Kivity wrote:
> On 11/03/2009 12:11 AM, Alexander Graf wrote:
>> Since Linux now understands how to talk to us graphics over VirtIO,
>> let's
>> add support for it in qemu.
>>
>> The good part about graphics over VirtIO is that you don't need PCI
>> to use
>> it. So if there's any platform out there trying to use graphics,
>> but not
>> capable of MMIO, it can use this one!
>>
>
> Which platforms are these?
For now S390 comes to mind first ... :-). I'd use and improve the
spice stuff, but that hasn't exactly been open-source friendly so far...
Alex
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2009-11-03 6:24 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-02 22:11 [PATCH 1/2] Add emulation for VirtIO Frame Buffer device Alexander Graf
2009-11-02 22:11 ` [Qemu-devel] " Alexander Graf
2009-11-02 22:11 ` [PATCH 2/2] Add PCI virtio support for frame buffer Alexander Graf
2009-11-02 22:11 ` [Qemu-devel] " Alexander Graf
2009-11-03 6:22 ` [PATCH 1/2] Add emulation for VirtIO Frame Buffer device Avi Kivity
2009-11-03 6:22 ` [Qemu-devel] " Avi Kivity
2009-11-03 6:23 ` Alexander Graf
2009-11-03 6:23 ` [Qemu-devel] " Alexander Graf
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.