summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--block.c1
-rw-r--r--block/qapi.c1
-rw-r--r--block/qcow2.c3
-rw-r--r--block/raw-posix.c2
-rw-r--r--block/sheepdog.c4
-rw-r--r--block/vmdk.c8
-rw-r--r--block/vvfat.c7
-rw-r--r--blockdev.c7
-rw-r--r--bsd-user/bsdload.c2
-rw-r--r--bsd-user/elfload.c2
-rw-r--r--bsd-user/main.c14
-rw-r--r--hw/usb/core.c21
-rw-r--r--hw/usb/desc.c12
-rw-r--r--hw/usb/hcd-ehci.c79
-rw-r--r--hw/usb/hcd-uhci.c36
-rw-r--r--hw/usb/hcd-xhci.c47
-rw-r--r--hw/usb/host-libusb.c76
-rw-r--r--include/hw/i386/pc.h4
-rw-r--r--include/hw/usb.h1
-rw-r--r--include/hw/usb/ehci-regs.h82
-rw-r--r--include/hw/usb/uhci-regs.h40
-rw-r--r--include/ui/console.h2
-rw-r--r--pc-bios/bios-256k.binbin262144 -> 262144 bytes
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--pc-bios/vgabios-cirrus.binbin37376 -> 37376 bytes
-rw-r--r--pc-bios/vgabios-qxl.binbin37376 -> 37376 bytes
-rw-r--r--pc-bios/vgabios-stdvga.binbin37376 -> 37376 bytes
-rw-r--r--pc-bios/vgabios-vmware.binbin37376 -> 37376 bytes
-rw-r--r--pc-bios/vgabios.binbin36864 -> 37376 bytes
-rw-r--r--qemu-img.c7
-rw-r--r--qemu-io.c22
m---------roms/seabios0
-rw-r--r--tests/Makefile4
-rw-r--r--tests/libqos/pci.c2
-rw-r--r--tests/usb-hcd-ehci-test.c153
-rw-r--r--trace-events10
-rw-r--r--ui/console.c33
-rw-r--r--ui/sdl2.c68
-rw-r--r--ui/vnc-enc-tight.c8
-rw-r--r--ui/vnc.c61
40 files changed, 597 insertions, 222 deletions
diff --git a/block.c b/block.c
index a517d72d71..310ea89fce 100644
--- a/block.c
+++ b/block.c
@@ -1228,6 +1228,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
                        bdref_key);
             ret = -EINVAL;
         }
+        QDECREF(image_options);
         goto done;
     }
 
diff --git a/block/qapi.c b/block/qapi.c
index 75f44f1537..97e16418ef 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -475,6 +475,7 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
         case QTYPE_QERROR: {
             QString *value = qerror_human((QError *)obj);
             func_fprintf(f, "%s", qstring_get_str(value));
+            QDECREF(value);
             break;
         }
         case QTYPE_NONE:
diff --git a/block/qcow2.c b/block/qcow2.c
index a4b97e8263..a54d2ba897 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1308,6 +1308,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
     options = qdict_clone_shallow(bs->options);
 
     ret = qcow2_open(bs, options, flags, &local_err);
+    QDECREF(options);
     if (local_err) {
         error_setg(errp, "Could not reopen qcow2 layer: %s",
                    error_get_pretty(local_err));
@@ -1318,8 +1319,6 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
         return;
     }
 
-    QDECREF(options);
-
     if (crypt_method) {
         s->crypt_method = crypt_method;
         memcpy(&s->aes_encrypt_key, &aes_encrypt_key, sizeof(aes_encrypt_key));
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 6586a0c9e1..b7f0f2624b 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -1192,7 +1192,7 @@ again:
         if (size == 0)
 #endif
 #if defined(__APPLE__) && defined(__MACH__)
-        size = LONG_LONG_MAX;
+        size = LLONG_MAX;
 #else
         size = lseek(fd, 0LL, SEEK_END);
 #endif
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 39f746157a..4ecbf5f498 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -2176,6 +2176,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag));
     /* we don't need to update entire object */
     datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
+    inode = g_malloc(datalen);
 
     /* refresh inode. */
     fd = connect_to_sdog(s, &local_err);
@@ -2202,8 +2203,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
         goto cleanup;
     }
 
-    inode = (SheepdogInode *)g_malloc(datalen);
-
     ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
                       s->inode.nr_copies, datalen, 0, s->cache_flags);
 
@@ -2217,6 +2216,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
             s->inode.name, s->inode.snap_id, s->inode.vdi_id);
 
 cleanup:
+    g_free(inode);
     closesocket(fd);
     return ret;
 }
diff --git a/block/vmdk.c b/block/vmdk.c
index 480ea37d7c..2b38f61fcd 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1534,7 +1534,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
     int ret, i;
     BlockDriverState *bs = NULL;
     VMDK4Header header;
-    Error *local_err;
+    Error *local_err = NULL;
     uint32_t tmp, magic, grains, gd_sectors, gt_size, gt_count;
     uint32_t *gd_buf = NULL;
     int gd_buf_size;
@@ -1700,7 +1700,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
 {
     int idx = 0;
     BlockDriverState *new_bs = NULL;
-    Error *local_err;
+    Error *local_err = NULL;
     char *desc = NULL;
     int64_t total_size = 0, filesize;
     const char *adapter_type = NULL;
@@ -1881,7 +1881,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
     } else {
         ret = bdrv_create_file(filename, options, &local_err);
         if (ret < 0) {
-            error_setg_errno(errp, -ret, "Could not create image file");
+            error_propagate(errp, local_err);
             goto exit;
         }
     }
@@ -1889,7 +1889,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
     ret = bdrv_open(&new_bs, filename, NULL, NULL,
                     BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
     if (ret < 0) {
-        error_setg_errno(errp, -ret, "Could not write description");
+        error_propagate(errp, local_err);
         goto exit;
     }
     ret = bdrv_pwrite(new_bs, desc_offset, desc, desc_len);
diff --git a/block/vvfat.c b/block/vvfat.c
index 8f5114bd16..3cda19f2f3 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -787,7 +787,9 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
 	    s->current_mapping->path=buffer;
 	    s->current_mapping->read_only =
 		(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
-	}
+        } else {
+            g_free(buffer);
+        }
     }
     closedir(dir);
 
@@ -1866,7 +1868,7 @@ static int check_directory_consistency(BDRVVVFATState *s,
 
 	if (s->used_clusters[cluster_num] & USED_ANY) {
 	    fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
-	    return 0;
+            goto fail;
 	}
 	s->used_clusters[cluster_num] = USED_DIRECTORY;
 
@@ -2929,6 +2931,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
     set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
 
     ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, errp);
+    free_option_parameters(options);
     if (ret < 0) {
         goto err;
     }
diff --git a/blockdev.c b/blockdev.c
index 8cc42fb1d0..9b5261b765 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -351,7 +351,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
     if (error) {
         error_propagate(errp, error);
-        return NULL;
+        goto err_no_opts;
     }
 
     qemu_opts_absorb_qdict(opts, bs_opts, &error);
@@ -564,8 +564,9 @@ bdrv_new_err:
     g_free(dinfo->id);
     g_free(dinfo);
 early_err:
-    QDECREF(bs_opts);
     qemu_opts_del(opts);
+err_no_opts:
+    QDECREF(bs_opts);
     return NULL;
 }
 
@@ -939,6 +940,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 
     /* Actual block device init: Functionality shared with blockdev-add */
     dinfo = blockdev_init(filename, bs_opts, &local_err);
+    bs_opts = NULL;
     if (dinfo == NULL) {
         if (local_err) {
             error_report("%s", error_get_pretty(local_err));
@@ -976,6 +978,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 
 fail:
     qemu_opts_del(legacy_opts);
+    QDECREF(bs_opts);
     return dinfo;
 }
 
diff --git a/bsd-user/bsdload.c b/bsd-user/bsdload.c
index 6b52e08720..2abc7136e0 100644
--- a/bsd-user/bsdload.c
+++ b/bsd-user/bsdload.c
@@ -183,7 +183,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
                 && bprm.buf[3] == 'F') {
             retval = load_elf_binary(&bprm,regs,infop);
         } else {
-            error_report("Unknown binary format");
+            fprintf(stderr, "Unknown binary format\n");
             return -1;
         }
     }
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 95652b1887..93fd9e4259 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -628,7 +628,7 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
     while (argc-- > 0) {
         tmp = argv[argc];
         if (!tmp) {
-            error_report("VFS: argc is wrong");
+            fprintf(stderr, "VFS: argc is wrong");
             exit(-1);
         }
         tmp1 = tmp;
diff --git a/bsd-user/main.c b/bsd-user/main.c
index de74d17cde..4ba61da896 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -378,8 +378,8 @@ void cpu_loop(CPUX86State *env)
 #endif
         default:
             pc = env->segs[R_CS].base + env->eip;
-            error_report("qemu: 0x%08lx: unhandled CPU exception 0x%x"
-                         " - aborting", (long)pc, trapnr);
+            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
+                    (long)pc, trapnr);
             abort();
         }
         process_pending_signals(env);
@@ -752,7 +752,7 @@ int main(int argc, char **argv)
     module_call_init(MODULE_INIT_QOM);
 
     if ((envlist = envlist_create()) == NULL) {
-        error_report("Unable to allocate envlist");
+        (void) fprintf(stderr, "Unable to allocate envlist\n");
         exit(1);
     }
 
@@ -794,7 +794,7 @@ int main(int argc, char **argv)
         } else if (!strcmp(r, "ignore-environment")) {
             envlist_free(envlist);
             if ((envlist = envlist_create()) == NULL) {
-                error_report("Unable to allocate envlist");
+                (void) fprintf(stderr, "Unable to allocate envlist\n");
                 exit(1);
             }
         } else if (!strcmp(r, "U")) {
@@ -816,7 +816,7 @@ int main(int argc, char **argv)
             qemu_host_page_size = atoi(argv[optind++]);
             if (qemu_host_page_size == 0 ||
                 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
-                error_report("page size must be a power of two");
+                fprintf(stderr, "page size must be a power of two\n");
                 exit(1);
             }
         } else if (!strcmp(r, "g")) {
@@ -910,7 +910,7 @@ int main(int argc, char **argv)
        qemu_host_page_size */
     env = cpu_init(cpu_model);
     if (!env) {
-        error_report("Unable to find CPU definition");
+        fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
     cpu = ENV_GET_CPU(env);
@@ -1012,7 +1012,7 @@ int main(int argc, char **argv)
 #ifndef TARGET_ABI32
     /* enable 64 bit mode if possible */
     if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
-        error_report("The selected x86 CPU does not support 64 bit mode");
+        fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
         exit(1);
     }
     env->cr[4] |= CR4_PAE_MASK;
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 67ba7d6018..cf34755bba 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -28,6 +28,26 @@
 #include "qemu/iov.h"
 #include "trace.h"
 
+void usb_pick_speed(USBPort *port)
+{
+    static const int speeds[] = {
+        USB_SPEED_SUPER,
+        USB_SPEED_HIGH,
+        USB_SPEED_FULL,
+        USB_SPEED_LOW,
+    };
+    USBDevice *udev = port->dev;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(speeds); i++) {
+        if ((udev->speedmask & (1 << speeds[i])) &&
+            (port->speedmask & (1 << speeds[i]))) {
+            udev->speed = speeds[i];
+            return;
+        }
+    }
+}
+
 void usb_attach(USBPort *port)
 {
     USBDevice *dev = port->dev;
@@ -35,6 +55,7 @@ void usb_attach(USBPort *port)
     assert(dev != NULL);
     assert(dev->attached);
     assert(dev->state == USB_STATE_NOTATTACHED);
+    usb_pick_speed(port);
     port->ops->attach(port);
     dev->state = USB_STATE_ATTACHED;
     usb_device_handle_attach(dev);
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index ab48691363..b82c397ef9 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -518,18 +518,6 @@ void usb_desc_init(USBDevice *dev)
 
 void usb_desc_attach(USBDevice *dev)
 {
-    const USBDesc *desc = usb_device_get_usb_desc(dev);
-
-    assert(desc != NULL);
-    if (desc->super && (dev->port->speedmask & USB_SPEED_MASK_SUPER)) {
-        dev->speed = USB_SPEED_SUPER;
-    } else if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
-        dev->speed = USB_SPEED_HIGH;
-    } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
-        dev->speed = USB_SPEED_FULL;
-    } else {
-        return;
-    }
     usb_desc_setdefaults(dev);
 }
 
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index a3ae9f260a..a00a93c3eb 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -27,87 +27,10 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "hw/usb/ehci-regs.h"
 #include "hw/usb/hcd-ehci.h"
 #include "trace.h"
 
-/* Capability Registers Base Address - section 2.2 */
-#define CAPLENGTH        0x0000  /* 1-byte, 0x0001 reserved */
-#define HCIVERSION       0x0002  /* 2-bytes, i/f version # */
-#define HCSPARAMS        0x0004  /* 4-bytes, structural params */
-#define HCCPARAMS        0x0008  /* 4-bytes, capability params */
-#define EECP             HCCPARAMS + 1
-#define HCSPPORTROUTE1   0x000c
-#define HCSPPORTROUTE2   0x0010
-
-#define USBCMD           0x0000
-#define USBCMD_RUNSTOP   (1 << 0)      // run / Stop
-#define USBCMD_HCRESET   (1 << 1)      // HC Reset
-#define USBCMD_FLS       (3 << 2)      // Frame List Size
-#define USBCMD_FLS_SH    2             // Frame List Size Shift
-#define USBCMD_PSE       (1 << 4)      // Periodic Schedule Enable
-#define USBCMD_ASE       (1 << 5)      // Asynch Schedule Enable
-#define USBCMD_IAAD      (1 << 6)      // Int Asynch Advance Doorbell
-#define USBCMD_LHCR      (1 << 7)      // Light Host Controller Reset
-#define USBCMD_ASPMC     (3 << 8)      // Async Sched Park Mode Count
-#define USBCMD_ASPME     (1 << 11)     // Async Sched Park Mode Enable
-#define USBCMD_ITC       (0x7f << 16)  // Int Threshold Control
-#define USBCMD_ITC_SH    16            // Int Threshold Control Shift
-
-#define USBSTS           0x0004
-#define USBSTS_RO_MASK   0x0000003f
-#define USBSTS_INT       (1 << 0)      // USB Interrupt
-#define USBSTS_ERRINT    (1 << 1)      // Error Interrupt
-#define USBSTS_PCD       (1 << 2)      // Port Change Detect
-#define USBSTS_FLR       (1 << 3)      // Frame List Rollover
-#define USBSTS_HSE       (1 << 4)      // Host System Error
-#define USBSTS_IAA       (1 << 5)      // Interrupt on Async Advance
-#define USBSTS_HALT      (1 << 12)     // HC Halted
-#define USBSTS_REC       (1 << 13)     // Reclamation
-#define USBSTS_PSS       (1 << 14)     // Periodic Schedule Status
-#define USBSTS_ASS       (1 << 15)     // Asynchronous Schedule Status
-
-/*
- *  Interrupt enable bits correspond to the interrupt active bits in USBSTS
- *  so no need to redefine here.
- */
-#define USBINTR              0x0008
-#define USBINTR_MASK         0x0000003f
-
-#define FRINDEX              0x000c
-#define CTRLDSSEGMENT        0x0010
-#define PERIODICLISTBASE     0x0014
-#define ASYNCLISTADDR        0x0018
-#define ASYNCLISTADDR_MASK   0xffffffe0
-
-#define CONFIGFLAG           0x0040
-
-/*
- * Bits that are reserved or are read-only are masked out of values
- * written to us by software
- */
-#define PORTSC_RO_MASK       0x007001c0
-#define PORTSC_RWC_MASK      0x0000002a
-#define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
-#define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
-#define PORTSC_WKCN_E        (1 << 20)    // Wake on Connect Enable
-#define PORTSC_PTC           (15 << 16)   // Port Test Control
-#define PORTSC_PTC_SH        16           // Port Test Control shift
-#define PORTSC_PIC           (3 << 14)    // Port Indicator Control
-#define PORTSC_PIC_SH        14           // Port Indicator Control Shift
-#define PORTSC_POWNER        (1 << 13)    // Port Owner
-#define PORTSC_PPOWER        (1 << 12)    // Port Power
-#define PORTSC_LINESTAT      (3 << 10)    // Port Line Status
-#define PORTSC_LINESTAT_SH   10           // Port Line Status Shift
-#define PORTSC_PRESET        (1 << 8)     // Port Reset
-#define PORTSC_SUSPEND       (1 << 7)     // Port Suspend
-#define PORTSC_FPRES         (1 << 6)     // Force Port Resume
-#define PORTSC_OCC           (1 << 5)     // Over Current Change
-#define PORTSC_OCA           (1 << 4)     // Over Current Active
-#define PORTSC_PEDC          (1 << 3)     // Port Enable/Disable Change
-#define PORTSC_PED           (1 << 2)     // Port Enable/Disable
-#define PORTSC_CSC           (1 << 1)     // Connect Status Change
-#define PORTSC_CONNECT       (1 << 0)     // Current Connect Status
-
 #define FRAME_TIMER_FREQ 1000
 #define FRAME_TIMER_NS   (1000000000 / FRAME_TIMER_FREQ)
 #define UFRAME_TIMER_NS  (FRAME_TIMER_NS / 8)
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 9b1166b2ef..c3bf72cc17 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -27,6 +27,7 @@
  */
 #include "hw/hw.h"
 #include "hw/usb.h"
+#include "hw/usb/uhci-regs.h"
 #include "hw/pci/pci.h"
 #include "qemu/timer.h"
 #include "qemu/iov.h"
@@ -37,41 +38,6 @@
 //#define DEBUG
 //#define DEBUG_DUMP_DATA
 
-#define UHCI_CMD_FGR      (1 << 4)
-#define UHCI_CMD_EGSM     (1 << 3)
-#define UHCI_CMD_GRESET   (1 << 2)
-#define UHCI_CMD_HCRESET  (1 << 1)
-#define UHCI_CMD_RS       (1 << 0)
-
-#define UHCI_STS_HCHALTED (1 << 5)
-#define UHCI_STS_HCPERR   (1 << 4)
-#define UHCI_STS_HSERR    (1 << 3)
-#define UHCI_STS_RD       (1 << 2)
-#define UHCI_STS_USBERR   (1 << 1)
-#define UHCI_STS_USBINT   (1 << 0)
-
-#define TD_CTRL_SPD     (1 << 29)
-#define TD_CTRL_ERROR_SHIFT  27
-#define TD_CTRL_IOS     (1 << 25)
-#define TD_CTRL_IOC     (1 << 24)
-#define TD_CTRL_ACTIVE  (1 << 23)
-#define TD_CTRL_STALL   (1 << 22)
-#define TD_CTRL_BABBLE  (1 << 20)
-#define TD_CTRL_NAK     (1 << 19)
-#define TD_CTRL_TIMEOUT (1 << 18)
-
-#define UHCI_PORT_SUSPEND (1 << 12)
-#define UHCI_PORT_RESET (1 << 9)
-#define UHCI_PORT_LSDA  (1 << 8)
-#define UHCI_PORT_RD    (1 << 6)
-#define UHCI_PORT_ENC   (1 << 3)
-#define UHCI_PORT_EN    (1 << 2)
-#define UHCI_PORT_CSC   (1 << 1)
-#define UHCI_PORT_CCS   (1 << 0)
-
-#define UHCI_PORT_READ_ONLY    (0x1bb)
-#define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC)
-
 #define FRAME_TIMER_FREQ 1000
 
 #define FRAME_MAX_LOOPS  256
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 54dea16009..7f2af8925f 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -498,6 +498,7 @@ typedef struct XHCIEvRingSeg {
 enum xhci_flags {
     XHCI_FLAG_USE_MSI = 1,
     XHCI_FLAG_USE_MSI_X,
+    XHCI_FLAG_SS_FIRST,
 };
 
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
@@ -714,10 +715,18 @@ static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
     case USB_SPEED_LOW:
     case USB_SPEED_FULL:
     case USB_SPEED_HIGH:
-        index = uport->index;
+        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
+            index = uport->index + xhci->numports_3;
+        } else {
+            index = uport->index;
+        }
         break;
     case USB_SPEED_SUPER:
-        index = uport->index + xhci->numports_2;
+        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
+            index = uport->index;
+        } else {
+            index = uport->index + xhci->numports_2;
+        }
         break;
     default:
         return NULL;
@@ -2856,7 +2865,7 @@ static void xhci_port_update(XHCIPort *port, int is_detach)
 
 static void xhci_port_reset(XHCIPort *port, bool warm_reset)
 {
-    trace_usb_xhci_port_reset(port->portnr);
+    trace_usb_xhci_port_reset(port->portnr, warm_reset);
 
     if (!xhci_port_have_device(port)) {
         return;
@@ -2972,7 +2981,11 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size)
         ret = 0x20425355; /* "USB " */
         break;
     case 0x28: /* Supported Protocol:08 */
-        ret = 0x00000001 | (xhci->numports_2<<8);
+        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
+            ret = (xhci->numports_2<<8) | (xhci->numports_3+1);
+        } else {
+            ret = (xhci->numports_2<<8) | 1;
+        }
         break;
     case 0x2c: /* Supported Protocol:0c */
         ret = 0x00000000; /* reserved */
@@ -2984,7 +2997,11 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size)
         ret = 0x20425355; /* "USB " */
         break;
     case 0x38: /* Supported Protocol:08 */
-        ret = 0x00000000 | (xhci->numports_2+1) | (xhci->numports_3<<8);
+        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
+            ret = (xhci->numports_3<<8) | 1;
+        } else {
+            ret = (xhci->numports_3<<8) | (xhci->numports_2+1);
+        }
         break;
     case 0x3c: /* Supported Protocol:0c */
         ret = 0x00000000; /* reserved */
@@ -3517,8 +3534,13 @@ static void usb_xhci_init(XHCIState *xhci)
     for (i = 0; i < usbports; i++) {
         speedmask = 0;
         if (i < xhci->numports_2) {
-            port = &xhci->ports[i];
-            port->portnr = i + 1;
+            if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
+                port = &xhci->ports[i + xhci->numports_3];
+                port->portnr = i + 1 + xhci->numports_3;
+            } else {
+                port = &xhci->ports[i];
+                port->portnr = i + 1;
+            }
             port->uport = &xhci->uports[i];
             port->speedmask =
                 USB_SPEED_MASK_LOW  |
@@ -3528,8 +3550,13 @@ static void usb_xhci_init(XHCIState *xhci)
             speedmask |= port->speedmask;
         }
         if (i < xhci->numports_3) {
-            port = &xhci->ports[i + xhci->numports_2];
-            port->portnr = i + 1 + xhci->numports_2;
+            if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
+                port = &xhci->ports[i];
+                port->portnr = i + 1;
+            } else {
+                port = &xhci->ports[i + xhci->numports_2];
+                port->portnr = i + 1 + xhci->numports_2;
+            }
             port->uport = &xhci->uports[i];
             port->speedmask = USB_SPEED_MASK_SUPER;
             snprintf(port->name, sizeof(port->name), "usb3 port #%d", i+1);
@@ -3788,6 +3815,8 @@ static const VMStateDescription vmstate_xhci = {
 static Property xhci_properties[] = {
     DEFINE_PROP_BIT("msi",      XHCIState, flags, XHCI_FLAG_USE_MSI, true),
     DEFINE_PROP_BIT("msix",     XHCIState, flags, XHCI_FLAG_USE_MSI_X, true),
+    DEFINE_PROP_BIT("superspeed-ports-first",
+                    XHCIState, flags, XHCI_FLAG_SS_FIRST, true),
     DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS),
     DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS),
     DEFINE_PROP_UINT32("p2",    XHCIState, numports_2, 4),
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 8007d1d156..afbf1563f4 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -111,6 +111,7 @@ struct USBHostRequest {
     unsigned char                    *buffer;
     unsigned char                    *cbuf;
     unsigned int                     clen;
+    bool                             usb3ep0quirk;
     QTAILQ_ENTRY(USBHostRequest)     next;
 };
 
@@ -146,6 +147,10 @@ static void usb_host_attach_kernel(USBHostDevice *s);
 #define BULK_TIMEOUT         0        /* unlimited */
 #define INTR_TIMEOUT         0        /* unlimited */
 
+#if LIBUSBX_API_VERSION >= 0x01000103
+# define HAVE_STREAMS 1
+#endif
+
 static const char *speed_name[] = {
     [LIBUSB_SPEED_UNKNOWN] = "?",
     [LIBUSB_SPEED_LOW]     = "1.5",
@@ -346,6 +351,13 @@ static void usb_host_req_complete_ctrl(struct libusb_transfer *xfer)
     r->p->actual_length = xfer->actual_length;
     if (r->in && xfer->actual_length) {
         memcpy(r->cbuf, r->buffer + 8, xfer->actual_length);
+
+        /* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices
+         * to work redirected to a not superspeed capable hcd */
+        if (r->usb3ep0quirk && xfer->actual_length >= 18 &&
+            r->cbuf[7] == 9) {
+            r->cbuf[7] = 64;
+        }
     }
     trace_usb_host_req_complete(s->bus_num, s->addr, r->p,
                                 r->p->status, r->p->actual_length);
@@ -672,11 +684,17 @@ static void usb_host_iso_data_out(USBHostDevice *s, USBPacket *p)
 
 /* ------------------------------------------------------------------------ */
 
-static bool usb_host_full_speed_compat(USBHostDevice *s)
+static void usb_host_speed_compat(USBHostDevice *s)
 {
+    USBDevice *udev = USB_DEVICE(s);
     struct libusb_config_descriptor *conf;
     const struct libusb_interface_descriptor *intf;
     const struct libusb_endpoint_descriptor *endp;
+#ifdef HAVE_STREAMS
+    struct libusb_ss_endpoint_companion_descriptor *endp_ss_comp;
+#endif
+    bool compat_high = true;
+    bool compat_full = true;
     uint8_t type;
     int rc, c, i, a, e;
 
@@ -693,10 +711,27 @@ static bool usb_host_full_speed_compat(USBHostDevice *s)
                     type = endp->bmAttributes & 0x3;
                     switch (type) {
                     case 0x01: /* ISO */
-                        return false;
+                        compat_full = false;
+                        compat_high = false;
+                        break;
+                    case 0x02: /* BULK */
+#ifdef HAVE_STREAMS
+                        rc = libusb_get_ss_endpoint_companion_descriptor
+                            (ctx, endp, &endp_ss_comp);
+                        if (rc == LIBUSB_SUCCESS) {
+                            libusb_free_ss_endpoint_companion_descriptor
+                                (endp_ss_comp);
+                            compat_full = false;
+                            compat_high = false;
+                        }
+#endif
+                        break;
                     case 0x03: /* INTERRUPT */
                         if (endp->wMaxPacketSize > 64) {
-                            return false;
+                            compat_full = false;
+                        }
+                        if (endp->wMaxPacketSize > 1024) {
+                            compat_high = false;
                         }
                         break;
                     }
@@ -705,7 +740,17 @@ static bool usb_host_full_speed_compat(USBHostDevice *s)
         }
         libusb_free_config_descriptor(conf);
     }
-    return true;
+
+    udev->speedmask = (1 << udev->speed);
+    if (udev->speed == USB_SPEED_SUPER && compat_high) {
+        udev->speedmask |= USB_SPEED_HIGH;
+    }
+    if (udev->speed == USB_SPEED_SUPER && compat_full) {
+        udev->speedmask |= USB_SPEED_FULL;
+    }
+    if (udev->speed == USB_SPEED_HIGH && compat_full) {
+        udev->speedmask |= USB_SPEED_FULL;
+    }
 }
 
 static void usb_host_ep_update(USBHostDevice *s)
@@ -720,7 +765,7 @@ static void usb_host_ep_update(USBHostDevice *s)
     struct libusb_config_descriptor *conf;
     const struct libusb_interface_descriptor *intf;
     const struct libusb_endpoint_descriptor *endp;
-#if LIBUSBX_API_VERSION >= 0x01000103
+#ifdef HAVE_STREAMS
     struct libusb_ss_endpoint_companion_descriptor *endp_ss_comp;
 #endif
     uint8_t devep, type;
@@ -768,7 +813,7 @@ static void usb_host_ep_update(USBHostDevice *s)
             usb_ep_set_type(udev, pid, ep, type);
             usb_ep_set_ifnum(udev, pid, ep, i);
             usb_ep_set_halted(udev, pid, ep, 0);
-#if LIBUSBX_API_VERSION >= 0x01000103
+#ifdef HAVE_STREAMS
             if (type == LIBUSB_TRANSFER_TYPE_BULK &&
                     libusb_get_ss_endpoint_companion_descriptor(ctx, endp,
                         &endp_ss_comp) == LIBUSB_SUCCESS) {
@@ -813,10 +858,7 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev)
     usb_host_ep_update(s);
 
     udev->speed     = speed_map[libusb_get_device_speed(dev)];
-    udev->speedmask = (1 << udev->speed);
-    if (udev->speed == USB_SPEED_HIGH && usb_host_full_speed_compat(s)) {
-        udev->speedmask |= USB_SPEED_MASK_FULL;
-    }
+    usb_host_speed_compat(s);
 
     if (s->ddesc.iProduct) {
         libusb_get_string_descriptor_ascii(s->dh, s->ddesc.iProduct,
@@ -1162,6 +1204,14 @@ static void usb_host_handle_control(USBDevice *udev, USBPacket *p,
         memcpy(r->buffer + 8, r->cbuf, r->clen);
     }
 
+    /* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices
+     * to work redirected to a not superspeed capable hcd */
+    if (udev->speed == USB_SPEED_SUPER &&
+        !((udev->port->speedmask & USB_SPEED_MASK_SUPER)) &&
+        request == 0x8006 && value == 0x100 && index == 0) {
+        r->usb3ep0quirk = true;
+    }
+
     libusb_fill_control_transfer(r->xfer, s->dh, r->buffer,
                                  usb_host_req_complete_ctrl, r,
                                  CONTROL_TIMEOUT);
@@ -1215,7 +1265,7 @@ static void usb_host_handle_data(USBDevice *udev, USBPacket *p)
         }
         ep = p->ep->nr | (r->in ? USB_DIR_IN : 0);
         if (p->stream) {
-#if LIBUSBX_API_VERSION >= 0x01000103
+#ifdef HAVE_STREAMS
             libusb_fill_bulk_stream_transfer(r->xfer, s->dh, ep, p->stream,
                                              r->buffer, size,
                                              usb_host_req_complete_data, r,
@@ -1296,7 +1346,7 @@ static void usb_host_handle_reset(USBDevice *udev)
 static int usb_host_alloc_streams(USBDevice *udev, USBEndpoint **eps,
                                   int nr_eps, int streams)
 {
-#if LIBUSBX_API_VERSION >= 0x01000103
+#ifdef HAVE_STREAMS
     USBHostDevice *s = USB_HOST_DEVICE(udev);
     unsigned char endpoints[30];
     int i, rc;
@@ -1326,7 +1376,7 @@ static int usb_host_alloc_streams(USBDevice *udev, USBEndpoint **eps,
 static void usb_host_free_streams(USBDevice *udev, USBEndpoint **eps,
                                   int nr_eps)
 {
-#if LIBUSBX_API_VERSION >= 0x01000103
+#ifdef HAVE_STREAMS
     USBHostDevice *s = USB_HOST_DEVICE(udev);
     unsigned char endpoints[30];
     int i;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 32a76876c7..31328a8157 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -271,6 +271,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
             .driver   = "apic",\
             .property = "version",\
             .value    = stringify(0x11),\
+        },{\
+            .driver   = "nec-usb-xhci",\
+            .property = "superspeed-ports-first",\
+            .value    = "off",\
         }
 
 #define PC_COMPAT_1_7 \
diff --git a/include/hw/usb.h b/include/hw/usb.h
index 1919bdc09d..8bcab48d29 100644
--- a/include/hw/usb.h
+++ b/include/hw/usb.h
@@ -458,6 +458,7 @@ void usb_ep_combine_input_packets(USBEndpoint *ep);
 void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p);
 void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p);
 
+void usb_pick_speed(USBPort *port);
 void usb_attach(USBPort *port);
 void usb_detach(USBPort *port);
 void usb_port_reset(USBPort *port);
diff --git a/include/hw/usb/ehci-regs.h b/include/hw/usb/ehci-regs.h
new file mode 100644
index 0000000000..616f1b88cc
--- /dev/null
+++ b/include/hw/usb/ehci-regs.h
@@ -0,0 +1,82 @@
+#ifndef HW_USB_EHCI_REGS_H
+#define HW_USB_EHCI_REGS_H 1
+
+/* Capability Registers Base Address - section 2.2 */
+#define CAPLENGTH        0x0000  /* 1-byte, 0x0001 reserved */
+#define HCIVERSION       0x0002  /* 2-bytes, i/f version # */
+#define HCSPARAMS        0x0004  /* 4-bytes, structural params */
+#define HCCPARAMS        0x0008  /* 4-bytes, capability params */
+#define EECP             HCCPARAMS + 1
+#define HCSPPORTROUTE1   0x000c
+#define HCSPPORTROUTE2   0x0010
+
+#define USBCMD           0x0000
+#define USBCMD_RUNSTOP   (1 << 0)      // run / Stop
+#define USBCMD_HCRESET   (1 << 1)      // HC Reset
+#define USBCMD_FLS       (3 << 2)      // Frame List Size
+#define USBCMD_FLS_SH    2             // Frame List Size Shift
+#define USBCMD_PSE       (1 << 4)      // Periodic Schedule Enable
+#define USBCMD_ASE       (1 << 5)      // Asynch Schedule Enable
+#define USBCMD_IAAD      (1 << 6)      // Int Asynch Advance Doorbell
+#define USBCMD_LHCR      (1 << 7)      // Light Host Controller Reset
+#define USBCMD_ASPMC     (3 << 8)      // Async Sched Park Mode Count
+#define USBCMD_ASPME     (1 << 11)     // Async Sched Park Mode Enable
+#define USBCMD_ITC       (0x7f << 16)  // Int Threshold Control
+#define USBCMD_ITC_SH    16            // Int Threshold Control Shift
+
+#define USBSTS           0x0004
+#define USBSTS_RO_MASK   0x0000003f
+#define USBSTS_INT       (1 << 0)      // USB Interrupt
+#define USBSTS_ERRINT    (1 << 1)      // Error Interrupt
+#define USBSTS_PCD       (1 << 2)      // Port Change Detect
+#define USBSTS_FLR       (1 << 3)      // Frame List Rollover
+#define USBSTS_HSE       (1 << 4)      // Host System Error
+#define USBSTS_IAA       (1 << 5)      // Interrupt on Async Advance
+#define USBSTS_HALT      (1 << 12)     // HC Halted
+#define USBSTS_REC       (1 << 13)     // Reclamation
+#define USBSTS_PSS       (1 << 14)     // Periodic Schedule Status
+#define USBSTS_ASS       (1 << 15)     // Asynchronous Schedule Status
+
+/*
+ *  Interrupt enable bits correspond to the interrupt active bits in USBSTS
+ *  so no need to redefine here.
+ */
+#define USBINTR              0x0008
+#define USBINTR_MASK         0x0000003f
+
+#define FRINDEX              0x000c
+#define CTRLDSSEGMENT        0x0010
+#define PERIODICLISTBASE     0x0014
+#define ASYNCLISTADDR        0x0018
+#define ASYNCLISTADDR_MASK   0xffffffe0
+
+#define CONFIGFLAG           0x0040
+
+/*
+ * Bits that are reserved or are read-only are masked out of values
+ * written to us by software
+ */
+#define PORTSC_RO_MASK       0x007001c0
+#define PORTSC_RWC_MASK      0x0000002a
+#define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
+#define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
+#define PORTSC_WKCN_E        (1 << 20)    // Wake on Connect Enable
+#define PORTSC_PTC           (15 << 16)   // Port Test Control
+#define PORTSC_PTC_SH        16           // Port Test Control shift
+#define PORTSC_PIC           (3 << 14)    // Port Indicator Control
+#define PORTSC_PIC_SH        14           // Port Indicator Control Shift
+#define PORTSC_POWNER        (1 << 13)    // Port Owner
+#define PORTSC_PPOWER        (1 << 12)    // Port Power
+#define PORTSC_LINESTAT      (3 << 10)    // Port Line Status
+#define PORTSC_LINESTAT_SH   10           // Port Line Status Shift
+#define PORTSC_PRESET        (1 << 8)     // Port Reset
+#define PORTSC_SUSPEND       (1 << 7)     // Port Suspend
+#define PORTSC_FPRES         (1 << 6)     // Force Port Resume
+#define PORTSC_OCC           (1 << 5)     // Over Current Change
+#define PORTSC_OCA           (1 << 4)     // Over Current Active
+#define PORTSC_PEDC          (1 << 3)     // Port Enable/Disable Change
+#define PORTSC_PED           (1 << 2)     // Port Enable/Disable
+#define PORTSC_CSC           (1 << 1)     // Connect Status Change
+#define PORTSC_CONNECT       (1 << 0)     // Current Connect Status
+
+#endif /* HW_USB_EHCI_REGS_H */
diff --git a/include/hw/usb/uhci-regs.h b/include/hw/usb/uhci-regs.h
new file mode 100644
index 0000000000..c7315c5e1f
--- /dev/null
+++ b/include/hw/usb/uhci-regs.h
@@ -0,0 +1,40 @@
+#ifndef HW_USB_UHCI_REGS_H
+#define HW_USB_UHCI_REGS_H 1
+
+#define UHCI_CMD_FGR      (1 << 4)
+#define UHCI_CMD_EGSM     (1 << 3)
+#define UHCI_CMD_GRESET   (1 << 2)
+#define UHCI_CMD_HCRESET  (1 << 1)
+#define UHCI_CMD_RS       (1 << 0)
+
+#define UHCI_STS_HCHALTED (1 << 5)
+#define UHCI_STS_HCPERR   (1 << 4)
+#define UHCI_STS_HSERR    (1 << 3)
+#define UHCI_STS_RD       (1 << 2)
+#define UHCI_STS_USBERR   (1 << 1)
+#define UHCI_STS_USBINT   (1 << 0)
+
+#define TD_CTRL_SPD     (1 << 29)
+#define TD_CTRL_ERROR_SHIFT  27
+#define TD_CTRL_IOS     (1 << 25)
+#define TD_CTRL_IOC     (1 << 24)
+#define TD_CTRL_ACTIVE  (1 << 23)
+#define TD_CTRL_STALL   (1 << 22)
+#define TD_CTRL_BABBLE  (1 << 20)
+#define TD_CTRL_NAK     (1 << 19)
+#define TD_CTRL_TIMEOUT (1 << 18)
+
+#define UHCI_PORT_SUSPEND (1 << 12)
+#define UHCI_PORT_RESET (1 << 9)
+#define UHCI_PORT_LSDA  (1 << 8)
+#define UHCI_PORT_RSVD1 (1 << 7)
+#define UHCI_PORT_RD    (1 << 6)
+#define UHCI_PORT_ENC   (1 << 3)
+#define UHCI_PORT_EN    (1 << 2)
+#define UHCI_PORT_CSC   (1 << 1)
+#define UHCI_PORT_CCS   (1 << 0)
+
+#define UHCI_PORT_READ_ONLY    (0x1bb)
+#define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC)
+
+#endif /* HW_USB_UHCI_REGS_H */
diff --git a/include/ui/console.h b/include/ui/console.h
index b513e2082d..edbaa9b475 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -82,6 +82,8 @@ void do_mouse_set(Monitor *mon, const QDict *qdict);
 #define QEMU_KEY_CTRL_PAGEDOWN   0xe407
 
 void kbd_put_keysym_console(QemuConsole *s, int keysym);
+bool kbd_put_qcode_console(QemuConsole *s, int qcode);
+void kbd_put_string_console(QemuConsole *s, const char *str, int len);
 void kbd_put_keysym(int keysym);
 
 /* consoles */
diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin
index 3e60a3dddb..09686a3814 100644
--- a/pc-bios/bios-256k.bin
+++ b/pc-bios/bios-256k.bin
Binary files differdiff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index d360d0a232..2314027c3c 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differdiff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin
index 2ddef2ee5d..57a5f954af 100644
--- a/pc-bios/vgabios-cirrus.bin
+++ b/pc-bios/vgabios-cirrus.bin
Binary files differdiff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin
index f84a984954..ed79993ad5 100644
--- a/pc-bios/vgabios-qxl.bin
+++ b/pc-bios/vgabios-qxl.bin
Binary files differdiff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin
index 833c464d58..d3579b4fb9 100644
--- a/pc-bios/vgabios-stdvga.bin
+++ b/pc-bios/vgabios-stdvga.bin
Binary files differdiff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin
index c4bf32260b..f89845e75c 100644
--- a/pc-bios/vgabios-vmware.bin
+++ b/pc-bios/vgabios-vmware.bin
Binary files differdiff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin
index 55c6db3b8e..d3038f4184 100644
--- a/pc-bios/vgabios.bin
+++ b/pc-bios/vgabios.bin
Binary files differdiff --git a/qemu-img.c b/qemu-img.c
index 1ad899e03b..b3d2bc6f02 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -287,6 +287,7 @@ static int print_block_option_help(const char *filename, const char *fmt)
         proto_drv = bdrv_find_protocol(filename, true);
         if (!proto_drv) {
             error_report("Unknown protocol '%s'", filename);
+            free_option_parameters(create_options);
             return 1;
         }
         create_options = append_option_parameters(create_options,
@@ -662,9 +663,7 @@ static int img_check(int argc, char **argv)
     ret = collect_image_check(bs, check, filename, fmt, fix);
 
     if (ret == -ENOTSUP) {
-        if (output_format == OFORMAT_HUMAN) {
-            error_report("This image format does not support checks");
-        }
+        error_report("This image format does not support checks");
         ret = 63;
         goto fail;
     }
@@ -1454,7 +1453,7 @@ static int img_convert(int argc, char **argv)
     ret = bdrv_parse_cache_flags(cache, &flags);
     if (ret < 0) {
         error_report("Invalid cache option: %s", cache);
-        return -1;
+        goto out;
     }
 
     out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
diff --git a/qemu-io.c b/qemu-io.c
index 9fcd72bb10..795cf46c6e 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -54,6 +54,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
 
     if (qemuio_bs) {
         fprintf(stderr, "file open already, try 'help close'\n");
+        QDECREF(opts);
         return 1;
     }
 
@@ -61,7 +62,8 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
         if (bdrv_open(&qemuio_bs, name, NULL, opts, flags | BDRV_O_PROTOCOL,
                       NULL, &local_err))
         {
-            fprintf(stderr, "%s: can't open device %s: %s\n", progname, name,
+            fprintf(stderr, "%s: can't open%s%s: %s\n", progname,
+                    name ? " device " : "", name ?: "",
                     error_get_pretty(local_err));
             error_free(local_err);
             return 1;
@@ -72,7 +74,8 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
         if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err)
             < 0)
         {
-            fprintf(stderr, "%s: can't open device %s: %s\n", progname, name,
+            fprintf(stderr, "%s: can't open%s%s: %s\n", progname,
+                    name ? " device " : "", name ?: "",
                     error_get_pretty(local_err));
             error_free(local_err);
             bdrv_unref(qemuio_bs);
@@ -118,6 +121,7 @@ static const cmdinfo_t open_cmd = {
 
 static QemuOptsList empty_opts = {
     .name = "drive",
+    .merge_lists = true,
     .head = QTAILQ_HEAD_INITIALIZER(empty_opts.head),
     .desc = {
         /* no elements => accept any params */
@@ -132,7 +136,7 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
     int growable = 0;
     int c;
     QemuOpts *qopts;
-    QDict *opts = NULL;
+    QDict *opts;
 
     while ((c = getopt(argc, argv, "snrgo:")) != EOF) {
         switch (c) {
@@ -149,15 +153,14 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
             growable = 1;
             break;
         case 'o':
-            qopts = qemu_opts_parse(&empty_opts, optarg, 0);
-            if (qopts == NULL) {
+            if (!qemu_opts_parse(&empty_opts, optarg, 0)) {
                 printf("could not parse option list -- %s\n", optarg);
+                qemu_opts_reset(&empty_opts);
                 return 0;
             }
-            opts = qemu_opts_to_qdict(qopts, opts);
-            qemu_opts_del(qopts);
             break;
         default:
+            qemu_opts_reset(&empty_opts);
             return qemuio_command_usage(&open_cmd);
         }
     }
@@ -166,11 +169,16 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
         flags |= BDRV_O_RDWR;
     }
 
+    qopts = qemu_opts_find(&empty_opts, NULL);
+    opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL;
+    qemu_opts_reset(&empty_opts);
+
     if (optind == argc - 1) {
         return openfile(argv[optind], flags, growable, opts);
     } else if (optind == argc) {
         return openfile(NULL, flags, growable, opts);
     } else {
+        QDECREF(opts);
         return qemuio_command_usage(&open_cmd);
     }
 }
diff --git a/roms/seabios b/roms/seabios
-Subproject b1d4dc908401719c5de78c25313cf82c7cd1d60
+Subproject e51488c5f8800a52ac5c8da7a31b85cca5cc95d
diff --git a/tests/Makefile b/tests/Makefile
index 8f71e0d664..6b294a7dbc 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -154,6 +154,8 @@ gcov-files-i386-y += hw/pci-bridge/ioh3420.c
 check-qtest-i386-y += tests/usb-hcd-ehci-test$(EXESUF)
 gcov-files-i386-y += hw/usb/hcd-ehci.c
 gcov-files-i386-y += hw/usb/hcd-uhci.c
+gcov-files-i386-y += hw/usb/dev-hid.c
+gcov-files-i386-y += hw/usb/dev-storage.c
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
@@ -319,7 +321,7 @@ tests/ac97-test$(EXESUF): tests/ac97-test.o
 tests/es1370-test$(EXESUF): tests/es1370-test.o
 tests/intel-hda-test$(EXESUF): tests/intel-hda-test.o
 tests/ioh3420-test$(EXESUF): tests/ioh3420-test.o
-tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o
+tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-pc-obj-y)
 tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
 tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o libqemuutil.a libqemustub.a
 
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index 7e0907b514..c9a0b9134a 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -103,7 +103,7 @@ void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value)
 
 void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
 {
-    dev->bus->config_writew(dev->bus, dev->devfn, offset, value);
+    dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
 }
 
 
diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c
index bc56ba7707..bcdf62fc3b 100644
--- a/tests/usb-hcd-ehci-test.c
+++ b/tests/usb-hcd-ehci-test.c
@@ -9,12 +9,149 @@
 
 #include <glib.h>
 #include <string.h>
+#include <stdio.h>
 #include "libqtest.h"
+#include "libqos/pci-pc.h"
 #include "qemu/osdep.h"
+#include "hw/usb/uhci-regs.h"
+#include "hw/usb/ehci-regs.h"
 
-/* Tests only initialization so far. TODO: Replace with functional tests */
-static void pci_nop(void)
+struct qhc {
+    QPCIDevice *dev;
+    void *base;
+};
+
+static QPCIBus *pcibus;
+static struct qhc uhci1;
+static struct qhc uhci2;
+static struct qhc uhci3;
+static struct qhc ehci1;
+
+/* helpers */
+
+static void pci_init_one(struct qhc *hc, uint32_t devfn, int bar)
+{
+    hc->dev = qpci_device_find(pcibus, devfn);
+    g_assert(hc->dev != NULL);
+    qpci_device_enable(hc->dev);
+    hc->base = qpci_iomap(hc->dev, bar);
+    g_assert(hc->base != NULL);
+}
+
+#if 0
+static void uhci_port_update(struct qhc *hc, int port,
+                             uint16_t set, uint16_t clear)
 {
+    void *addr = hc->base + 0x10 + 2 * port;
+    uint16_t value;
+
+    value = qpci_io_readw(hc->dev, addr);
+    value |= set;
+    value &= ~clear;
+    qpci_io_writew(hc->dev, addr, value);
+}
+#endif
+
+static void uhci_port_test(struct qhc *hc, int port, uint16_t expect)
+{
+    void *addr = hc->base + 0x10 + 2 * port;
+    uint16_t value = qpci_io_readw(hc->dev, addr);
+    uint16_t mask = ~(UHCI_PORT_WRITE_CLEAR | UHCI_PORT_RSVD1);
+
+#if 0
+    fprintf(stderr, "%s: %d, have 0x%04x, want 0x%04x\n",
+            __func__, port, value & mask, expect & mask);
+#endif
+    g_assert((value & mask) == (expect & mask));
+}
+
+static void ehci_port_test(struct qhc *hc, int port, uint32_t expect)
+{
+    void *addr = hc->base + 0x64 + 4 * port;
+    uint32_t value = qpci_io_readl(hc->dev, addr);
+    uint16_t mask = ~(PORTSC_CSC | PORTSC_PEDC | PORTSC_OCC);
+
+#if 0
+    fprintf(stderr, "%s: %d, have 0x%08x, want 0x%08x\n",
+            __func__, port, value & mask, expect & mask);
+#endif
+    g_assert((value & mask) == (expect & mask));
+}
+
+/* tests */
+
+static void pci_init(void)
+{
+    if (pcibus) {
+        return;
+    }
+    pcibus = qpci_init_pc();
+    g_assert(pcibus != NULL);
+
+    pci_init_one(&uhci1, QPCI_DEVFN(0x1d, 0), 4);
+    pci_init_one(&uhci2, QPCI_DEVFN(0x1d, 1), 4);
+    pci_init_one(&uhci3, QPCI_DEVFN(0x1d, 2), 4);
+    pci_init_one(&ehci1, QPCI_DEVFN(0x1d, 7), 0);
+}
+
+static void pci_uhci_port_1(void)
+{
+    g_assert(pcibus != NULL);
+
+    uhci_port_test(&uhci1, 0, UHCI_PORT_CCS); /* usb-tablet  */
+    uhci_port_test(&uhci1, 1, UHCI_PORT_CCS); /* usb-storage */
+    uhci_port_test(&uhci2, 0, 0);
+    uhci_port_test(&uhci2, 1, 0);
+    uhci_port_test(&uhci3, 0, 0);
+    uhci_port_test(&uhci3, 1, 0);
+}
+
+static void pci_ehci_port_1(void)
+{
+    int i;
+
+    g_assert(pcibus != NULL);
+
+    for (i = 0; i < 6; i++) {
+        ehci_port_test(&ehci1, i, PORTSC_POWNER | PORTSC_PPOWER);
+    }
+}
+
+static void pci_ehci_config(void)
+{
+    /* hands over all ports from companion uhci to ehci */
+    qpci_io_writew(ehci1.dev, ehci1.base + 0x60, 1);
+}
+
+static void pci_uhci_port_2(void)
+{
+    g_assert(pcibus != NULL);
+
+    uhci_port_test(&uhci1, 0, 0); /* usb-tablet,  @ehci */
+    uhci_port_test(&uhci1, 1, 0); /* usb-storage, @ehci */
+    uhci_port_test(&uhci2, 0, 0);
+    uhci_port_test(&uhci2, 1, 0);
+    uhci_port_test(&uhci3, 0, 0);
+    uhci_port_test(&uhci3, 1, 0);
+}
+
+static void pci_ehci_port_2(void)
+{
+    static uint32_t expect[] = {
+        PORTSC_PPOWER | PORTSC_CONNECT, /* usb-tablet  */
+        PORTSC_PPOWER | PORTSC_CONNECT, /* usb-storage */
+        PORTSC_PPOWER,
+        PORTSC_PPOWER,
+        PORTSC_PPOWER,
+        PORTSC_PPOWER,
+    };
+    int i;
+
+    g_assert(pcibus != NULL);
+
+    for (i = 0; i < 6; i++) {
+        ehci_port_test(&ehci1, i, expect[i]);
+    }
 }
 
 int main(int argc, char **argv)
@@ -22,7 +159,12 @@ int main(int argc, char **argv)
     int ret;
 
     g_test_init(&argc, &argv, NULL);
-    qtest_add_func("/ehci/pci/nop", pci_nop);
+    qtest_add_func("/ehci/pci/init", pci_init);
+    qtest_add_func("/ehci/pci/uhci-port-1", pci_uhci_port_1);
+    qtest_add_func("/ehci/pci/ehci-port-1", pci_ehci_port_1);
+    qtest_add_func("/ehci/pci/ehci-config", pci_ehci_config);
+    qtest_add_func("/ehci/pci/uhci-port-2", pci_uhci_port_2);
+    qtest_add_func("/ehci/pci/ehci-port-2", pci_ehci_port_2);
 
     qtest_start("-machine q35 -device ich9-usb-ehci1,bus=pcie.0,addr=1d.7,"
                 "multifunction=on,id=ich9-ehci-1 "
@@ -31,7 +173,10 @@ int main(int argc, char **argv)
                 "-device ich9-usb-uhci2,bus=pcie.0,addr=1d.1,"
                 "multifunction=on,masterbus=ich9-ehci-1.0,firstport=2 "
                 "-device ich9-usb-uhci3,bus=pcie.0,addr=1d.2,"
-                "multifunction=on,masterbus=ich9-ehci-1.0,firstport=4");
+                "multifunction=on,masterbus=ich9-ehci-1.0,firstport=4 "
+                "-drive if=none,id=usbcdrom,media=cdrom "
+                "-device usb-tablet,bus=ich9-ehci-1.0,port=1,usb_version=1 "
+                "-device usb-storage,bus=ich9-ehci-1.0,port=2,drive=usbcdrom ");
     ret = g_test_run();
 
     qtest_end();
diff --git a/trace-events b/trace-events
index f256ca51b0..ffe6e62031 100644
--- a/trace-events
+++ b/trace-events
@@ -371,7 +371,7 @@ usb_xhci_irq_msix_use(uint32_t nr) "nr %d"
 usb_xhci_irq_msix_unuse(uint32_t nr) "nr %d"
 usb_xhci_queue_event(uint32_t vector, uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "v %d, idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
-usb_xhci_port_reset(uint32_t port) "port %d"
+usb_xhci_port_reset(uint32_t port, bool warm) "port %d, warm %d"
 usb_xhci_port_link(uint32_t port, uint32_t pls) "port %d, pls %d"
 usb_xhci_port_notify(uint32_t port, uint32_t pls) "port %d, bits %x"
 usb_xhci_slot_enable(uint32_t slotid) "slotid %d"
@@ -1047,6 +1047,14 @@ gd_update(const char *tab, int x, int y, int w, int h) "tab=%s, x=%d, y=%d, w=%d
 gd_key_event(const char *tab, int gdk_keycode, int qemu_keycode, const char *action) "tab=%s, translated GDK keycode %d to QEMU keycode %d (%s)"
 gd_grab(const char *tab, const char *device, bool on) "tab=%s, %s %d"
 
+# ui/vnc.c
+vnc_key_guest_leds(bool caps, bool num, bool scroll) "caps %d, num %d, scroll %d"
+vnc_key_map_init(const char *layout) "%s"
+vnc_key_event_ext(bool down, int sym, int keycode, const char *name) "down %d, sym 0x%x, keycode 0x%x [%s]"
+vnc_key_event_map(bool down, int sym, int keycode, const char *name) "down %d, sym 0x%x -> keycode 0x%x [%s]"
+vnc_key_sync_numlock(bool on) "%d"
+vnc_key_sync_capslock(bool on) "%d"
+
 # ui/input.c
 input_event_key_number(int conidx, int number, const char *qcode, bool down) "con %d, key number 0x%x [%s], down %d"
 input_event_key_qcode(int conidx, const char *qcode, bool down) "con %d, key qcode %s, down %d"
diff --git a/ui/console.c b/ui/console.c
index 75ec3afcf7..2ce55a69d0 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1109,6 +1109,39 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym)
     }
 }
 
+static const int qcode_to_keysym[Q_KEY_CODE_MAX] = {
+    [Q_KEY_CODE_UP]     = QEMU_KEY_UP,
+    [Q_KEY_CODE_DOWN]   = QEMU_KEY_DOWN,
+    [Q_KEY_CODE_RIGHT]  = QEMU_KEY_RIGHT,
+    [Q_KEY_CODE_LEFT]   = QEMU_KEY_LEFT,
+    [Q_KEY_CODE_HOME]   = QEMU_KEY_HOME,
+    [Q_KEY_CODE_END]    = QEMU_KEY_END,
+    [Q_KEY_CODE_PGUP]   = QEMU_KEY_PAGEUP,
+    [Q_KEY_CODE_PGDN]   = QEMU_KEY_PAGEDOWN,
+    [Q_KEY_CODE_DELETE] = QEMU_KEY_DELETE,
+};
+
+bool kbd_put_qcode_console(QemuConsole *s, int qcode)
+{
+    int keysym;
+
+    keysym = qcode_to_keysym[qcode];
+    if (keysym == 0) {
+        return false;
+    }
+    kbd_put_keysym_console(s, keysym);
+    return true;
+}
+
+void kbd_put_string_console(QemuConsole *s, const char *str, int len)
+{
+    int i;
+
+    for (i = 0; i < len && str[i]; i++) {
+        kbd_put_keysym_console(s, str[i]);
+    }
+}
+
 void kbd_put_keysym(int keysym)
 {
     kbd_put_keysym_console(active_console, keysym);
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 0e884f96fd..fcac87b4be 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -49,6 +49,7 @@ static struct sdl2_state {
     int idx;
     int last_vm_running; /* per console for caption reasons */
     int x, y;
+    int hidden;
 } *sdl2_console;
 
 static SDL_Surface *guest_sprite_surface;
@@ -136,6 +137,9 @@ static void do_sdl_resize(struct sdl2_state *scon, int width, int height,
         } else {
             flags |= SDL_WINDOW_RESIZABLE;
         }
+        if (scon->hidden) {
+            flags |= SDL_WINDOW_HIDDEN;
+        }
 
         scon->real_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED,
                                              SDL_WINDOWPOS_UNDEFINED,
@@ -210,6 +214,23 @@ static void sdl_process_key(struct sdl2_state *scon,
     int qcode = sdl2_scancode_to_qcode[ev->keysym.scancode];
     QemuConsole *con = scon ? scon->dcl.con : NULL;
 
+    if (!qemu_console_is_graphic(con)) {
+        if (ev->type == SDL_KEYDOWN) {
+            switch (ev->keysym.scancode) {
+            case SDL_SCANCODE_RETURN:
+                kbd_put_keysym_console(con, '\n');
+                break;
+            case SDL_SCANCODE_BACKSPACE:
+                kbd_put_keysym_console(con, QEMU_KEY_BACKSPACE);
+                break;
+            default:
+                kbd_put_qcode_console(con, qcode);
+                break;
+            }
+        }
+        return;
+    }
+
     switch (ev->keysym.scancode) {
 #if 0
     case SDL_SCANCODE_NUMLOCKCLEAR:
@@ -305,6 +326,11 @@ static void sdl_show_cursor(void)
 
 static void sdl_grab_start(struct sdl2_state *scon)
 {
+    QemuConsole *con = scon ? scon->dcl.con : NULL;
+
+    if (!con || !qemu_console_is_graphic(con)) {
+        return;
+    }
     /*
      * If the application is not active, do not try to enter grab state. This
      * prevents 'SDL_WM_GrabInput(SDL_GRAB_ON)' from blocking all the
@@ -458,7 +484,7 @@ static void toggle_full_screen(struct sdl2_state *scon)
 
 static void handle_keydown(SDL_Event *ev)
 {
-    int mod_state;
+    int mod_state, win;
     struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
 
     if (alt_grab) {
@@ -473,6 +499,27 @@ static void handle_keydown(SDL_Event *ev)
 
     if (gui_key_modifier_pressed) {
         switch (ev->key.keysym.scancode) {
+        case SDL_SCANCODE_2:
+        case SDL_SCANCODE_3:
+        case SDL_SCANCODE_4:
+        case SDL_SCANCODE_5:
+        case SDL_SCANCODE_6:
+        case SDL_SCANCODE_7:
+        case SDL_SCANCODE_8:
+        case SDL_SCANCODE_9:
+            win = ev->key.keysym.scancode - SDL_SCANCODE_1;
+            if (win < sdl2_num_outputs) {
+                sdl2_console[win].hidden = !sdl2_console[win].hidden;
+                if (sdl2_console[win].real_window) {
+                    if (sdl2_console[win].hidden) {
+                        SDL_HideWindow(sdl2_console[win].real_window);
+                    } else {
+                        SDL_ShowWindow(sdl2_console[win].real_window);
+                    }
+                }
+                gui_keysym = 1;
+            }
+            break;
         case SDL_SCANCODE_F:
             toggle_full_screen(scon);
             gui_keysym = 1;
@@ -544,6 +591,17 @@ static void handle_keyup(SDL_Event *ev)
     }
 }
 
+static void handle_textinput(SDL_Event *ev)
+{
+    struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+    QemuConsole *con = scon ? scon->dcl.con : NULL;
+
+    if (qemu_console_is_graphic(con)) {
+        return;
+    }
+    kbd_put_string_console(con, ev->text.text, strlen(ev->text.text));
+}
+
 static void handle_mousemotion(SDL_Event *ev)
 {
     int max_x, max_y;
@@ -680,6 +738,9 @@ static void sdl_refresh(DisplayChangeListener *dcl)
         case SDL_KEYUP:
             handle_keyup(ev);
             break;
+        case SDL_TEXTINPUT:
+            handle_textinput(ev);
+            break;
         case SDL_QUIT:
             if (!no_quit) {
                 no_shutdown = 0;
@@ -808,7 +869,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
 
     for (i = 0;; i++) {
         QemuConsole *con = qemu_console_lookup_by_index(i);
-        if (!con || !qemu_console_is_graphic(con)) {
+        if (!con) {
             break;
         }
     }
@@ -816,6 +877,9 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
     sdl2_console = g_new0(struct sdl2_state, sdl2_num_outputs);
     for (i = 0; i < sdl2_num_outputs; i++) {
         QemuConsole *con = qemu_console_lookup_by_index(i);
+        if (!qemu_console_is_graphic(con)) {
+            sdl2_console[i].hidden = true;
+        }
         sdl2_console[i].dcl.ops = &dcl_ops;
         sdl2_console[i].dcl.con = con;
         register_displaychangelistener(&sdl2_console[i].dcl);
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 59b59c0c79..f02352cc46 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -181,6 +181,10 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
         }
     }
 
+    if (pixels == 0) {
+        return 0;
+    }
+
     /* 95% smooth or more ... */
     if (stats[0] * 33 / pixels >= 95) {
         return 0;
@@ -267,7 +271,9 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
                 y += w;                                                 \
             }                                                           \
         }                                                               \
-                                                                        \
+        if (pixels == 0) {                                              \
+            return 0;                                                   \
+        }                                                               \
         if ((stats[0] + stats[1]) * 100 / pixels >= 90) {               \
             return 0;                                                   \
         }                                                               \
diff --git a/ui/vnc.c b/ui/vnc.c
index 2d7def9aa2..61b1f933bf 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -26,6 +26,7 @@
 
 #include "vnc.h"
 #include "vnc-jobs.h"
+#include "trace.h"
 #include "sysemu/sysemu.h"
 #include "qemu/sockets.h"
 #include "qemu/timer.h"
@@ -1597,6 +1598,10 @@ static void kbd_leds(void *opaque, int ledstate)
     int caps, num, scr;
     bool has_changed = (ledstate != current_led_state(vs));
 
+    trace_vnc_key_guest_leds((ledstate & QEMU_CAPS_LOCK_LED),
+                             (ledstate & QEMU_NUM_LOCK_LED),
+                             (ledstate & QEMU_SCROLL_LOCK_LED));
+
     caps = ledstate & QEMU_CAPS_LOCK_LED ? 1 : 0;
     num  = ledstate & QEMU_NUM_LOCK_LED  ? 1 : 0;
     scr  = ledstate & QEMU_SCROLL_LOCK_LED ? 1 : 0;
@@ -1659,11 +1664,13 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
         */
         if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
             if (!vs->modifiers_state[0x45]) {
+                trace_vnc_key_sync_numlock(true);
                 vs->modifiers_state[0x45] = 1;
                 press_key(vs, 0xff7f);
             }
         } else {
             if (vs->modifiers_state[0x45]) {
+                trace_vnc_key_sync_numlock(false);
                 vs->modifiers_state[0x45] = 0;
                 press_key(vs, 0xff7f);
             }
@@ -1682,11 +1689,13 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
         int capslock = !!(vs->modifiers_state[0x3a]);
         if (capslock) {
             if (uppercase == shift) {
+                trace_vnc_key_sync_capslock(false);
                 vs->modifiers_state[0x3a] = 0;
                 press_key(vs, 0xffe5);
             }
         } else {
             if (uppercase != shift) {
+                trace_vnc_key_sync_capslock(true);
                 vs->modifiers_state[0x3a] = 1;
                 press_key(vs, 0xffe5);
             }
@@ -1819,6 +1828,11 @@ static void vnc_release_modifiers(VncState *vs)
     }
 }
 
+static const char *code2name(int keycode)
+{
+    return QKeyCode_lookup[qemu_input_key_number_to_qcode(keycode)];
+}
+
 static void key_event(VncState *vs, int down, uint32_t sym)
 {
     int keycode;
@@ -1829,6 +1843,7 @@ static void key_event(VncState *vs, int down, uint32_t sym)
     }
 
     keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & SCANCODE_KEYMASK;
+    trace_vnc_key_event_map(down, sym, keycode, code2name(keycode));
     do_key_event(vs, down, keycode, sym);
 }
 
@@ -1836,10 +1851,12 @@ static void ext_key_event(VncState *vs, int down,
                           uint32_t sym, uint16_t keycode)
 {
     /* if the user specifies a keyboard layout, always use it */
-    if (keyboard_layout)
+    if (keyboard_layout) {
         key_event(vs, down, sym);
-    else
+    } else {
+        trace_vnc_key_event_ext(down, sym, keycode, code2name(keycode));
         do_key_event(vs, down, keycode, sym);
+    }
 }
 
 static void framebuffer_update_request(VncState *vs, int incremental,
@@ -2929,10 +2946,12 @@ void vnc_display_init(DisplayState *ds)
     QTAILQ_INIT(&vs->clients);
     vs->expires = TIME_MAX;
 
-    if (keyboard_layout)
+    if (keyboard_layout) {
+        trace_vnc_key_map_init(keyboard_layout);
         vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
-    else
+    } else {
         vs->kbd_layout = init_keyboard_layout(name2keysym, "en-us");
+    }
 
     if (!vs->kbd_layout)
         exit(1);
@@ -2976,26 +2995,6 @@ static void vnc_display_close(DisplayState *ds)
 #endif
 }
 
-static int vnc_display_disable_login(DisplayState *ds)
-{
-    VncDisplay *vs = vnc_display;
-
-    if (!vs) {
-        return -1;
-    }
-
-    if (vs->password) {
-        g_free(vs->password);
-    }
-
-    vs->password = NULL;
-    if (vs->auth == VNC_AUTH_NONE) {
-        vs->auth = VNC_AUTH_VNC;
-    }
-
-    return 0;
-}
-
 int vnc_display_password(DisplayState *ds, const char *password)
 {
     VncDisplay *vs = vnc_display;
@@ -3003,20 +3002,18 @@ int vnc_display_password(DisplayState *ds, const char *password)
     if (!vs) {
         return -EINVAL;
     }
-
-    if (!password) {
-        /* This is not the intention of this interface but err on the side
-           of being safe */
-        return vnc_display_disable_login(ds);
+    if (vs->auth == VNC_AUTH_NONE) {
+        error_printf_unless_qmp("If you want use passwords please enable "
+                                "password auth using '-vnc ${dpy},password'.");
+        return -EINVAL;
     }
 
     if (vs->password) {
         g_free(vs->password);
         vs->password = NULL;
     }
-    vs->password = g_strdup(password);
-    if (vs->auth == VNC_AUTH_NONE) {
-        vs->auth = VNC_AUTH_VNC;
+    if (password) {
+        vs->password = g_strdup(password);
     }
 
     return 0;