diff --git a/src/internal.h b/src/internal.h
index 4ec6edcda2..f82fbd2533 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -58,6 +58,12 @@
 # define STRCASENEQLEN(a,b,n) (strncasecmp(a,b,n) != 0)
 # define STRPREFIX(a,b) (strncmp(a,b,strlen(b)) == 0)
 
+# define STREQ_NULLABLE(a, b)                           \
+    ((!(a) && !(b)) || ((a) && (b) && STREQ((a), (b))))
+# define STRNEQ_NULLABLE(a, b)                          \
+    ((!(a) ^ !(b)) || ((a) && (b) && STRNEQ((a), (b))))
+
+
 # define NUL_TERMINATE(buf) do { (buf)[sizeof(buf)-1] = '\0'; } while (0)
 # define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cf6670dd06..0033d2a373 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -139,6 +139,7 @@ virDomainFindByName;
 virDomainFindByUUID;
 virDomainGetRootFilesystem;
 virDomainGraphicsTypeFromString;
+virDomainGraphicsTypeToString;
 virDomainGraphicsDefFree;
 virDomainHostdevDefFree;
 virDomainHostdevModeTypeToString;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 75ee98b874..5b263a7d8e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7046,6 +7046,83 @@ static int qemudDomainAttachDeviceFlags(virDomainPtr dom,
 }
 
 
+static virDomainGraphicsDefPtr qemuDomainFindGraphics(virDomainObjPtr vm,
+                                                      virDomainGraphicsDefPtr dev)
+{
+    int i;
+
+    for (i = 0 ; i < vm->def->ngraphics ; i++) {
+        if (vm->def->graphics[i]->type == dev->type)
+            return vm->def->graphics[i];
+    }
+
+    return NULL;
+}
+
+
+static int
+qemuDomainChangeGraphics(struct qemud_driver *driver,
+                         virDomainObjPtr vm,
+                         virDomainGraphicsDefPtr dev)
+{
+    virDomainGraphicsDefPtr olddev = qemuDomainFindGraphics(vm, dev);
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    int ret = -1;
+
+    if (!olddev) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("cannot find existing graphics device to modify"));
+        return -1;
+    }
+
+    switch (dev->type) {
+    case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
+        if ((olddev->data.vnc.autoport != dev->data.vnc.autoport) ||
+            (!dev->data.vnc.autoport && (olddev->data.vnc.port != dev->data.vnc.port))) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("cannot change port settings on vnc graphics"));
+            return -1;
+        }
+        if (STRNEQ_NULLABLE(olddev->data.vnc.listenAddr, dev->data.vnc.listenAddr)) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("cannot change listen address setting on vnc graphics"));
+            return -1;
+        }
+        if (STRNEQ_NULLABLE(olddev->data.vnc.keymap, dev->data.vnc.keymap)) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("cannot change keymap setting on vnc graphics"));
+            return -1;
+        }
+
+        if (STRNEQ_NULLABLE(olddev->data.vnc.passwd, dev->data.vnc.passwd)) {
+            VIR_DEBUG("Updating password on VNC server %p %p", dev->data.vnc.passwd, driver->vncPassword);
+            qemuDomainObjEnterMonitorWithDriver(driver, vm);
+            ret = qemuMonitorSetVNCPassword(priv->mon,
+                                            dev->data.vnc.passwd ?
+                                            dev->data.vnc.passwd :
+                                            driver->vncPassword);
+            qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+            /* Steal the new dev's  char * reference */
+            VIR_FREE(olddev->data.vnc.passwd);
+            olddev->data.vnc.passwd = dev->data.vnc.passwd;
+            dev->data.vnc.passwd = NULL;
+        } else {
+            ret = 0;
+        }
+        break;
+
+    default:
+        qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("unable to change config on '%s' graphics type"),
+                        virDomainGraphicsTypeToString(dev->type));
+        break;
+    }
+
+    return ret;
+}
+
+
 static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
                                        const char *xml,
                                        unsigned int flags)
@@ -7134,6 +7211,10 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
         }
         break;
 
+    case VIR_DOMAIN_DEVICE_GRAPHICS:
+        ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics);
+        break;
+
     default:
         qemuReportError(VIR_ERR_NO_SUPPORT,
                         _("disk device type '%s' cannot be updated"),
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index f998d77d7b..2877a00135 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -39,7 +39,8 @@
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
-#define QEMU_DEBUG_RAW_IO 0
+#define DEBUG_IO 0
+#define DEBUG_RAW_IO 0
 
 struct _qemuMonitor {
     virMutex lock;
@@ -302,7 +303,8 @@ qemuMonitorIOProcess(qemuMonitorPtr mon)
     if (mon->msg && mon->msg->txOffset == mon->msg->txLength)
         msg = mon->msg;
 
-#if QEMU_DEBUG_RAW_IO
+#if DEBUG_IO
+#if DEBUG_RAW_IO
     char *str1 = qemuMonitorEscapeNonPrintable(msg ? msg->txBuffer : "");
     char *str2 = qemuMonitorEscapeNonPrintable(mon->buffer);
     VIR_ERROR("Process %d %p %p [[[[%s]]][[[%s]]]", (int)mon->bufferOffset, mon->msg, msg, str1, str2);
@@ -311,6 +313,8 @@ qemuMonitorIOProcess(qemuMonitorPtr mon)
 #else
     VIR_DEBUG("Process %d", (int)mon->bufferOffset);
 #endif
+#endif
+
     if (mon->json)
         len = qemuMonitorJSONIOProcess(mon,
                                        mon->buffer, mon->bufferOffset,
@@ -332,7 +336,9 @@ qemuMonitorIOProcess(qemuMonitorPtr mon)
         VIR_FREE(mon->buffer);
         mon->bufferOffset = mon->bufferLength = 0;
     }
+#if DEBUG_IO
     VIR_DEBUG("Process done %d used %d", (int)mon->bufferOffset, len);
+#endif
     if (msg && msg->finished)
         virCondBroadcast(&mon->notify);
     return len;
@@ -455,7 +461,9 @@ qemuMonitorIORead(qemuMonitorPtr mon)
         mon->buffer[mon->bufferOffset] = '\0';
     }
 
+#if DEBUG_IO
     VIR_DEBUG("Now read %d bytes of data", (int)mon->bufferOffset);
+#endif
 
     return ret;
 }
@@ -485,7 +493,9 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
 
     qemuMonitorLock(mon);
     qemuMonitorRef(mon);
+#if DEBUG_IO
     VIR_DEBUG("Monitor %p I/O on watch %d fd %d events %d", mon, watch, fd, events);
+#endif
 
     if (mon->fd != fd || mon->watch != watch) {
         VIR_ERROR("event from unexpected fd %d!=%d / watch %d!=%d", mon->fd, fd, mon->watch, watch);
@@ -981,6 +991,9 @@ int qemuMonitorSetVNCPassword(qemuMonitorPtr mon,
     int ret;
     DEBUG("mon=%p, fd=%d", mon, mon->fd);
 
+    if (!password)
+        password = "";
+
     if (mon->json)
         ret = qemuMonitorJSONSetVNCPassword(mon, password);
     else