]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Add VESA device
authorJohn Floren <john@jfloren.net>
Mon, 23 May 2011 12:15:16 +0000 (15:15 +0300)
committerPekka Enberg <penberg@kernel.org>
Mon, 23 May 2011 14:07:39 +0000 (17:07 +0300)
Add a simple VESA device which simply moves a framebuffer
from guest kernel to a VNC server.

VESA device PCI code is very similar to virtio-* PCI code.

Signed-off-by: John Floren <john@jfloren.net>
[ turning code into patches and cleanup ]
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/hw/vesa.c [new file with mode: 0644]
tools/kvm/include/kvm/ioport.h
tools/kvm/include/kvm/vesa.h [new file with mode: 0644]
tools/kvm/include/kvm/virtio-pci-dev.h

diff --git a/tools/kvm/hw/vesa.c b/tools/kvm/hw/vesa.c
new file mode 100644 (file)
index 0000000..0be1617
--- /dev/null
@@ -0,0 +1,107 @@
+#include "kvm/vesa.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/irq.h"
+#include "kvm/virtio-pci-dev.h"
+
+#include <rfb/rfb.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+#define VESA_QUEUE_SIZE                128
+#define VESA_IRQ               14
+
+/*
+ * This "6000" value is pretty much the result of experimentation
+ * It seems that around this value, things update pretty smoothly
+ */
+#define VESA_UPDATE_TIME       6000
+
+u8 videomem[VESA_MEM_SIZE];
+
+static bool vesa_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+{
+       printf("vesa in port=%u\n", port);
+       return true;
+}
+
+static bool vesa_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count)
+{
+       printf("vesa out port=%u\n", port);
+       return true;
+}
+
+static struct ioport_operations vesa_io_ops = {
+       .io_in  = vesa_pci_io_in,
+       .io_out = vesa_pci_io_out,
+};
+
+static struct pci_device_header vesa_pci_device = {
+       .vendor_id              = PCI_VENDOR_ID_REDHAT_QUMRANET,
+       .device_id              = PCI_DEVICE_ID_VESA,
+       .header_type            = PCI_HEADER_TYPE_NORMAL,
+       .revision_id            = 0,
+       .class                  = 0x030000,
+       .subsys_vendor_id       = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
+       .subsys_id              = PCI_SUBSYSTEM_ID_VESA,
+       .bar[0]                 = IOPORT_VESA | PCI_BASE_ADDRESS_SPACE_IO,
+       .bar[1]                 = VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY,
+};
+
+
+void vesa_mmio_callback(u64 addr, u8 *data, u32 len, u8 is_write)
+{
+       if (is_write)
+               memcpy(&videomem[addr - VESA_MEM_ADDR], data, len);
+
+       return;
+}
+
+void vesa__init(struct kvm *kvm)
+{
+       u8 dev, line, pin;
+       pthread_t thread;
+
+       if (irq__register_device(PCI_DEVICE_ID_VESA, &dev, &pin, &line) < 0)
+               return;
+
+       vesa_pci_device.irq_pin = pin;
+       vesa_pci_device.irq_line = line;
+       pci__register(&vesa_pci_device, dev);
+       ioport__register(IOPORT_VESA, &vesa_io_ops, IOPORT_VESA_SIZE);
+
+       kvm__register_mmio(VESA_MEM_ADDR, VESA_MEM_SIZE, &vesa_mmio_callback);
+       pthread_create(&thread, NULL, vesa__dovnc, kvm);
+}
+
+/*
+ * This starts a VNC server to display the framebuffer.
+ * It's not altogether clear this belongs here rather than in kvm-run.c
+ */
+void *vesa__dovnc(void *v)
+{
+       /*
+        * Make a fake argc and argv because the getscreen function
+        * seems to want it.
+        */
+       int ac = 1;
+       char av[1][1] = {{0} };
+       rfbScreenInfoPtr server;
+
+       server = rfbGetScreen(&ac, (char **)av, VESA_WIDTH, VESA_HEIGHT, 8, 3, 4);
+       server->frameBuffer = (char *)videomem;
+       server->alwaysShared = TRUE;
+       rfbInitServer(server);
+
+       while (rfbIsActive(server)) {
+               rfbMarkRectAsModified(server, 0, 0, VESA_WIDTH, VESA_HEIGHT);
+               rfbProcessEvents(server, server->deferUpdateTime * VESA_UPDATE_TIME);
+       }
+       return NULL;
+}
index 218530c06242b1565c65067352079d59852a47bd..8253938308f29ad7bb6a79f73ab0b1bf8350c3a3 100644 (file)
@@ -7,6 +7,8 @@
 
 /* some ports we reserve for own use */
 #define IOPORT_DBG                     0xe0
+#define IOPORT_VESA                    0xa200
+#define IOPORT_VESA_SIZE               256
 #define IOPORT_VIRTIO_P9               0xb200  /* Virtio 9P device */
 #define IOPORT_VIRTIO_P9_SIZE          256
 #define IOPORT_VIRTIO_BLK              0xc200  /* Virtio block device */
diff --git a/tools/kvm/include/kvm/vesa.h b/tools/kvm/include/kvm/vesa.h
new file mode 100644 (file)
index 0000000..ff3ec75
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef KVM__VESA_H
+#define KVM__VESA_H
+
+#include <linux/types.h>
+
+#define VESA_WIDTH     640
+#define VESA_HEIGHT    480
+
+#define VESA_MEM_ADDR  0xd0000000
+#define VESA_MEM_SIZE  (4*VESA_WIDTH*VESA_HEIGHT)
+#define VESA_BPP       32
+
+struct kvm;
+struct int10_args;
+
+void vesa_mmio_callback(u64, u8*, u32, u8);
+void vesa__init(struct kvm *self);
+void *vesa__dovnc(void *);
+void int10_handler(struct int10_args *args);
+
+#ifndef CONFIG_HAS_VNCSERVER
+void vesa__init(struct kvm *self) { }
+#endif
+
+extern u8 videomem[VESA_MEM_SIZE];
+
+#endif
index 1b7862eea4be92a225c41587fa760ad36afcf1b3..ca373df7bb12a42be82c9958d12b8fcdd46f6190 100644 (file)
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE           0x1003
 #define PCI_DEVICE_ID_VIRTIO_RNG               0x1004
 #define PCI_DEVICE_ID_VIRTIO_P9                        0x1009
+#define PCI_DEVICE_ID_VESA                     0x2000
 
 #define PCI_VENDOR_ID_REDHAT_QUMRANET          0x1af4
 #define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET        0x1af4
 
+#define PCI_SUBSYSTEM_ID_VESA                  0x0004
+
 #endif /* VIRTIO_PCI_DEV_H_ */