[Spice-devel,3/3] qxl-virtio: introducing changes to support virtio based transport

Submitted by Erlon Cruz on Aug. 24, 2012, 7:11 p.m.

Details

Message ID 1345835460-23061-4-git-send-email-erlon.cruz@br.flextronics.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Erlon Cruz Aug. 24, 2012, 7:11 p.m.
Signed-off-by: Erlon R. Cruz <erlon.cruz@fit-tecnologia.org.br>
Signed-off-by: Fabiano FidĂȘncio <fabiano.fidencio@fit-tecnologia.org.br>
Signed-off-by: Rafael F. Santos <fonsecasantos.rafael@gmail.com>
---
 examples/Makefile.am                 |    6 +-
 examples/virtioqxl.xorg.conf.example |   24 +++
 src/Makefile.am                      |   11 +-
 src/qxl.h                            |  196 +++++++++++++++++++++++-
 src/qxl_driver.c                     |  275 ++++++++++++++++++++++++++--------
 src/qxl_logger.c                     |    8 +
 src/qxl_ring.c                       |  169 ++++++++++++++++++++-
 src/qxl_surface.c                    |   94 ++++--------
 8 files changed, 637 insertions(+), 146 deletions(-)
 create mode 100644 examples/virtioqxl.xorg.conf.example

Patch hide | download patch | download mbox

diff --git a/examples/Makefile.am b/examples/Makefile.am
index 75e61ea..251f6f1 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -19,6 +19,8 @@ 
 #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 if BUILD_XSPICE
-doc_DATA = spiceqxl.xorg.conf.example
+doc_DATA = spiceqxl.xorg.conf.example	\
+		   virtioqxl.xorg.conf.example
 endif
-EXTRA_DIST = spiceqxl.xorg.conf.example
+EXTRA_DIST = spiceqxl.xorg.conf.example	\
+			 virtioqxl.xorg.conf.example
diff --git a/examples/virtioqxl.xorg.conf.example b/examples/virtioqxl.xorg.conf.example
new file mode 100644
index 0000000..bcb9b9d
--- /dev/null
+++ b/examples/virtioqxl.xorg.conf.example
@@ -0,0 +1,24 @@ 
+Section "Device"
+    Identifier "QXL_device"
+    Driver "virtioqxl"
+    Option "virtiodev" "/dev/virtioqxl0"
+EndSection
+
+Section "InputDevice"
+    Identifier  "Mouse"
+    Driver      "mouse"
+    Option      "Protocol" "PS/2"
+    Option      "Device" "/dev/input/mice"
+EndSection
+
+Section "Monitor"
+    Identifier  "Configured Monitor"
+EndSection
+
+Section "Screen"
+    Identifier      "Screen"
+    Monitor         "Configured Monitor"
+    Device          "QXL_device"
+    DefaultDepth    24
+EndSection
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 3ffa3ce..09d89ad 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,6 +31,7 @@  AM_CFLAGS = $(SPICE_PROTOCOL_CFLAGS) $(XORG_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNF
 
 if ENABLE_DEBUG
 DEBUGFLAGS = -DENABLE_DEBUG -O0 -g
+DEBUG_FILES = qxl_logger.c
 endif
 
 if BUILD_DUMP_COMMANDS
@@ -57,7 +58,7 @@  qxl_drv_la_SOURCES =				\
 	murmurhash3.h				\
 	qxl_cursor.c				\
 	compat-api.h				\
-	qxl_logger.c
+	$(DEBUG_FILES) 
 endif
 
 if BUILD_VIRTIO_QXL
@@ -80,7 +81,7 @@  virtioqxl_drv_la_SOURCES =			\
 	murmurhash3.c				\
 	murmurhash3.h				\
 	qxl_cursor.c				\
-	qxl_logger.c
+	$(DEBUG_FILES)
 endif
 
 if BUILD_XSPICE
@@ -103,7 +104,7 @@  spiceqxl_drv_la_SOURCES =				\
 	spiceqxl_driver.c			\
 	spiceqxl_driver.h			\
 	spiceqxl_main_loop.c			\
-	spiceqxl_main_loop.h		\
+	spiceqxl_main_loop.h			\
 	spiceqxl_display.c			\
 	spiceqxl_display.h			\
 	spiceqxl_inputs.c			\
@@ -118,5 +119,5 @@  spiceqxl_drv_la_SOURCES =				\
 	murmurhash3.c				\
 	murmurhash3.h				\
 	qxl_cursor.c				\
-	qxl_logger.c
-endif
+	$(DEBUG_FILES)
+endif
\ No newline at end of file
diff --git a/src/qxl.h b/src/qxl.h
index 7d90dfc..83eea99 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -30,6 +30,21 @@ 
 #include <spice.h>
 #endif
 
+#ifdef VIRTIO_QXL
+#include <linux/virtio_bridge.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <endian.h>
+
+#ifdef ENABLE_DEBUG
+#define DEBUG_RINGS 0
+#define DEBUG_CURSOR_RING 0
+#define DEBUG_COMMAND_RING 0
+#define DEBUG_RELEASE_RING 0
+#define DEBUG_RAM_UPDATES 0
+#endif
+#endif // VIRTIO_QXL
+
 #include "compiler.h"
 #include "xf86.h"
 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
@@ -53,7 +68,10 @@ 
 #include "compat-api.h"
 #define hidden _X_HIDDEN
 
-#ifdef XSPICE
+#ifdef VIRTIO_QXL
+#define QXL_NAME        "virtioqxl"
+#define QXL_DRIVER_NAME "virtioqxl"
+#elif defined XSPICE
 #define QXL_NAME		"spiceqxl"
 #define QXL_DRIVER_NAME		"spiceqxl"
 #else
@@ -92,6 +110,47 @@  typedef struct
 
 typedef struct qxl_surface_t qxl_surface_t;
 
+struct qxl_surface_t
+{
+    surface_cache_t    *cache;
+    
+    uint32_t	        id;
+
+    pixman_image_t *	dev_image;
+    pixman_image_t *	host_image;
+
+    uxa_access_t	access_type;
+    RegionRec		access_region;
+
+    void *		address;
+    void *		end;
+    
+    qxl_surface_t *	next;
+    qxl_surface_t *	prev;	/* Only used in the 'live'
+				 * chain in the surface cache
+				 */
+
+    int			in_use;
+    int			bpp;		/* bpp of the pixmap */
+    int			ref_count;
+
+    PixmapPtr		pixmap;
+
+    struct evacuated_surface_t *evacuated;
+
+    union
+    {
+	qxl_surface_t *copy_src;
+	Pixel	       solid_pixel;
+    } u;
+};
+
+typedef enum {
+    CURSOR_RING,
+    COMMAND_RING,
+    RELEASE_RING
+} ring_type;
+
 /*
  * Config Options
  */
@@ -172,7 +231,7 @@  struct _qxl_screen_t
     
     EntityInfoPtr		entity;
 
-#ifndef XSPICE
+#if !defined XSPICE && !defined VIRTIO_QXL
     void *			io_pages;
     void *			io_pages_physical;
 
@@ -220,6 +279,13 @@  struct _qxl_screen_t
     int				enable_fallback_cache;
     int				enable_surfaces;
     
+#ifdef VIRTIO_QXL
+    int virtiofd;
+    struct virtioqxl_config virtio_config;
+    void *vmem_start;
+    char *device_name;
+#endif
+
 #ifdef XSPICE
     /* XSpice specific */
     struct QXLRom		shadow_rom;    /* Parameter RAM */
@@ -248,6 +314,54 @@  struct _qxl_screen_t
 #endif /* XSPICE */
 };
 
+#ifdef VIRTIO_QXL
+static inline uint64_t physical_address(qxl_screen_t *qxl, 
+                void *virtual,
+                uint8_t slot_id){
+    
+    char *ram;
+    uint64_t offset;
+    int maplen;
+
+    ram = (char *)qxl->ram;
+    maplen = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize +
+        qxl->virtio_config.romsize;
+    offset = (char *)virtual - ram;
+
+    if (offset >= 0 && offset < maplen) {
+        return offset;
+    }
+
+    // Die
+    fprintf(stderr, "GUEST (%s): Memory %p (%ld) out of bounds [%p - %p]\n",
+            __func__, virtual, (char *)virtual - ram, ram, ram + maplen);
+    exit(1);
+}
+
+static inline void * virtual_address (qxl_screen_t *qxl,
+                void *physical,
+                uint8_t slot_id){
+    
+    char *ram;
+    uint64_t offset;
+    void *local;
+    int memlen = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize +
+        qxl->virtio_config.romsize;
+
+    ram = (char *)qxl->ram;
+    offset = (uint64_t)physical;
+
+    if (offset >= 0 && offset < memlen) {
+        local = (void *)(ram + offset);
+    } else {
+        fprintf(stderr, "GUEST (%s): Memory %p (%ld) out of bounds [%p - %p]\n",
+                __func__, (uint64_t)physical + ram, offset, ram, ram + memlen);
+        exit(1);
+    }
+
+    return local;
+}
+#else
 static inline uint64_t
 physical_address (qxl_screen_t *qxl, void *virtual, uint8_t slot_id)
 {
@@ -267,6 +381,7 @@  virtual_address (qxl_screen_t *qxl, void *physical, uint8_t slot_id)
 
     return (void *)virt;
 }
+#endif // VIRTIO_QXL
 
 static inline void *
 u64_to_pointer (uint64_t u)
@@ -296,7 +411,8 @@  struct qxl_ring * qxl_ring_create      (struct qxl_ring_header *header,
 					int                     element_size,
 					int                     n_elements,
 					int                     prod_notify,
-					qxl_screen_t            *qxl);
+					qxl_screen_t            *qxl,
+                                        int ring_type);
 void              qxl_ring_push        (struct qxl_ring        *ring,
 					const void             *element);
 Bool              qxl_ring_pop         (struct qxl_ring        *ring,
@@ -387,7 +503,7 @@  static inline struct QXLRam *
 get_ram_header (qxl_screen_t *qxl)
 {
     return (struct QXLRam *)
-	((uint8_t *)qxl->ram + qxl->rom->ram_header_offset);
+	((uint8_t *)qxl->ram + le32toh(qxl->rom->ram_header_offset));
 }
 
 /*
@@ -430,13 +546,13 @@  void qxl_mem_unverifiable(struct qxl_mem *mem);
 static inline void qxl_mem_unverifiable(struct qxl_mem *mem) {}
 #endif
 
-#ifdef DUMP_COMMANDS
+#ifdef ENABLE_DEBUG
 void qxl_log_command(qxl_screen_t *qxl, QXLCommand *cmd, char *direction);
 #endif
 /*
  * I/O port commands
  */
-void qxl_update_area(qxl_screen_t *qxl);
+void qxl_update_area(qxl_screen_t *qxl,qxl_surface_t *surface);
 void qxl_io_memslot_add(qxl_screen_t *qxl, uint8_t id);
 void qxl_io_create_primary(qxl_screen_t *qxl);
 void qxl_io_destroy_primary(qxl_screen_t *qxl);
@@ -447,6 +563,12 @@  void qxl_io_destroy_all_surfaces (qxl_screen_t *qxl);
 #ifdef XSPICE
 /* device to spice-server, now xspice to spice-server */
 void ioport_write(qxl_screen_t *qxl, uint32_t io_port, uint32_t val);
+#elif defined VIRTIO_QXL
+static inline void ioport_write(qxl_screen_t *qxl, int port, int val)
+{
+    int cmd = _IOW(QXLMAGIC, port, unsigned int);
+    ioctl(qxl->virtiofd, cmd, val);
+}
 #else
 static inline void ioport_write(qxl_screen_t *qxl, int port, int val)
 {
@@ -454,6 +576,68 @@  static inline void ioport_write(qxl_screen_t *qxl, int port, int val)
 }
 #endif
 
+#ifdef ENABLE_DEBUG
+void qxl_log_command(qxl_screen_t *qxl, QXLCommand *cmd, char *direction);
+#endif
+
+#ifdef VIRTIO_QXL
+/* Write guest memory on host*/
+static inline void virtioqxl_push_ram(qxl_screen_t *qxl, void *ptr, int len)
+{
+    char *start, *end;
+    struct qxl_ram_area ram_area;
+    int memlen = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize +
+        qxl->virtio_config.romsize;
+
+    start = (char *)ptr;
+    end = (char *)ptr + len;
+
+    if (start < (char *)qxl->ram ||
+        end > ((char *)qxl->ram + memlen)) {
+        fprintf(stderr,"%s: Error pushing memory [%p - %p] out of bounds "
+                "[%p - %p]\n", __func__, start, end, qxl->ram,
+                (char *)qxl->ram + memlen);
+        return;
+    }
+
+    ram_area.offset = start - (char *)qxl->ram;
+    ram_area.len = len;
+
+#ifdef ENABLE_DEBUG
+    fprintf(stderr,"%s: pushing area[%d->%d]. %d bytes\n",
+                __func__, ram_area.offset, ram_area.offset + ram_area.len,
+                ram_area.len);
+#endif
+
+    write(qxl->virtiofd,ptr,len);
+}
+
+/* Read from memory on host*/
+static inline void virtioqxl_pull_ram(qxl_screen_t *qxl, void *ptr, int len)
+{
+    struct qxl_ram_area ram_area;
+    int mem_size = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize +
+        qxl->virtio_config.romsize;
+
+    if ((uint8_t *)ptr < (uint8_t *)qxl->ram ||
+        (uint8_t *)ptr+len > ((uint8_t *)qxl->ram + mem_size)) {
+        fprintf(stderr,"%s: Error pulling memory out of bounds\n",__func__);
+        return;
+    }
+
+    ram_area.offset = (uint8_t *)ptr - (uint8_t *)qxl->ram;
+    ram_area.len = len;
+
+#ifdef ENABLE_DEBUG   
+    fprintf(stderr,"%s: pulling area[%d->%d]. %d bytes\n",
+                __func__, ram_area.offset, ram_area.offset + ram_area.len,
+                ram_area.len);
+#endif
+    
+    read(qxl->virtiofd,ptr,len);
+}
+#endif // VIRTIO_QXL
+
 #ifdef XSPICE
 
 #define MEMSLOT_GROUP 0
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index e4c477a..5474850 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -46,6 +46,14 @@ 
 #include "assert.h"
 #include "qxl_option_helpers.h"
 
+#ifdef VIRTIO_QXL
+#include <linux/virtio_bridge.h>
+#include "spiceqxl_driver.h"
+#define VIRTIO_DEV "/dev/virtioqxl0"
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+
 #ifdef XSPICE
 #include "spiceqxl_driver.h"
 #include "spiceqxl_main_loop.h"
@@ -126,7 +134,7 @@  qxl_available_options (int chipid, int busid)
     return DefaultOptions;
 }
 
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
 static void qxl_wait_for_io_command(qxl_screen_t *qxl)
 {
     struct QXLRam *ram_header = (void *)(
@@ -139,9 +147,16 @@  static void qxl_wait_for_io_command(qxl_screen_t *qxl)
 }
 #endif
 
-void qxl_update_area(qxl_screen_t *qxl)
+void qxl_update_area(qxl_screen_t *qxl, qxl_surface_t *surface)
 {
-#ifndef XSPICE
+
+#ifdef VIRTIO_QXL
+    QXLRam *ram_header = get_ram_header(qxl);
+    virtioqxl_push_ram(qxl, &ram_header->update_area, sizeof(QXLRect));
+    virtioqxl_push_ram(qxl, &ram_header->update_surface, sizeof(int));
+#endif
+
+#if !defined XSPICE && !defined VIRTIO_QXL
     if (qxl->pci->revision >= 3) {
         ioport_write(qxl, QXL_IO_UPDATE_AREA_ASYNC, 0);
         qxl_wait_for_io_command(qxl);
@@ -151,11 +166,20 @@  void qxl_update_area(qxl_screen_t *qxl)
 #else
     ioport_write(qxl, QXL_IO_UPDATE_AREA, 0);
 #endif
+
+#ifdef VIRTIO_QXL
+    if (!surface || !surface->id) {   //Primary
+        virtioqxl_pull_ram(qxl, qxl->surface0_area, qxl->surface0_size);
+    } else {
+        virtioqxl_pull_ram(qxl, surface->address,
+                (intptr_t)surface->end - (intptr_t)surface->address);
+    }
+#endif
 }
 
 void qxl_io_memslot_add(qxl_screen_t *qxl, uint8_t id)
 {
-#ifndef XSPICE
+#if !defined XSPICE && !defined VIRTIO_QXL
     if (qxl->pci->revision >= 3) {
         ioport_write(qxl, QXL_IO_MEMSLOT_ADD_ASYNC, id);
         qxl_wait_for_io_command(qxl);
@@ -169,7 +193,7 @@  void qxl_io_memslot_add(qxl_screen_t *qxl, uint8_t id)
 
 void qxl_io_create_primary(qxl_screen_t *qxl)
 {
-#ifndef XSPICE
+#if !defined XSPICE && !defined VIRTIO_QXL
     if (qxl->pci->revision >= 3) {
         ioport_write(qxl, QXL_IO_CREATE_PRIMARY_ASYNC, 0);
         qxl_wait_for_io_command(qxl);
@@ -184,7 +208,7 @@  void qxl_io_create_primary(qxl_screen_t *qxl)
 
 void qxl_io_destroy_primary(qxl_screen_t *qxl)
 {
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
     if (qxl->pci->revision >= 3)
     {
         ioport_write(qxl, QXL_IO_DESTROY_PRIMARY_ASYNC, 0);
@@ -206,7 +230,7 @@  void qxl_io_notify_oom(qxl_screen_t *qxl)
 
 void qxl_io_flush_surfaces(qxl_screen_t *qxl)
 {
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
     ioport_write(qxl, QXL_IO_FLUSH_SURFACES_ASYNC, 0);
     qxl_wait_for_io_command(qxl);
 #else
@@ -273,9 +297,14 @@  qxl_garbage_collect (qxl_screen_t *qxl)
 		qxl_surface_recycle (qxl->surface_cache, surface_cmd->surface_id);
 		qxl_surface_cache_sanity_check (qxl->surface_cache);
 	    }
-	    
-	    id = info->next;
-	    
+
+#ifdef VIRTIO_QXL
+		virtioqxl_pull_ram(qxl,&info->next,sizeof(info->next));
+		id = info->next;
+#else
+		id = info->next;
+#endif
+
 	    qxl_free (qxl->mem, info);
 
 	    ++i;
@@ -358,7 +387,99 @@  qxl_blank_screen(ScreenPtr pScreen, int mode)
     return TRUE;
 }
 
-#ifdef XSPICE
+#ifdef VIRTIO_QXL
+
+#undef SPICE_RING_PROD_ITEM
+#define SPICE_RING_PROD_ITEM(r, ret) {                      \
+    typeof(r) start = r;                                    \
+    typeof(r) end = r + 1;                                  \
+    uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r);   \
+    typeof(&(r)->items[prod]) m_item = &(r)->items[prod];   \
+    if (!((uint8_t *)m_item >= (uint8_t *)(start) && (uint8_t *)(m_item + 1) <= (uint8_t *)(end))) { \
+        abort();                                            \
+    }                                                       \
+    ret = &m_item->el;                                      \
+}
+
+#undef SPICE_RING_CONS_ITEM
+#define SPICE_RING_CONS_ITEM(r, ret) {                      \
+    typeof(r) start = r;                                    \
+    typeof(r) end = r + 1;                                  \
+    uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r);   \
+    typeof(&(r)->items[cons]) m_item = &(r)->items[cons];   \
+    if (!((uint8_t *)m_item >= (uint8_t *)(start) && (uint8_t *)(m_item + 1) <= (uint8_t *)(end))) { \
+        abort();                                            \
+    }                                                       \
+    ret = &m_item->el;                                      \
+}
+
+static void virtio_init_qxl_ram(qxl_screen_t *qxl)
+{
+    QXLRam *ram = get_ram_header(qxl);
+    uint64_t *item;
+
+    ram->magic       = htole32(QXL_RAM_MAGIC);
+    ram->int_pending = htole32(0);
+    ram->int_mask    = htole32(0);
+    SPICE_RING_INIT(&ram->cmd_ring);
+    SPICE_RING_INIT(&ram->cursor_ring);
+    SPICE_RING_INIT(&ram->release_ring);
+    SPICE_RING_PROD_ITEM(&ram->release_ring, item);
+    *item = 0;
+}
+
+static void unmap_memory_helper(qxl_screen_t *qxl)
+{
+    free(qxl->ram);
+    close(qxl->virtiofd);
+}
+
+static void map_memory_helper(qxl_screen_t *qxl)
+{
+    void *vmem_start,*modes_start;
+    int memlen, num_modes;
+    struct QXLRom *rom;
+    QXLRam *ram_header;
+    
+    CHECK_POINT();
+
+    qxl->virtiofd = open(qxl->device_name, O_RDWR | O_SYNC);
+
+    if (qxl->virtiofd < 0) {
+        ErrorF("Error opening virtio device. Check if "
+                " virtio-qxl-bridge is loaded\n");
+        return;
+    }
+
+    ioctl(qxl->virtiofd, QXL_IOCTL_QXL_IO_GETCFG, &qxl->virtio_config);
+
+    memlen = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize +
+        qxl->virtio_config.romsize;
+
+    qxl->ram = vmem_start = qxl->ram_physical = malloc(memlen);
+    memset(qxl->ram,0x0,memlen);
+    ErrorF("%s: allocated %d bytes as video memory at %p\n",__func__, memlen,qxl->ram);
+    ioctl(qxl->virtiofd, QXL_IOCTL_QXL_IO_SET_RAMSTART, &qxl->ram);
+
+    qxl->vram = (uint8_t *)vmem_start + qxl->virtio_config.ramsize;
+    qxl->vram_size = qxl->virtio_config.vramsize;
+    qxl->vram_physical = qxl->vram;
+    qxl->rom = (void *)((uint8_t *)vmem_start + qxl->virtio_config.ramsize +
+            qxl->virtio_config.vramsize);
+
+    ram_header = get_ram_header(qxl);
+    rom = qxl->rom;
+    //Read the ROM contents from the device
+    //The 4 aditional bits brings the number of modes
+    read(qxl->virtiofd, qxl->rom,sizeof(*qxl->rom)+sizeof(int));
+    num_modes = le32toh(*(int *)((char *)qxl->rom+sizeof(*qxl->rom)));
+    modes_start = (char *)qxl->rom+sizeof(*qxl->rom)+sizeof(int);
+    read(qxl->virtiofd, modes_start,sizeof(QXLMode)*num_modes);
+
+    read(qxl->virtiofd, ram_header,sizeof(*ram_header));
+}
+
+#elif defined XSPICE
 static void
 unmap_memory_helper(qxl_screen_t *qxl)
 {
@@ -441,7 +562,7 @@  map_memory_helper(qxl_screen_t *qxl)
     qxl->io_base = qxl->pci->ioBase[3];
 #endif
 }
-#endif /* XSPICE */
+#endif /* VIRTIO_QXL */
 
 static void
 qxl_unmap_memory(qxl_screen_t *qxl)
@@ -477,30 +598,35 @@  qxl_mspace_print_func(void *user_data, const char *format, ...)
 static Bool
 qxl_map_memory(qxl_screen_t *qxl, int scrnIndex)
 {
+
+#ifdef VIRTIO_QXL
+    xf86DrvMsg(scrnIndex, X_INFO, "Opening device %s.\n", qxl->device_name);
+#endif    
+
     map_memory_helper(qxl);
 
     if (!qxl->ram || !qxl->vram || !qxl->rom)
 	return FALSE;
 
     xf86DrvMsg(scrnIndex, X_INFO, "framebuffer at %p (%d KB)\n",
-	       qxl->ram, qxl->rom->surface0_area_size / 1024);
+	       qxl->ram, le32toh(qxl->rom->surface0_area_size) / 1024);
 
     xf86DrvMsg(scrnIndex, X_INFO, "command ram at %p (%d KB)\n",
-	       (void *)((unsigned long)qxl->ram + qxl->rom->surface0_area_size),
-	       (qxl->rom->num_pages * getpagesize() - qxl->rom->surface0_area_size)/1024);
+	       (void *)((unsigned long)qxl->ram + le32toh(qxl->rom->surface0_area_size)),
+	       (le32toh(qxl->rom->num_pages) * getpagesize() - le32toh(qxl->rom->surface0_area_size))/1024);
 
     xf86DrvMsg(scrnIndex, X_INFO, "vram at %p (%ld KB)\n",
 	       qxl->vram, qxl->vram_size / 1024);
 
     xf86DrvMsg(scrnIndex, X_INFO, "rom at %p\n", qxl->rom);
 
-    qxl->num_modes = *(uint32_t *)((uint8_t *)qxl->rom + qxl->rom->modes_offset);
-    qxl->modes = (struct QXLMode *)(((uint8_t *)qxl->rom) + qxl->rom->modes_offset + 4);
+    qxl->num_modes = le32toh(*(uint32_t *)((uint8_t *)qxl->rom + le32toh(qxl->rom->modes_offset)));
+    qxl->modes = (struct QXLMode *)(((uint8_t *)qxl->rom) + le32toh(qxl->rom->modes_offset) + 4);
     qxl->surface0_area = qxl->ram;
-    qxl->surface0_size = qxl->rom->surface0_area_size;
+    qxl->surface0_size = le32toh(qxl->rom->surface0_area_size);
 
     qxl->mem = qxl_mem_create ((void *)((unsigned long)qxl->ram + qxl->surface0_size),
-			       qxl->rom->num_pages * getpagesize() - qxl->surface0_size);
+			       le32toh(qxl->rom->num_pages) * getpagesize() - qxl->surface0_size);
     qxl->surf_mem = qxl_mem_create ((void *)((unsigned long)qxl->vram), qxl->vram_size);
 
     mspace_set_abort_func(qxl_mspace_abort_func);
@@ -509,7 +635,7 @@  qxl_map_memory(qxl_screen_t *qxl, int scrnIndex)
     return TRUE;
 }
 
-#ifdef XSPICE
+#if defined XSPICE || defined VIRTIO_QXL
 static void
 qxl_save_state(ScrnInfoPtr pScrn)
 {
@@ -589,7 +715,10 @@  qxl_reset_and_create_mem_slots (qxl_screen_t *qxl)
 
     qxl->mem_slots = xnfalloc (qxl->n_mem_slots * sizeof (qxl_memslot_t));
 
-#ifdef XSPICE
+#ifdef VIRTIO_QXL
+    virtio_init_qxl_ram(qxl);
+    qxl->main_mem_slot = qxl->vram_mem_slot = setup_slot(qxl, 0, 0, ~0, 0, ~0);
+#elif defined XSPICE
     qxl->main_mem_slot = qxl->vram_mem_slot = setup_slot(qxl, 0, 0, ~0, 0, ~0);
 #else /* QXL */
     qxl->main_mem_slot = setup_slot(qxl, 0,
@@ -616,7 +745,7 @@  qxl_mark_mem_unverifiable(qxl_screen_t *qxl)
 void
 qxl_io_destroy_all_surfaces (qxl_screen_t *qxl)
 {
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
     if (qxl->pci->revision >= 3)
     {
         ioport_write(qxl, QXL_IO_DESTROY_ALL_SURFACES_ASYNC, 0);
@@ -648,7 +777,7 @@  qxl_close_screen(CLOSE_SCREEN_ARGS_DECL)
     
     result = pScreen->CloseScreen(CLOSE_SCREEN_ARGS);
 
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
     if (!xf86IsPrimaryPci (qxl->pci) && qxl->primary)
        qxl_reset_and_create_mem_slots (qxl);
 #endif
@@ -679,7 +808,7 @@  set_screen_pixmap_header (ScreenPtr pScreen)
 	
 	pScreen->ModifyPixmapHeader(
 	    pPixmap,
-	    qxl->current_mode->x_res, qxl->current_mode->y_res,
+	    le32toh(qxl->current_mode->x_res), le32toh(qxl->current_mode->y_res),
 	    -1, -1,
 	    qxl->pScrn->displayWidth * qxl->bytes_per_pixel,
 	    NULL);
@@ -1170,20 +1299,20 @@  qxl_screen_init(SCREEN_INIT_ARGS_DECL)
     qxl_reset_and_create_mem_slots (qxl);
     ErrorF ("done reset\n");
 
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
     qxl->io_pages = (void *)((unsigned long)qxl->ram);
     qxl->io_pages_physical = (void *)((unsigned long)qxl->ram_physical);
 #endif
 
     qxl->command_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->cmd_ring),
 					 sizeof (struct QXLCommand),
-					 QXL_COMMAND_RING_SIZE, QXL_IO_NOTIFY_CMD, qxl);
+					 QXL_COMMAND_RING_SIZE, QXL_IO_NOTIFY_CMD, qxl,COMMAND_RING);
     qxl->cursor_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->cursor_ring),
 					sizeof (struct QXLCommand),
-					QXL_CURSOR_RING_SIZE, QXL_IO_NOTIFY_CURSOR, qxl);
+					QXL_CURSOR_RING_SIZE, QXL_IO_NOTIFY_CURSOR, qxl,CURSOR_RING);
     qxl->release_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->release_ring),
 					 sizeof (uint64_t),
-					 QXL_RELEASE_RING_SIZE, 0, qxl);
+					 QXL_RELEASE_RING_SIZE, 0, qxl,RELEASE_RING);
 
     qxl->surface_cache = qxl_surface_cache_create (qxl);
     
@@ -1325,12 +1454,12 @@  print_modes (qxl_screen_t *qxl, int scrnIndex)
 	
 	xf86DrvMsg (scrnIndex, X_INFO,
 		    "%d: %dx%d, %d bits, stride %d, %dmm x %dmm, orientation %d\n",
-		    m->id, m->x_res, m->y_res, m->bits, m->stride, m->x_mili,
-		    m->y_mili, m->orientation);
+		    le32toh(m->id), le32toh(m->x_res), le32toh(m->y_res), le32toh(m->bits), le32toh(m->stride), le32toh(m->x_mili),
+		    le32toh(m->y_mili), le32toh(m->orientation));
     }
 }
 
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
 static Bool
 qxl_check_device(ScrnInfoPtr pScrn, qxl_screen_t *qxl)
 {
@@ -1381,18 +1510,18 @@  qxl_find_native_mode(ScrnInfoPtr pScrn, DisplayModePtr p)
     for (i = 0; i < qxl->num_modes; i++) 
     {
 	struct QXLMode *m = qxl->modes + i;
-	
-	if (m->x_res == p->HDisplay &&
-	    m->y_res == p->VDisplay &&
-	    m->bits == pScrn->bitsPerPixel)
+
+	if (le32toh(m->x_res) == p->HDisplay &&
+	    le32toh(m->y_res) == p->VDisplay &&
+	    le32toh(m->bits) == pScrn->bitsPerPixel)
 	{
-	    if (m->bits == 16) 
+	    if (le32toh(m->bits) == 16)
 	    {
 		/* What QXL calls 16 bit is actually x1r5g5b515 */
 		if (pScrn->depth == 15)
 		    return i;
 	    }
-	    else if (m->bits == 32)
+	    else if (le32toh(m->bits) == 32)
 	    {
 		/* What QXL calls 32 bit is actually x8r8g8b8 */
 		if (pScrn->depth == 24)
@@ -1499,7 +1628,7 @@  qxl_pre_init(ScrnInfoPtr pScrn, int flags)
 
     qxl->entity = xf86GetEntityInfo(pScrn->entityList[0]);
     
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
     qxl->pci = xf86GetPciInfoForEntity(qxl->entity->index);
 #ifndef XSERVER_LIBPCIACCESS
     qxl->pci_tag = pciTag(qxl->pci->bus, qxl->pci->device, qxl->pci->func);
@@ -1529,19 +1658,28 @@  qxl_pre_init(ScrnInfoPtr pScrn, int flags)
 	       qxl->enable_image_cache? "Enabled" : "Disabled");
     xf86DrvMsg(scrnIndex, X_INFO, "Fallback Cache: %s\n",
 	       qxl->enable_fallback_cache? "Enabled" : "Disabled");
-    
+
+#ifdef VIRTIO_QXL
+    qxl->device_name = xf86FindOptionValue(pScrn->options,"virtiodev");
+
+    if (!qxl->device_name)
+        qxl->device_name = VIRTIO_DEV;
+
+    xf86DrvMsg(scrnIndex, X_INFO, "Using virtio device %s.\n", qxl->device_name);
+#endif
+
     if (!qxl_map_memory(qxl, scrnIndex))
 	goto out;
-    
-#ifndef XSPICE
+
+#if (!defined XSPICE && !defined VIRTIO_QXL)
     if (!qxl_check_device(pScrn, qxl))
 	goto out;
-#else
+#elif defined XSPICE
     xspice_init_qxl_ram(qxl); /* initialize the rings */
 #endif
-    pScrn->videoRam = (qxl->rom->num_pages * 4096) / 1024;
+    pScrn->videoRam = (le32toh(qxl->rom->num_pages) * 4096) / 1024;
     xf86DrvMsg(scrnIndex, X_INFO, "%d KB of video RAM\n", pScrn->videoRam);
-    xf86DrvMsg(scrnIndex, X_INFO, "%d surfaces\n", qxl->rom->n_surfaces);
+    xf86DrvMsg(scrnIndex, X_INFO, "%d surfaces\n", le32toh(qxl->rom->n_surfaces));
 
     /* ddc stuff here */
     
@@ -1568,13 +1706,13 @@  qxl_pre_init(ScrnInfoPtr pScrn, int flags)
     
     /* Add any modes not in xorg's default mode list */
     for (i = 0; i < qxl->num_modes; i++)
-        if (qxl->modes[i].orientation == 0) {
-            qxl_add_mode(pScrn, qxl->modes[i].x_res, qxl->modes[i].y_res,
+        if (le32toh(qxl->modes[i].orientation) == 0) {
+            qxl_add_mode(pScrn, le32toh(qxl->modes[i].x_res), le32toh(qxl->modes[i].y_res),
                          M_T_DRIVER);
-            if (qxl->modes[i].x_res > max_x)
-                max_x = qxl->modes[i].x_res;
-            if (qxl->modes[i].y_res > max_y)
-                max_y = qxl->modes[i].y_res;
+            if (le32toh(qxl->modes[i].x_res) > max_x)
+                max_x = le32toh(qxl->modes[i].x_res);
+            if (le32toh(qxl->modes[i].y_res) > max_y)
+                max_y = le32toh(qxl->modes[i].y_res);
         }
 
     if (pScrn->display->virtualX == 0 && pScrn->display->virtualY == 0) {
@@ -1582,8 +1720,8 @@  qxl_pre_init(ScrnInfoPtr pScrn, int flags)
            to a virtual size which will not fit into the framebuffer when this
            happens we prefer max width and make height as large as possible */
         if (max_x * max_y * (pScrn->bitsPerPixel / 8) >
-                qxl->rom->surface0_area_size)
-            pScrn->display->virtualY = qxl->rom->surface0_area_size /
+                le32toh(qxl->rom->surface0_area_size))
+            pScrn->display->virtualY = le32toh(qxl->rom->surface0_area_size) /
                                        (max_x * (pScrn->bitsPerPixel / 8));
         else
             pScrn->display->virtualY = max_y;
@@ -1618,7 +1756,7 @@  qxl_pre_init(ScrnInfoPtr pScrn, int flags)
     xf86SetDpi(pScrn, 0, 0);
     
     if (!xf86LoadSubModule(pScrn, "fb")
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
 	|| !xf86LoadSubModule(pScrn, "ramdac")
 	|| !xf86LoadSubModule(pScrn, "vgahw")
 #endif
@@ -1629,7 +1767,7 @@  qxl_pre_init(ScrnInfoPtr pScrn, int flags)
     
     print_modes (qxl, scrnIndex);
 
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
     /* VGA hardware initialisation */
     if (!vgaHWGetHWRec(pScrn))
         return FALSE;
@@ -1656,7 +1794,7 @@  out:
     return FALSE;
 }
 
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
 #ifdef XSERVER_LIBPCIACCESS
 enum qxl_class
 {
@@ -1695,7 +1833,7 @@  static PciChipsets qxlPciChips[] =
 static void
 qxl_identify(int flags)
 {
-#ifndef XSPICE
+#if (!defined XSPICE && !defined VIRTIO_QXL)
     xf86PrintChipsets("qxl", "Driver for QXL virtual graphics", qxlChips);
 #endif
 }
@@ -1713,7 +1851,7 @@  qxl_init_scrn(ScrnInfoPtr pScrn)
     pScrn->LeaveVT	    = qxl_leave_vt;
 }
 
-#ifdef XSPICE
+#if (defined VIRTIO_QXL || defined XSPICE)
 static Bool
 qxl_probe(struct _DriverRec *drv, int flags)
 {
@@ -1738,11 +1876,6 @@  qxl_probe(struct _DriverRec *drv, int flags)
 
     return TRUE;
 }
-static Bool qxl_driver_func(ScrnInfoPtr screen_info_ptr, xorgDriverFuncOp xorg_driver_func_op, pointer hw_flags)
-{
-    *(xorgHWFlags*)hw_flags = (xorgHWFlags)HW_SKIP_CONSOLE;
-    return TRUE;
-}
 #else /* normal, not XSPICE */
 #ifndef XSERVER_LIBPCIACCESS
 static Bool
@@ -1812,7 +1945,15 @@  qxl_pci_probe(DriverPtr drv, int entity, struct pci_device *dev, intptr_t match)
 #define qxl_probe NULL
 
 #endif
-#endif /* XSPICE */
+#endif /* VIRTIO_QXL || XSPICE */
+
+#ifdef XSPICE
+static Bool qxl_driver_func(ScrnInfoPtr screen_info_ptr, xorgDriverFuncOp xorg_driver_func_op, pointer hw_flags)
+{
+    *(xorgHWFlags*)hw_flags = (xorgHWFlags)HW_SKIP_CONSOLE;
+    return TRUE;
+}
+#endif
 
 static DriverRec qxl_driver = {
     0,
@@ -1822,7 +1963,11 @@  static DriverRec qxl_driver = {
     qxl_available_options,
     NULL,
     0,
-#ifdef XSPICE
+#ifdef VIRTIO_QXL
+    NULL,
+    NULL,
+    NULL
+#elif defined XSPICE
     qxl_driver_func,
     NULL,
     NULL
@@ -1870,6 +2015,8 @@  static XF86ModuleVersionInfo qxl_module_info = {
 _X_EXPORT XF86ModuleData
 #ifdef XSPICE
 spiceqxlModuleData
+#elif VIRTIO_QXL
+virtioqxlModuleData
 #else
 qxlModuleData
 #endif
diff --git a/src/qxl_logger.c b/src/qxl_logger.c
index 40025e4..98286b8 100644
--- a/src/qxl_logger.c
+++ b/src/qxl_logger.c
@@ -180,6 +180,7 @@  static void
 qxl_log_cmd_surface(qxl_screen_t *qxl, QXLSurfaceCmd *cmd)
 {
     uint64_t offset;
+    void *data;
 
     fprintf(stderr," %s id %d",
             qxl_name(qxl_surface_cmd, cmd->type),
@@ -189,7 +190,14 @@  qxl_log_cmd_surface(qxl_screen_t *qxl, QXLSurfaceCmd *cmd)
         return;
     }
 
+#ifdef VIRTIO_QXL
     offset = cmd->u.surface_create.data;
+#else
+    data = virtual_address(qxl, (void *)cmd->u.surface_create.data,
+                           qxl->vram_mem_slot);
+    offset = virtual_address(qxl, data, qxl->vram_mem_slot);
+#endif
+   
     fprintf(stderr," size %dx%d stride %d format %s data @ %llu",
             cmd->u.surface_create.width,
             cmd->u.surface_create.height,
diff --git a/src/qxl_ring.c b/src/qxl_ring.c
index 5dd1f90..e503ae0 100644
--- a/src/qxl_ring.c
+++ b/src/qxl_ring.c
@@ -46,6 +46,7 @@  struct qxl_ring
     int			n_elements;
     int			io_port_prod_notify;
     qxl_screen_t    *qxl;
+    int type;
 };
 
 struct qxl_ring *
@@ -53,7 +54,7 @@  qxl_ring_create (struct qxl_ring_header *header,
 		 int                     element_size,
 		 int                     n_elements,
 		 int			 io_port_prod_notify,
-		 qxl_screen_t           *qxl)
+		 qxl_screen_t           *qxl, int ring_type)
 {
     struct qxl_ring *ring;
 
@@ -61,6 +62,7 @@  qxl_ring_create (struct qxl_ring_header *header,
     if (!ring)
 	return NULL;
 
+    ring->type = ring_type;
     ring->ring = (volatile struct ring *)header;
     ring->element_size = element_size;
     ring->n_elements = n_elements;
@@ -69,6 +71,132 @@  qxl_ring_create (struct qxl_ring_header *header,
     return ring;
 }
 
+#ifdef VIRTIO_QXL
+static void
+update_cursor_ring(qxl_screen_t *qxl) {
+    char *push1 = (char *)qxl->cursor_ring->ring;
+    char *pull = push1 + sizeof(uint32_t) * 3;
+    char *push2 = pull + sizeof(uint32_t);
+
+    virtioqxl_push_ram(qxl, (void *)push2,
+                       sizeof(QXLCursorRing) - sizeof(uint32_t) * 4);
+    virtioqxl_push_ram(qxl, (void *)push1, sizeof(uint32_t) * 3);
+    virtioqxl_pull_ram(qxl, (void *)pull, sizeof(uint32_t));
+}
+
+static void
+update_command_ring(qxl_screen_t *qxl) {
+    char *push1 = (char *)qxl->command_ring->ring;
+    char *pull = push1 + sizeof(uint32_t) * 3;
+    char *push2 = pull + sizeof(uint32_t);
+
+    virtioqxl_push_ram(qxl, (void *)push2,
+                       sizeof(QXLCommandRing) - sizeof(uint32_t) * 4);
+    virtioqxl_push_ram(qxl, (void *)push1, sizeof(uint32_t) * 3);
+    virtioqxl_pull_ram(qxl, (void *)pull, sizeof(uint32_t));
+}
+
+static void
+update_release_ring(qxl_screen_t *qxl) {
+    char *pull1 = (char *)qxl->release_ring->ring;
+    char *push = pull1 + sizeof(uint32_t) * 3;
+    char *pull2 = push + sizeof(uint32_t);
+
+    virtioqxl_pull_ram(qxl, (void *)pull2,
+                       sizeof(QXLReleaseRing) - sizeof(uint32_t) * 4);
+    virtioqxl_pull_ram(qxl, (void *)pull1, sizeof(uint32_t) * 3);
+    virtioqxl_push_ram(qxl, (void *)push, sizeof(uint32_t));
+}
+#endif
+
+#ifdef VIRTIO_QXL
+static void
+qxl_ring_push_command(struct qxl_ring *ring, struct QXLCommand *cmd)
+{
+    qxl_screen_t *qxl = ring->qxl;
+
+    switch (cmd->type) {
+        case QXL_CMD_SURFACE:
+        {
+            int stride;
+            QXLSurface surf;
+            uint8_t *ptr;
+            QXLSurfaceCmd *c = virtual_address(qxl, (void *)cmd->data,
+                                               qxl->main_mem_slot);
+
+            virtioqxl_push_ram(qxl, (void *)c, sizeof(*c));
+
+            if (c->type == QXL_SURFACE_CMD_DESTROY) {
+                break;
+            }
+
+            surf = c->u.surface_create;
+            stride = abs(surf.stride);
+            ptr = virtual_address(qxl, (void *)surf.data, qxl->vram_mem_slot);
+            virtioqxl_push_ram(qxl, (void *)ptr,
+                               surf.height * stride + stride);
+            break;
+        }
+        case QXL_CMD_DRAW:
+        {
+            QXLPHYSICAL addr;
+            QXLImage *image;
+            QXLDataChunk *chunk;
+            QXLDrawable *draw = virtual_address(qxl, (void *)cmd->data,
+                                                qxl->main_mem_slot);
+
+            virtioqxl_push_ram(qxl, (void *)draw, sizeof(*draw));
+
+            if (draw->type != QXL_DRAW_COPY) {
+                break;
+            }
+
+            image = virtual_address(qxl, (void *)draw->u.copy.src_bitmap,
+                                    qxl->main_mem_slot);
+            virtioqxl_push_ram(qxl, (void *)image, sizeof(*image));
+
+            if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) {
+                break;
+            }
+
+            if (image->bitmap.flags & QXL_BITMAP_DIRECT) {
+                uint8_t *ptr = virtual_address(qxl, (void *)image->bitmap.data,
+                                               qxl->main_mem_slot);
+                virtioqxl_push_ram(qxl, (void *)ptr,
+                        image->descriptor.height * image->bitmap.stride);
+                break;
+            }
+            addr = image->bitmap.data;
+            while (addr) {
+                chunk = virtual_address(qxl, (void *)addr, qxl->main_mem_slot);
+                virtioqxl_push_ram(qxl, (void *)chunk,
+                                   sizeof(*chunk) + chunk->data_size);
+                addr = chunk->next_chunk;
+            }
+            break;
+        }
+        case QXL_CMD_CURSOR:
+        {
+            QXLCursor *cursor;
+            QXLCursorCmd *c = virtual_address(qxl, (void *)cmd->data,
+                                              qxl->main_mem_slot);
+
+            virtioqxl_push_ram(qxl, (void *)c, sizeof(*c));
+
+            if (c->type != QXL_CURSOR_SET) {
+                break;
+            }
+
+            cursor = virtual_address(qxl, (void *)c->u.set.shape,
+                                     qxl->main_mem_slot);
+            virtioqxl_push_ram(qxl, (void *)cursor,
+                               sizeof(*cursor) + cursor->data_size);
+            break;
+        }
+    }
+}
+#endif // VIRTIO_QXL
+
 void
 qxl_ring_push (struct qxl_ring *ring,
 	       const void      *new_elt)
@@ -77,18 +205,40 @@  qxl_ring_push (struct qxl_ring *ring,
     volatile uint8_t *elt;
     int idx;
 
-#ifdef DUMP_COMMANDS
-    struct QXLCommand *cmd = (QXLCommand *)new_elt;
+#if defined VIRTIO_QXL || defined ENABLE_DEBUG
+    struct QXLCommand *cmd = (QXLCommand *)new_elt;    
+#endif
+    
+#ifdef VIRTIO_QXL
+    struct QXLRam *ram = get_ram_header(ring->qxl);
+    if(ring->type == CURSOR_RING){
+        // When the guest stop sending cursor commands, the host side
+        // consumer(libspice thread) sleeps. This avoid a delay when starting
+        // to move the mouse again.
+        if(SPICE_RING_IS_EMPTY(&ram->cursor_ring)){
+            ioport_write(ring->qxl, QXL_IO_NOTIFY_CURSOR, 0);
+        }
+    }
+    qxl_ring_push_command(ring, cmd);
+#endif
+
+#ifdef ENABLE_DEBUG
     qxl_log_command(ring->qxl, cmd, "");
 #endif 
     
     while (header->prod - header->cons == header->num_items)
     {
-	header->notify_on_cons = header->cons + 1;
+#ifdef VIRTIO_QXL
+        ioport_write(ring->qxl, QXL_IO_NOTIFY_CURSOR, 0);
+        update_command_ring(ring->qxl);
+        update_cursor_ring(ring->qxl);
+        sched_yield();
+#endif
+        header->notify_on_cons = header->cons + 1;
 #ifdef XSPICE
 	/* in gtkperf, circles, this is a major bottleneck. Can't be that good in a vm either
 	 * Adding the yield reduces cpu usage, but doesn't improve throughput. */
-	sched_yield();
+        sched_yield();
 #endif
 	mem_barrier();
     }
@@ -102,6 +252,11 @@  qxl_ring_push (struct qxl_ring *ring,
 
     mem_barrier();
 
+#ifdef VIRTIO_QXL
+    update_command_ring(ring->qxl);
+    update_cursor_ring(ring->qxl);
+#endif
+
     if (header->prod == header->notify_on_prod) {
         ioport_write (ring->qxl, ring->io_port_prod_notify, 0);
     }
@@ -115,6 +270,10 @@  qxl_ring_pop (struct qxl_ring *ring,
     volatile uint8_t *ring_elt;
     int idx;
 
+#ifdef VIRTIO_QXL
+    update_release_ring(ring->qxl);
+#endif
+
     if (header->cons == header->prod)
 	return FALSE;
 
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index 113f09b..22823ba 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -57,41 +57,6 @@  static FILE* surface_log;
 
 typedef struct evacuated_surface_t evacuated_surface_t;
 
-struct qxl_surface_t
-{
-    surface_cache_t    *cache;
-    
-    uint32_t	        id;
-
-    pixman_image_t *	dev_image;
-    pixman_image_t *	host_image;
-
-    uxa_access_t	access_type;
-    RegionRec		access_region;
-
-    void *		address;
-    void *		end;
-    
-    qxl_surface_t *	next;
-    qxl_surface_t *	prev;	/* Only used in the 'live'
-				 * chain in the surface cache
-				 */
-
-    int			in_use;
-    int			bpp;		/* bpp of the pixmap */
-    int			ref_count;
-
-    PixmapPtr		pixmap;
-
-    struct evacuated_surface_t *evacuated;
-
-    union
-    {
-	qxl_surface_t *copy_src;
-	Pixel	       solid_pixel;
-    } u;
-};
-
 struct evacuated_surface_t
 {
     pixman_image_t	*image;
@@ -169,7 +134,7 @@  static void debug_surface_log(surface_cache_t *cache)
 static Bool
 surface_cache_init (surface_cache_t *cache, qxl_screen_t *qxl)
 {
-    int n_surfaces = qxl->rom->n_surfaces;
+    int n_surfaces = le32toh(qxl->rom->n_surfaces);
     int i;
 
     if (!cache->all_surfaces)
@@ -356,38 +321,40 @@  qxl_surface_cache_create_primary (surface_cache_t	*cache,
     qxl_surface_t *surface;
     qxl_screen_t *qxl = cache->qxl;
 
-    if (mode->bits == 16)
+    if (le32toh(mode->bits) == 16)
     {
 	format = PIXMAN_x1r5g5b5;
     }
-    else if (mode->bits == 32)
+    else if (le32toh(mode->bits) == 32)
     {
 	format = PIXMAN_x8r8g8b8;
     }
     else
     {
-	xf86DrvMsg (cache->qxl->pScrn->scrnIndex, X_ERROR,
-		    "Unknown bit depth %d\n", mode->bits);
+        xf86DrvMsg (cache->qxl->pScrn->scrnIndex, X_ERROR,
+		    "Unknown bit depth %d\n", le32toh(mode->bits));
 	return NULL;
     }
-	
-    create->width = mode->x_res;
-    create->height = mode->y_res;
-    create->stride = - mode->stride;
-    create->format = mode->bits;
-    create->position = 0; /* What is this? The Windows driver doesn't use it */
-    create->flags = 0;
-    create->type = QXL_SURF_TYPE_PRIMARY;
-    create->mem = physical_address (cache->qxl, cache->qxl->ram, cache->qxl->main_mem_slot);
+    
+    create->width	= mode->x_res; //this will be sent to the host that spect LE values
+    create->height 	= mode->y_res; //Modes is in LE already. No need to convert
+    create->stride 	= htole32(-le32toh(mode->stride));
+    create->format 	= mode->bits;
+    create->position 	= 0; /* What is this? The Windows driver doesn't use it */
+    create->flags 	= 0;
+    create->type 	= htole32(QXL_SURF_TYPE_PRIMARY);
+    create->mem 	= htole64(physical_address(cache->qxl, cache->qxl->ram, cache->qxl->main_mem_slot));
+
+#ifdef VIRTIO_QXL
+    virtioqxl_push_ram(qxl, create, sizeof(*create));
+#endif
 
     qxl_io_create_primary(qxl);
 
-    dev_addr = (uint8_t *)qxl->ram + mode->stride * (mode->y_res - 1);
-
-    dev_image = pixman_image_create_bits (format, mode->x_res, mode->y_res,
-					  (uint32_t *)dev_addr, -mode->stride);
-
-    host_image = pixman_image_create_bits (format, 
+    dev_addr = (uint8_t *)qxl->ram + le32toh(mode->stride) * (le32toh(mode->y_res) - 1);
+    dev_image = pixman_image_create_bits (format, le32toh(mode->x_res), le32toh(mode->y_res),
+					  (uint32_t *)dev_addr, le32toh(-mode->stride));
+    host_image = pixman_image_create_bits (format,
 					   qxl->virtual_x, qxl->virtual_y,
 					   qxl->fb, qxl->stride);
 
@@ -396,7 +363,7 @@  qxl_surface_cache_create_primary (surface_cache_t	*cache,
     surface->dev_image = dev_image;
     surface->host_image = host_image;
     surface->cache = cache;
-    surface->bpp = mode->bits;
+    surface->bpp = le32toh(mode->bits);
     surface->next = NULL;
     surface->prev = NULL;
     surface->evacuated = NULL;
@@ -486,7 +453,7 @@  make_drawable (qxl_screen_t *qxl, int surface, uint8_t type,
     if (rect)
 	drawable->bbox = *rect;
     
-    drawable->mm_time = qxl->rom->mm_clock;
+    drawable->mm_time = le32toh(qxl->rom->mm_clock);
     
     return drawable;
 }
@@ -894,14 +861,13 @@  download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
 {
     struct QXLRam *ram_header = get_ram_header (surface->cache->qxl);
     
-    ram_header->update_area.top = y1;
-    ram_header->update_area.bottom = y2;
-    ram_header->update_area.left = x1;
-    ram_header->update_area.right = x2;
-    
-    ram_header->update_surface = surface->id;
+    ram_header->update_area.top = htole32(y1);
+    ram_header->update_area.bottom = htole32(y2);
+    ram_header->update_area.left = htole32(x1);
+    ram_header->update_area.right = htole32(x2);
+    ram_header->update_surface = htole32(surface->id);
 
-    qxl_update_area(surface->cache->qxl);
+    qxl_update_area(surface->cache->qxl,surface);
 
     pixman_image_composite (PIXMAN_OP_SRC,
      			    surface->dev_image,