Merge remote-tracking branch 'qmp/queue/qmp' into staging

* qmp/queue/qmp:
  migration: move total_time from ram stats to migration info
  monitor: avoid declaring unused variables
  qapi: Fix memory leak
diff --git a/arch_init.c b/arch_init.c
index 9b46bfc..5a1173e 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -44,6 +44,7 @@
 #include "exec-memory.h"
 #include "hw/pcspk.h"
 #include "qemu/page_cache.h"
+#include "qmp-commands.h"
 
 #ifdef DEBUG_ARCH_INIT
 #define DPRINTF(fmt, ...) \
@@ -1080,3 +1081,13 @@
     return 0;
 #endif
 }
+
+
+TargetInfo *qmp_query_target(Error **errp)
+{
+    TargetInfo *info = g_malloc0(sizeof(*info));
+
+    info->arch = TARGET_TYPE;
+
+    return info;
+}
diff --git a/block/iscsi.c b/block/iscsi.c
index bb9cf82..4828b83 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -73,13 +73,43 @@
 };
 
 static void
+iscsi_bh_cb(void *p)
+{
+    IscsiAIOCB *acb = p;
+
+    qemu_bh_delete(acb->bh);
+
+    if (acb->canceled == 0) {
+        acb->common.cb(acb->common.opaque, acb->status);
+    }
+
+    if (acb->task != NULL) {
+        scsi_free_scsi_task(acb->task);
+        acb->task = NULL;
+    }
+
+    qemu_aio_release(acb);
+}
+
+static void
+iscsi_schedule_bh(IscsiAIOCB *acb)
+{
+    if (acb->bh) {
+        return;
+    }
+    acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
+    qemu_bh_schedule(acb->bh);
+}
+
+
+static void
 iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
                     void *private_data)
 {
-    IscsiAIOCB *acb = (IscsiAIOCB *)private_data;
+    IscsiAIOCB *acb = private_data;
 
-    scsi_free_scsi_task(acb->task);
-    acb->task = NULL;
+    acb->status = -ECANCELED;
+    iscsi_schedule_bh(acb);
 }
 
 static void
@@ -88,15 +118,19 @@
     IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
     IscsiLun *iscsilun = acb->iscsilun;
 
+    if (acb->status != -EINPROGRESS) {
+        return;
+    }
+
     acb->canceled = 1;
 
-    acb->common.cb(acb->common.opaque, -ECANCELED);
-
-    /* send a task mgmt call to the target to cancel the task on the target
-     * this also cancels the task in libiscsi
-     */
+    /* send a task mgmt call to the target to cancel the task on the target */
     iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
-                                     iscsi_abort_task_cb, &acb);
+                                     iscsi_abort_task_cb, acb);
+
+    while (acb->status == -EINPROGRESS) {
+        qemu_aio_wait();
+    }
 }
 
 static AIOPool iscsi_aio_pool = {
@@ -163,41 +197,6 @@
 }
 
 
-static int
-iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb)
-{
-    acb->bh = qemu_bh_new(cb, acb);
-    if (!acb->bh) {
-        error_report("oom: could not create iscsi bh");
-        return -EIO;
-    }
-
-    qemu_bh_schedule(acb->bh);
-    return 0;
-}
-
-static void
-iscsi_readv_writev_bh_cb(void *p)
-{
-    IscsiAIOCB *acb = p;
-
-    qemu_bh_delete(acb->bh);
-
-    if (!acb->canceled) {
-        acb->common.cb(acb->common.opaque, acb->status);
-    }
-
-    qemu_aio_release(acb);
-
-    if (acb->canceled) {
-        return;
-    }
-
-    scsi_free_scsi_task(acb->task);
-    acb->task = NULL;
-}
-
-
 static void
 iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
                      void *command_data, void *opaque)
@@ -208,8 +207,7 @@
 
     g_free(acb->buf);
 
-    if (acb->canceled) {
-        qemu_aio_release(acb);
+    if (acb->canceled != 0) {
         return;
     }
 
@@ -220,7 +218,7 @@
         acb->status = -EIO;
     }
 
-    iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    iscsi_schedule_bh(acb);
 }
 
 static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
@@ -249,6 +247,8 @@
     acb->qiov     = qiov;
 
     acb->canceled   = 0;
+    acb->bh         = NULL;
+    acb->status     = -EINPROGRESS;
 
     /* XXX we should pass the iovec to write16 to avoid the extra copy */
     /* this will allow us to get rid of 'buf' completely */
@@ -305,8 +305,7 @@
 
     trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
 
-    if (acb->canceled) {
-        qemu_aio_release(acb);
+    if (acb->canceled != 0) {
         return;
     }
 
@@ -317,7 +316,7 @@
         acb->status = -EIO;
     }
 
-    iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    iscsi_schedule_bh(acb);
 }
 
 static BlockDriverAIOCB *
@@ -343,6 +342,8 @@
     acb->qiov     = qiov;
 
     acb->canceled    = 0;
+    acb->bh          = NULL;
+    acb->status      = -EINPROGRESS;
     acb->read_size   = qemu_read_size;
     acb->buf         = NULL;
 
@@ -417,8 +418,7 @@
 {
     IscsiAIOCB *acb = opaque;
 
-    if (acb->canceled) {
-        qemu_aio_release(acb);
+    if (acb->canceled != 0) {
         return;
     }
 
@@ -429,7 +429,7 @@
         acb->status = -EIO;
     }
 
-    iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    iscsi_schedule_bh(acb);
 }
 
 static BlockDriverAIOCB *
@@ -444,6 +444,8 @@
 
     acb->iscsilun = iscsilun;
     acb->canceled   = 0;
+    acb->bh         = NULL;
+    acb->status     = -EINPROGRESS;
 
     acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun,
                                          0, 0, 0, 0,
@@ -467,8 +469,7 @@
 {
     IscsiAIOCB *acb = opaque;
 
-    if (acb->canceled) {
-        qemu_aio_release(acb);
+    if (acb->canceled != 0) {
         return;
     }
 
@@ -479,7 +480,7 @@
         acb->status = -EIO;
     }
 
-    iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    iscsi_schedule_bh(acb);
 }
 
 static BlockDriverAIOCB *
@@ -496,6 +497,8 @@
 
     acb->iscsilun = iscsilun;
     acb->canceled   = 0;
+    acb->bh         = NULL;
+    acb->status     = -EINPROGRESS;
 
     list[0].lba = sector_qemu2lun(sector_num, iscsilun);
     list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;
@@ -523,8 +526,7 @@
 {
     IscsiAIOCB *acb = opaque;
 
-    if (acb->canceled) {
-        qemu_aio_release(acb);
+    if (acb->canceled != 0) {
         return;
     }
 
@@ -552,7 +554,7 @@
         memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss);
     }
 
-    iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    iscsi_schedule_bh(acb);
 }
 
 static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
@@ -570,6 +572,8 @@
 
     acb->iscsilun = iscsilun;
     acb->canceled    = 0;
+    acb->bh          = NULL;
+    acb->status      = -EINPROGRESS;
     acb->buf         = NULL;
     acb->ioh         = buf;
 
diff --git a/block/sheepdog.c b/block/sheepdog.c
index a04ad99..df4f441 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -485,6 +485,7 @@
             if (errno == EINTR) {
                 goto reconnect;
             }
+            close(fd);
             break;
         }
 
diff --git a/block/vmdk.c b/block/vmdk.c
index daee426..bba4c61 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -35,6 +35,7 @@
 #define VMDK4_FLAG_RGD (1 << 1)
 #define VMDK4_FLAG_COMPRESS (1 << 16)
 #define VMDK4_FLAG_MARKER (1 << 17)
+#define VMDK4_GD_AT_END 0xffffffffffffffffULL
 
 typedef struct {
     uint32_t version;
@@ -57,8 +58,8 @@
     int64_t desc_offset;
     int64_t desc_size;
     int32_t num_gtes_per_gte;
-    int64_t gd_offset;
     int64_t rgd_offset;
+    int64_t gd_offset;
     int64_t grain_offset;
     char filler[1];
     char check_bytes[4];
@@ -115,6 +116,13 @@
     uint8_t  data[0];
 } VmdkGrainMarker;
 
+enum {
+    MARKER_END_OF_STREAM    = 0,
+    MARKER_GRAIN_TABLE      = 1,
+    MARKER_GRAIN_DIRECTORY  = 2,
+    MARKER_FOOTER           = 3,
+};
+
 static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
     uint32_t magic;
@@ -451,6 +459,54 @@
     if (header.capacity == 0 && header.desc_offset) {
         return vmdk_open_desc_file(bs, flags, header.desc_offset << 9);
     }
+
+    if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) {
+        /*
+         * The footer takes precedence over the header, so read it in. The
+         * footer starts at offset -1024 from the end: One sector for the
+         * footer, and another one for the end-of-stream marker.
+         */
+        struct {
+            struct {
+                uint64_t val;
+                uint32_t size;
+                uint32_t type;
+                uint8_t pad[512 - 16];
+            } QEMU_PACKED footer_marker;
+
+            uint32_t magic;
+            VMDK4Header header;
+            uint8_t pad[512 - 4 - sizeof(VMDK4Header)];
+
+            struct {
+                uint64_t val;
+                uint32_t size;
+                uint32_t type;
+                uint8_t pad[512 - 16];
+            } QEMU_PACKED eos_marker;
+        } QEMU_PACKED footer;
+
+        ret = bdrv_pread(file,
+            bs->file->total_sectors * 512 - 1536,
+            &footer, sizeof(footer));
+        if (ret < 0) {
+            return ret;
+        }
+
+        /* Some sanity checks for the footer */
+        if (be32_to_cpu(footer.magic) != VMDK4_MAGIC ||
+            le32_to_cpu(footer.footer_marker.size) != 0  ||
+            le32_to_cpu(footer.footer_marker.type) != MARKER_FOOTER ||
+            le64_to_cpu(footer.eos_marker.val) != 0  ||
+            le32_to_cpu(footer.eos_marker.size) != 0  ||
+            le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM)
+        {
+            return -EINVAL;
+        }
+
+        header = footer.header;
+    }
+
     l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
                         * le64_to_cpu(header.granularity);
     if (l1_entry_sectors == 0) {
diff --git a/configure b/configure
index 60d266f..d97fd81 100755
--- a/configure
+++ b/configure
@@ -3834,14 +3834,19 @@
   ;;
 esac
 
+upper() {
+    echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
+}
+
 echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
 echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
 echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
 echo "TARGET_LLONG_ALIGNMENT=$target_llong_alignment" >> $config_target_mak
 echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak
-target_arch_name="`echo $TARGET_ARCH | LC_ALL=C tr '[a-z]' '[A-Z]'`"
+target_arch_name="`upper $TARGET_ARCH`"
 echo "TARGET_$target_arch_name=y" >> $config_target_mak
 echo "TARGET_ARCH2=$target_arch2" >> $config_target_mak
+echo "TARGET_TYPE=TARGET_TYPE_`upper $target_arch2`" >> $config_target_mak
 echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak
 if [ "$TARGET_ABI_DIR" = "" ]; then
   TARGET_ABI_DIR=$TARGET_ARCH
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 872e112..b7cf4e2 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -15,6 +15,8 @@
 #include "exec-memory.h"
 
 
+#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
+
 typedef struct TyphoonCchip {
     MemoryRegion region;
     uint64_t misc;
@@ -40,8 +42,12 @@
     TyphoonWindow win[4];
 } TyphoonPchip;
 
+#define TYPHOON_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE)
+
 typedef struct TyphoonState {
-    PCIHostState host;
+    PCIHostState parent_obj;
+
     TyphoonCchip cchip;
     TyphoonPchip pchip;
     MemoryRegion dchip_region;
@@ -700,16 +706,16 @@
     MemoryRegion *addr_space = get_system_memory();
     MemoryRegion *addr_space_io = get_system_io();
     DeviceState *dev;
-    PCIHostState *p;
     TyphoonState *s;
+    PCIHostState *phb;
     PCIBus *b;
     int i;
 
-    dev = qdev_create(NULL, "typhoon-pcihost");
+    dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE);
     qdev_init_nofail(dev);
 
-    p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
-    s = container_of(p, TyphoonState, host);
+    s = TYPHOON_PCI_HOST_BRIDGE(dev);
+    phb = PCI_HOST_BRIDGE(dev);
 
     /* Remember the CPUs so that we can deliver interrupts to them.  */
     for (i = 0; i < 4; i++) {
@@ -763,10 +769,10 @@
     memory_region_add_subregion(addr_space, 0x801fc000000ULL,
                                 &s->pchip.reg_io);
 
-    b = pci_register_bus(&s->host.busdev.qdev, "pci",
+    b = pci_register_bus(dev, "pci",
                          typhoon_set_irq, sys_map_irq, s,
                          &s->pchip.reg_mem, addr_space_io, 0, 64);
-    s->host.bus = b;
+    phb->bus = b;
 
     /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
     memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b,
@@ -817,9 +823,9 @@
     dc->no_user = 1;
 }
 
-static TypeInfo typhoon_pcihost_info = {
-    .name          = "typhoon-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo typhoon_pcihost_info = {
+    .name          = TYPE_TYPHOON_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(TyphoonState),
     .class_init    = typhoon_pcihost_class_init,
 };
diff --git a/hw/bonito.c b/hw/bonito.c
index 77786f8..6084ac4 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -180,11 +180,14 @@
 #define PCI_ADDR(busno,devno,funno,regno)  \
     ((((busno)<<16)&0xff0000) + (((devno)<<11)&0xf800) + (((funno)<<8)&0x700) + (regno))
 
-typedef PCIHostState BonitoState;
+#define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost"
+
+typedef struct BonitoState BonitoState;
 
 typedef struct PCIBonitoState
 {
     PCIDevice dev;
+
     BonitoState *pcihost;
     uint32_t regs[BONITO_REGS];
 
@@ -218,7 +221,16 @@
 
 } PCIBonitoState;
 
-PCIBonitoState * bonito_state;
+#define BONITO_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(BonitoState, (obj), TYPE_BONITO_PCI_HOST_BRIDGE)
+
+struct BonitoState {
+    PCIHostState parent_obj;
+
+    qemu_irq *pic;
+
+    PCIBonitoState *pci_dev;
+};
 
 static void bonito_writel(void *opaque, target_phys_addr_t addr,
                           uint64_t val, unsigned size)
@@ -314,9 +326,10 @@
                                   uint64_t val, unsigned size)
 {
     PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
 
     DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
-    s->dev.config_write(&s->dev, addr, val, 4);
+    d->config_write(d, addr, val, 4);
 }
 
 static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr,
@@ -324,9 +337,10 @@
 {
 
     PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
 
     DPRINTF("bonito_pciconf_readl "TARGET_FMT_plx"\n", addr);
-    return s->dev.config_read(&s->dev, addr, 4);
+    return d->config_read(d, addr, 4);
 }
 
 /* north bridge PCI configure space. 0x1fe0 0000 - 0x1fe0 00ff */
@@ -402,6 +416,7 @@
 static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr)
 {
     PCIBonitoState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
     uint32_t cfgaddr;
     uint32_t idsel;
     uint32_t devno;
@@ -423,13 +438,13 @@
     regno = (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OFFSET;
 
     if (idsel == 0) {
-        fprintf(stderr, "error in bonito pci config address" TARGET_FMT_plx
+        fprintf(stderr, "error in bonito pci config address " TARGET_FMT_plx
             ",pcimap_cfg=%x\n", addr, s->regs[BONITO_PCIMAP_CFG]);
         exit(1);
     }
-    pciaddr = PCI_ADDR(pci_bus_num(s->pcihost->bus), devno, funno, regno);
+    pciaddr = PCI_ADDR(pci_bus_num(phb->bus), devno, funno, regno);
     DPRINTF("cfgaddr %x pciaddr %x busno %x devno %d funno %d regno %d\n",
-        cfgaddr, pciaddr, pci_bus_num(s->pcihost->bus), devno, funno, regno);
+        cfgaddr, pciaddr, pci_bus_num(phb->bus), devno, funno, regno);
 
     return pciaddr;
 }
@@ -438,6 +453,8 @@
                                    uint32_t val)
 {
     PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
     uint32_t pciaddr;
     uint16_t status;
 
@@ -449,24 +466,26 @@
     }
 
     /* set the pci address in s->config_reg */
-    s->pcihost->config_reg = (pciaddr) | (1u << 31);
-    pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val & 0xff, 1);
+    phb->config_reg = (pciaddr) | (1u << 31);
+    pci_data_write(phb->bus, phb->config_reg, val & 0xff, 1);
 
     /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(s->dev.config + PCI_STATUS);
+    status = pci_get_word(d->config + PCI_STATUS);
     status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(s->dev.config + PCI_STATUS, status);
+    pci_set_word(d->config + PCI_STATUS, status);
 }
 
 static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr,
                                    uint32_t val)
 {
     PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
     uint32_t pciaddr;
     uint16_t status;
 
     DPRINTF("bonito_spciconf_writew "TARGET_FMT_plx" val %x\n", addr, val);
-    assert((addr&0x1)==0);
+    assert((addr & 0x1) == 0);
 
     pciaddr = bonito_sbridge_pciaddr(s, addr);
 
@@ -475,24 +494,26 @@
     }
 
     /* set the pci address in s->config_reg */
-    s->pcihost->config_reg = (pciaddr) | (1u << 31);
-    pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val, 2);
+    phb->config_reg = (pciaddr) | (1u << 31);
+    pci_data_write(phb->bus, phb->config_reg, val, 2);
 
     /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(s->dev.config + PCI_STATUS);
+    status = pci_get_word(d->config + PCI_STATUS);
     status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(s->dev.config + PCI_STATUS, status);
+    pci_set_word(d->config + PCI_STATUS, status);
 }
 
 static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr,
                                    uint32_t val)
 {
     PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
     uint32_t pciaddr;
     uint16_t status;
 
     DPRINTF("bonito_spciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
-    assert((addr&0x3)==0);
+    assert((addr & 0x3) == 0);
 
     pciaddr = bonito_sbridge_pciaddr(s, addr);
 
@@ -501,18 +522,20 @@
     }
 
     /* set the pci address in s->config_reg */
-    s->pcihost->config_reg = (pciaddr) | (1u << 31);
-    pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val, 4);
+    phb->config_reg = (pciaddr) | (1u << 31);
+    pci_data_write(phb->bus, phb->config_reg, val, 4);
 
     /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(s->dev.config + PCI_STATUS);
+    status = pci_get_word(d->config + PCI_STATUS);
     status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(s->dev.config + PCI_STATUS, status);
+    pci_set_word(d->config + PCI_STATUS, status);
 }
 
 static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr)
 {
     PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
     uint32_t pciaddr;
     uint16_t status;
 
@@ -524,24 +547,26 @@
     }
 
     /* set the pci address in s->config_reg */
-    s->pcihost->config_reg = (pciaddr) | (1u << 31);
+    phb->config_reg = (pciaddr) | (1u << 31);
 
     /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(s->dev.config + PCI_STATUS);
+    status = pci_get_word(d->config + PCI_STATUS);
     status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(s->dev.config + PCI_STATUS, status);
+    pci_set_word(d->config + PCI_STATUS, status);
 
-    return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 1);
+    return pci_data_read(phb->bus, phb->config_reg, 1);
 }
 
 static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr)
 {
     PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
     uint32_t pciaddr;
     uint16_t status;
 
     DPRINTF("bonito_spciconf_readw "TARGET_FMT_plx"\n", addr);
-    assert((addr&0x1)==0);
+    assert((addr & 0x1) == 0);
 
     pciaddr = bonito_sbridge_pciaddr(s, addr);
 
@@ -550,24 +575,26 @@
     }
 
     /* set the pci address in s->config_reg */
-    s->pcihost->config_reg = (pciaddr) | (1u << 31);
+    phb->config_reg = (pciaddr) | (1u << 31);
 
     /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(s->dev.config + PCI_STATUS);
+    status = pci_get_word(d->config + PCI_STATUS);
     status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(s->dev.config + PCI_STATUS, status);
+    pci_set_word(d->config + PCI_STATUS, status);
 
-    return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 2);
+    return pci_data_read(phb->bus, phb->config_reg, 2);
 }
 
 static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr)
 {
     PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
     uint32_t pciaddr;
     uint16_t status;
 
     DPRINTF("bonito_spciconf_readl "TARGET_FMT_plx"\n", addr);
-    assert((addr&0x3) == 0);
+    assert((addr & 0x3) == 0);
 
     pciaddr = bonito_sbridge_pciaddr(s, addr);
 
@@ -576,14 +603,14 @@
     }
 
     /* set the pci address in s->config_reg */
-    s->pcihost->config_reg = (pciaddr) | (1u << 31);
+    phb->config_reg = (pciaddr) | (1u << 31);
 
     /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(s->dev.config + PCI_STATUS);
+    status = pci_get_word(d->config + PCI_STATUS);
     status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(s->dev.config + PCI_STATUS, status);
+    pci_set_word(d->config + PCI_STATUS, status);
 
-    return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 4);
+    return pci_data_read(phb->bus, phb->config_reg, 4);
 }
 
 /* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */
@@ -607,13 +634,15 @@
 
 static void pci_bonito_set_irq(void *opaque, int irq_num, int level)
 {
-    qemu_irq *pic = opaque;
+    BonitoState *s = opaque;
+    qemu_irq *pic = s->pic;
+    PCIBonitoState *bonito_state = s->pci_dev;
     int internal_irq = irq_num - BONITO_IRQ_BASE;
 
-    if (bonito_state->regs[BONITO_INTEDGE] & (1<<internal_irq)) {
+    if (bonito_state->regs[BONITO_INTEDGE] & (1 << internal_irq)) {
         qemu_irq_pulse(*pic);
     } else {   /* level triggered */
-        if (bonito_state->regs[BONITO_INTPOL] & (1<<internal_irq)) {
+        if (bonito_state->regs[BONITO_INTPOL] & (1 << internal_irq)) {
             qemu_irq_raise(*pic);
         } else {
             qemu_irq_lower(*pic);
@@ -673,13 +702,21 @@
 
 static int bonito_pcihost_initfn(SysBusDevice *dev)
 {
+    PCIHostState *phb = PCI_HOST_BRIDGE(dev);
+
+    phb->bus = pci_register_bus(DEVICE(dev), "pci",
+                                pci_bonito_set_irq, pci_bonito_map_irq, dev,
+                                get_system_memory(), get_system_io(),
+                                0x28, 32);
+
     return 0;
 }
 
 static int bonito_initfn(PCIDevice *dev)
 {
     PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev);
-    SysBusDevice *sysbus = &s->pcihost->busdev;
+    SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
 
     /* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */
     pci_config_set_prog_interface(dev->config, 0x00);
@@ -691,15 +728,15 @@
     sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE);
 
     /* set the north bridge pci configure  mapping */
-    memory_region_init_io(&s->pcihost->conf_mem, &bonito_pciconf_ops, s,
+    memory_region_init_io(&phb->conf_mem, &bonito_pciconf_ops, s,
                           "north-bridge-pci-config", BONITO_PCICONFIG_SIZE);
-    sysbus_init_mmio(sysbus, &s->pcihost->conf_mem);
+    sysbus_init_mmio(sysbus, &phb->conf_mem);
     sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE);
 
     /* set the south bridge pci configure  mapping */
-    memory_region_init_io(&s->pcihost->data_mem, &bonito_spciconf_ops, s,
+    memory_region_init_io(&phb->data_mem, &bonito_spciconf_ops, s,
                           "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE);
-    sysbus_init_mmio(sysbus, &s->pcihost->data_mem);
+    sysbus_init_mmio(sysbus, &phb->data_mem);
     sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
 
     memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s,
@@ -742,28 +779,25 @@
 PCIBus *bonito_init(qemu_irq *pic)
 {
     DeviceState *dev;
-    PCIBus *b;
     BonitoState *pcihost;
+    PCIHostState *phb;
     PCIBonitoState *s;
     PCIDevice *d;
 
-    dev = qdev_create(NULL, "Bonito-pcihost");
-    pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev));
-    b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq,
-                         pci_bonito_map_irq, pic, get_system_memory(),
-                         get_system_io(),
-                         0x28, 32);
-    pcihost->bus = b;
+    dev = qdev_create(NULL, TYPE_BONITO_PCI_HOST_BRIDGE);
+    phb = PCI_HOST_BRIDGE(dev);
+    pcihost = BONITO_PCI_HOST_BRIDGE(dev);
+    pcihost->pic = pic;
     qdev_init_nofail(dev);
 
     /* set the pcihost pointer before bonito_initfn is called */
-    d = pci_create(b, PCI_DEVFN(0, 0), "Bonito");
+    d = pci_create(phb->bus, PCI_DEVFN(0, 0), "Bonito");
     s = DO_UPCAST(PCIBonitoState, dev, d);
     s->pcihost = pcihost;
-    bonito_state = s;
-    qdev_init_nofail(&d->qdev);
+    pcihost->pci_dev = s;
+    qdev_init_nofail(DEVICE(d));
 
-    return b;
+    return phb->bus;
 }
 
 static void bonito_class_init(ObjectClass *klass, void *data)
@@ -781,7 +815,7 @@
     dc->vmsd = &vmstate_bonito;
 }
 
-static TypeInfo bonito_info = {
+static const TypeInfo bonito_info = {
     .name          = "Bonito",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIBonitoState),
@@ -797,9 +831,9 @@
     dc->no_user = 1;
 }
 
-static TypeInfo bonito_pcihost_info = {
-    .name          = "Bonito-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo bonito_pcihost_info = {
+    .name          = TYPE_BONITO_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(BonitoState),
     .class_init    = bonito_pcihost_class_init,
 };
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index 37337bf..c30ade3 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -40,9 +40,10 @@
 #define DEC_DPRINTF(fmt, ...)
 #endif
 
+#define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154)
+
 typedef struct DECState {
-    SysBusDevice busdev;
-    PCIHostState host_state;
+    PCIHostState parent_obj;
 } DECState;
 
 static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
@@ -66,7 +67,7 @@
     dc->vmsd = &vmstate_pci_device;
 }
 
-static TypeInfo dec_21154_pci_bridge_info = {
+static const TypeInfo dec_21154_pci_bridge_info = {
     .name          = "dec-21154-p2p-bridge",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIBridge),
@@ -88,16 +89,16 @@
 
 static int pci_dec_21154_device_init(SysBusDevice *dev)
 {
-    DECState *s;
+    PCIHostState *phb;
 
-    s = FROM_SYSBUS(DECState, dev);
+    phb = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
-                          &s->host_state, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
-                          &s->host_state, "pci-data-idx", 0x1000);
-    sysbus_init_mmio(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio(dev, &s->host_state.data_mem);
+    memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
+                          dev, "pci-data-idx", 0x1000);
+    sysbus_init_mmio(dev, &phb->conf_mem);
+    sysbus_init_mmio(dev, &phb->data_mem);
     return 0;
 }
 
@@ -119,7 +120,7 @@
     k->is_bridge = 1;
 }
 
-static TypeInfo dec_21154_pci_host_info = {
+static const TypeInfo dec_21154_pci_host_info = {
     .name          = "dec-21154",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -133,9 +134,9 @@
     sdc->init = pci_dec_21154_device_init;
 }
 
-static TypeInfo pci_dec_21154_device_info = {
-    .name          = "dec-21154-sysbus",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo pci_dec_21154_device_info = {
+    .name          = TYPE_DEC_21154,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(DECState),
     .class_init    = pci_dec_21154_device_class_init,
 };
diff --git a/hw/dec_pci.h b/hw/dec_pci.h
index 79264ba..17dc0c2 100644
--- a/hw/dec_pci.h
+++ b/hw/dec_pci.h
@@ -3,6 +3,8 @@
 
 #include "qemu-common.h"
 
+#define TYPE_DEC_21154 "dec-21154-sysbus"
+
 PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn);
 
 #endif
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 81ff3a3..67da307 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -23,10 +23,9 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "pci_host.h"
 #include "ppc_mac.h"
 #include "pci.h"
-#include "pci_host.h"
 
 /* debug Grackle */
 //#define DEBUG_GRACKLE
@@ -38,9 +37,12 @@
 #define GRACKLE_DPRINTF(fmt, ...)
 #endif
 
+#define GRACKLE_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE)
+
 typedef struct GrackleState {
-    SysBusDevice busdev;
-    PCIHostState host_state;
+    PCIHostState parent_obj;
+
     MemoryRegion pci_mmio;
     MemoryRegion pci_hole;
 } GrackleState;
@@ -59,22 +61,20 @@
     qemu_set_irq(pic[irq_num + 0x15], level);
 }
 
-static void pci_grackle_reset(void *opaque)
-{
-}
-
 PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io)
 {
     DeviceState *dev;
     SysBusDevice *s;
+    PCIHostState *phb;
     GrackleState *d;
 
-    dev = qdev_create(NULL, "grackle-pcihost");
+    dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
-    d = FROM_SYSBUS(GrackleState, s);
+    s = SYS_BUS_DEVICE(dev);
+    phb = PCI_HOST_BRIDGE(dev);
+    d = GRACKLE_PCI_HOST_BRIDGE(dev);
 
     memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
     memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
@@ -82,36 +82,35 @@
     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                 &d->pci_hole);
 
-    d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
-                                         pci_grackle_set_irq,
-                                         pci_grackle_map_irq,
-                                         pic,
-                                         &d->pci_mmio,
-                                         address_space_io,
-                                         0, 4);
+    phb->bus = pci_register_bus(dev, "pci",
+                                pci_grackle_set_irq,
+                                pci_grackle_map_irq,
+                                pic,
+                                &d->pci_mmio,
+                                address_space_io,
+                                0, 4);
 
-    pci_create_simple(d->host_state.bus, 0, "grackle");
+    pci_create_simple(phb->bus, 0, "grackle");
 
     sysbus_mmio_map(s, 0, base);
     sysbus_mmio_map(s, 1, base + 0x00200000);
 
-    return d->host_state.bus;
+    return phb->bus;
 }
 
 static int pci_grackle_init_device(SysBusDevice *dev)
 {
-    GrackleState *s;
+    PCIHostState *phb;
 
-    s = FROM_SYSBUS(GrackleState, dev);
+    phb = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
-                          &s->host_state, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
-                          &s->host_state, "pci-data-idx", 0x1000);
-    sysbus_init_mmio(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio(dev, &s->host_state.data_mem);
+    memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
+                          dev, "pci-data-idx", 0x1000);
+    sysbus_init_mmio(dev, &phb->conf_mem);
+    sysbus_init_mmio(dev, &phb->data_mem);
 
-    qemu_register_reset(pci_grackle_reset, &s->host_state);
     return 0;
 }
 
@@ -134,7 +133,7 @@
     dc->no_user = 1;
 }
 
-static TypeInfo grackle_pci_info = {
+static const TypeInfo grackle_pci_info = {
     .name          = "grackle",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -150,9 +149,9 @@
     dc->no_user = 1;
 }
 
-static TypeInfo grackle_pci_host_info = {
-    .name          = "grackle-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo grackle_pci_host_info = {
+    .name          = TYPE_GRACKLE_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(GrackleState),
     .class_init    = pci_grackle_class_init,
 };
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index a2d0e5a..e95e664 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -229,9 +229,14 @@
     target_phys_addr_t regname ##_length;     \
     MemoryRegion regname ##_mem
 
+#define TYPE_GT64120_PCI_HOST_BRIDGE "gt64120"
+
+#define GT64120_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(GT64120State, (obj), TYPE_GT64120_PCI_HOST_BRIDGE)
+
 typedef struct GT64120State {
-    SysBusDevice busdev;
-    PCIHostState pci;
+    PCIHostState parent_obj;
+
     uint32_t regs[GT_REGS];
     PCI_MAPPING_ENTRY(PCI0IO);
     PCI_MAPPING_ENTRY(ISD);
@@ -310,6 +315,7 @@
                             uint64_t val, unsigned size)
 {
     GT64120State *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
     uint32_t saddr;
 
     if (!(s->regs[GT_CPU] & 0x00001000))
@@ -530,13 +536,15 @@
         /* not implemented */
         break;
     case GT_PCI0_CFGADDR:
-        s->pci.config_reg = val & 0x80fffffc;
+        phb->config_reg = val & 0x80fffffc;
         break;
     case GT_PCI0_CFGDATA:
-        if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800))
+        if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) {
             val = bswap32(val);
-        if (s->pci.config_reg & (1u << 31))
-            pci_data_write(s->pci.bus, s->pci.config_reg, val, 4);
+        }
+        if (phb->config_reg & (1u << 31)) {
+            pci_data_write(phb->bus, phb->config_reg, val, 4);
+        }
         break;
 
     /* Interrupts */
@@ -589,6 +597,7 @@
                                target_phys_addr_t addr, unsigned size)
 {
     GT64120State *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
     uint32_t val;
     uint32_t saddr;
 
@@ -770,15 +779,17 @@
 
     /* PCI Internal */
     case GT_PCI0_CFGADDR:
-        val = s->pci.config_reg;
+        val = phb->config_reg;
         break;
     case GT_PCI0_CFGDATA:
-        if (!(s->pci.config_reg & (1 << 31)))
+        if (!(phb->config_reg & (1 << 31))) {
             val = 0xffffffff;
-        else
-            val = pci_data_read(s->pci.bus, s->pci.config_reg, 4);
-        if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800))
+        } else {
+            val = pci_data_read(phb->bus, phb->config_reg, 4);
+        }
+        if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) {
             val = bswap32(val);
+        }
         break;
 
     case GT_PCI0_CMD:
@@ -1083,31 +1094,31 @@
 
 PCIBus *gt64120_register(qemu_irq *pic)
 {
-    SysBusDevice *s;
     GT64120State *d;
+    PCIHostState *phb;
     DeviceState *dev;
 
-    dev = qdev_create(NULL, "gt64120");
+    dev = qdev_create(NULL, TYPE_GT64120_PCI_HOST_BRIDGE);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
-    d = FROM_SYSBUS(GT64120State, s);
-    d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
-                                  gt64120_pci_set_irq, gt64120_pci_map_irq,
-                                  pic,
-                                  get_system_memory(),
-                                  get_system_io(),
-                                  PCI_DEVFN(18, 0), 4);
+    d = GT64120_PCI_HOST_BRIDGE(dev);
+    phb = PCI_HOST_BRIDGE(dev);
+    phb->bus = pci_register_bus(dev, "pci",
+                                gt64120_pci_set_irq, gt64120_pci_map_irq,
+                                pic,
+                                get_system_memory(),
+                                get_system_io(),
+                                PCI_DEVFN(18, 0), 4);
     memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000);
 
-    pci_create_simple(d->pci.bus, PCI_DEVFN(0, 0), "gt64120_pci");
-    return d->pci.bus;
+    pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
+    return phb->bus;
 }
 
 static int gt64120_init(SysBusDevice *dev)
 {
     GT64120State *s;
 
-    s = FROM_SYSBUS(GT64120State, dev);
+    s = GT64120_PCI_HOST_BRIDGE(dev);
 
     /* FIXME: This value is computed from registers during reset, but some
        devices (e.g. VGA card) need to know it when they are registered.
@@ -1147,7 +1158,7 @@
     k->class_id = PCI_CLASS_BRIDGE_HOST;
 }
 
-static TypeInfo gt64120_pci_info = {
+static const TypeInfo gt64120_pci_info = {
     .name          = "gt64120_pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -1161,9 +1172,9 @@
     sdc->init = gt64120_init;
 }
 
-static TypeInfo gt64120_info = {
-    .name          = "gt64120",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo gt64120_info = {
+    .name          = TYPE_GT64120_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(GT64120State),
     .class_init    = gt64120_class_init,
 };
diff --git a/hw/i82378.c b/hw/i82378.c
index 9b11d90..2123c14 100644
--- a/hw/i82378.c
+++ b/hw/i82378.c
@@ -225,7 +225,6 @@
     pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io);
 
     memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000);
-    memory_region_set_coalescing(&s->mem);
     pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
 
     /* Make I/O address read only */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 0c0096f..88ff041 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -360,6 +360,14 @@
 
 #define PC_COMPAT_1_1 \
         {\
+            .driver   = "virtio-scsi-pci",\
+            .property = "hotplug",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-scsi-pci",\
+            .property = "param_change",\
+            .value    = "off",\
+        },{\
             .driver   = "VGA",\
             .property = "vgamem_mb",\
             .value    = stringify(8),\
@@ -375,6 +383,10 @@
             .driver   = "qxl",\
             .property = "vgamem_mb",\
             .value    = stringify(8),\
+        },{\
+            .driver   = "virtio-blk-pci",\
+            .property = "config-wce",\
+            .value    = "off",\
         }
 
 static QEMUMachine pc_machine_v1_1 = {
diff --git a/hw/pci_host.c b/hw/pci_host.c
index 8041778..3950e94 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -165,4 +165,16 @@
     .endianness = DEVICE_BIG_ENDIAN,
 };
 
+static const TypeInfo pci_host_type_info = {
+    .name = TYPE_PCI_HOST_BRIDGE,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .abstract = true,
+    .instance_size = sizeof(PCIHostState),
+};
 
+static void pci_host_register_types(void)
+{
+    type_register_static(&pci_host_type_info);
+}
+
+type_init(pci_host_register_types)
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 359e38f..4b9c300 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -30,8 +30,13 @@
 
 #include "sysbus.h"
 
+#define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
+#define PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE)
+
 struct PCIHostState {
     SysBusDevice busdev;
+
     MemoryRegion conf_mem;
     MemoryRegion data_mem;
     MemoryRegion mmcfg;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index c497a01..537fc19 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -36,7 +36,9 @@
  * http://download.intel.com/design/chipsets/datashts/29054901.pdf
  */
 
-typedef PCIHostState I440FXState;
+typedef struct I440FXState {
+    PCIHostState parent_obj;
+} I440FXState;
 
 #define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
 #define PIIX_NUM_PIRQS          4ULL    /* PIRQ[A-D] */
@@ -225,7 +227,7 @@
 
 static int i440fx_pcihost_initfn(SysBusDevice *dev)
 {
-    I440FXState *s = FROM_SYSBUS(I440FXState, dev);
+    PCIHostState *s = PCI_HOST_BRIDGE(dev);
 
     memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s,
                           "pci-conf-idx", 4);
@@ -267,14 +269,14 @@
     DeviceState *dev;
     PCIBus *b;
     PCIDevice *d;
-    I440FXState *s;
+    PCIHostState *s;
     PIIX3State *piix3;
     PCII440FXState *f;
 
     dev = qdev_create(NULL, "i440FX-pcihost");
-    s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
+    s = PCI_HOST_BRIDGE(dev);
     s->address_space = address_space_mem;
-    b = pci_bus_new(&s->busdev.qdev, NULL, pci_address_space,
+    b = pci_bus_new(dev, NULL, pci_address_space,
                     address_space_io, 0);
     s->bus = b;
     object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
@@ -537,7 +539,7 @@
     k->class_id     = PCI_CLASS_BRIDGE_ISA;
 }
 
-static TypeInfo piix3_info = {
+static const TypeInfo piix3_info = {
     .name          = "PIIX3",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PIIX3State),
@@ -560,7 +562,7 @@
     k->class_id     = PCI_CLASS_BRIDGE_ISA;
 };
 
-static TypeInfo piix3_xen_info = {
+static const TypeInfo piix3_xen_info = {
     .name          = "PIIX3-xen",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PIIX3State),
@@ -584,7 +586,7 @@
     dc->vmsd = &vmstate_i440fx;
 }
 
-static TypeInfo i440fx_info = {
+static const TypeInfo i440fx_info = {
     .name          = "i440FX",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCII440FXState),
@@ -601,9 +603,9 @@
     dc->no_user = 1;
 }
 
-static TypeInfo i440fx_pcihost_info = {
+static const TypeInfo i440fx_pcihost_info = {
     .name          = "i440FX-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(I440FXState),
     .class_init    = i440fx_pcihost_class_init,
 };
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index 0dd4dab..c198071 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -216,7 +216,8 @@
                       ram_bases, ram_sizes, 1);
 
     /* PCI */
-    dev = sysbus_create_varargs("ppc4xx-pcihost", PPC440EP_PCI_CONFIG,
+    dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
+                                PPC440EP_PCI_CONFIG,
                                 pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]],
                                 pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]],
                                 NULL);
diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index b511020..5cd78b6 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -53,6 +53,8 @@
                         target_phys_addr_t *ram_sizes,
                         int do_init);
 
+#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
+
 PCIBus *ppc4xx_pci_init(CPUPPCState *env, qemu_irq pci_irqs[4],
                         target_phys_addr_t config_space,
                         target_phys_addr_t int_ack,
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 203c3cd..a14fd42 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -45,11 +45,14 @@
     uint32_t la;
 };
 
+#define PPC4xx_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PPC4xxPCIState, (obj), TYPE_PPC4xx_PCI_HOST_BRIDGE)
+
 #define PPC4xx_PCI_NR_PMMS 3
 #define PPC4xx_PCI_NR_PTMS 2
 
 struct PPC4xxPCIState {
-    PCIHostState pci_state;
+    PCIHostState parent_obj;
 
     struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
     struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
@@ -93,16 +96,18 @@
                                     unsigned size)
 {
     PPC4xxPCIState *ppc4xx_pci = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci);
 
-    return ppc4xx_pci->pci_state.config_reg;
+    return phb->config_reg;
 }
 
 static void pci4xx_cfgaddr_write(void *opaque, target_phys_addr_t addr,
                                   uint64_t value, unsigned size)
 {
     PPC4xxPCIState *ppc4xx_pci = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci);
 
-    ppc4xx_pci->pci_state.config_reg = value & ~0x3;
+    phb->config_reg = value & ~0x3;
 }
 
 static const MemoryRegionOps pci4xx_cfgaddr_ops = {
@@ -335,17 +340,17 @@
     PCIBus *b;
     int i;
 
-    h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
-    s = DO_UPCAST(PPC4xxPCIState, pci_state, h);
+    h = PCI_HOST_BRIDGE(dev);
+    s = PPC4xx_PCI_HOST_BRIDGE(dev);
 
     for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
         sysbus_init_irq(dev, &s->irq[i]);
     }
 
-    b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, ppc4xx_pci_set_irq,
+    b = pci_register_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
                          ppc4xx_pci_map_irq, s->irq, get_system_memory(),
                          get_system_io(), 0, 4);
-    s->pci_state.bus = b;
+    h->bus = b;
 
     pci_create_simple(b, 0, "ppc4xx-host-bridge");
 
@@ -377,7 +382,7 @@
     k->class_id     = PCI_CLASS_BRIDGE_OTHER;
 }
 
-static TypeInfo ppc4xx_host_bridge_info = {
+static const TypeInfo ppc4xx_host_bridge_info = {
     .name          = "ppc4xx-host-bridge",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -393,9 +398,9 @@
     dc->vmsd = &vmstate_ppc4xx_pci;
 }
 
-static TypeInfo ppc4xx_pcihost_info = {
-    .name          = "ppc4xx-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo ppc4xx_pcihost_info = {
+    .name          = TYPE_PPC4xx_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(PPC4xxPCIState),
     .class_init    = ppc4xx_pcihost_class_init,
 };
diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index af75e45..7d08418 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -55,6 +55,7 @@
                             int nb_cpus, qemu_irq **irqs);
 
 /* Grackle PCI */
+#define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost"
 PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io);
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 7a87616..592b7b2 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -471,7 +471,6 @@
     uint32_t kernel_base, initrd_base;
     long kernel_size, initrd_size;
     DeviceState *dev;
-    SysBusDevice *sys;
     PCIHostState *pcihost;
     PCIBus *pci_bus;
     PCIDevice *pci;
@@ -584,8 +583,7 @@
     }
 
     dev = qdev_create(NULL, "raven-pcihost");
-    sys = sysbus_from_qdev(dev);
-    pcihost = DO_UPCAST(PCIHostState, busdev, sys);
+    pcihost = PCI_HOST_BRIDGE(dev);
     pcihost->address_space = get_system_memory();
     object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL);
     qdev_init_nofail(dev);
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 0f60b24..92b1dc0 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -72,8 +72,14 @@
     uint32_t piwar;
 };
 
+#define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost"
+
+#define PPC_E500_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE)
+
 struct PPCE500PCIState {
-    PCIHostState pci_state;
+    PCIHostState parent_obj;
+
     struct pci_outbound pob[PPCE500_PCI_NR_POBS];
     struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
     uint32_t gasket_time;
@@ -310,17 +316,17 @@
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *address_space_io = get_system_io();
 
-    h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
-    s = DO_UPCAST(PPCE500PCIState, pci_state, h);
+    h = PCI_HOST_BRIDGE(dev);
+    s = PPC_E500_PCI_HOST_BRIDGE(dev);
 
     for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
         sysbus_init_irq(dev, &s->irq[i]);
     }
 
-    b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
+    b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
                          mpc85xx_pci_map_irq, s->irq, address_space_mem,
                          address_space_io, PCI_DEVFN(0x11, 0), 4);
-    s->pci_state.bus = b;
+    h->bus = b;
 
     pci_create_simple(b, 0, "e500-host-bridge");
 
@@ -350,7 +356,7 @@
     dc->desc = "Host bridge";
 }
 
-static TypeInfo e500_host_bridge_info = {
+static const TypeInfo e500_host_bridge_info = {
     .name          = "e500-host-bridge",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -366,9 +372,9 @@
     dc->vmsd = &vmstate_ppce500_pci;
 }
 
-static TypeInfo e500_pcihost_info = {
-    .name          = "e500-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo e500_pcihost_info = {
+    .name          = TYPE_PPC_E500_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(PPCE500PCIState),
     .class_init    = e500_pcihost_class_init,
 };
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 38dbff44..cc44e61 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -28,8 +28,14 @@
 #include "pc.h"
 #include "exec-memory.h"
 
+#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
+
+#define RAVEN_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE)
+
 typedef struct PRePPCIState {
-    PCIHostState host_state;
+    PCIHostState parent_obj;
+
     MemoryRegion intack;
     qemu_irq irq[4];
 } PREPPCIState;
@@ -42,9 +48,10 @@
 {
     int i;
 
-    for(i = 0; i < 11; i++) {
-        if ((addr & (1 << (11 + i))) != 0)
+    for (i = 0; i < 11; i++) {
+        if ((addr & (1 << (11 + i))) != 0) {
             break;
+        }
     }
     return (addr & 0x7ff) |  (i << 11);
 }
@@ -53,14 +60,16 @@
                              uint64_t val, unsigned int size)
 {
     PREPPCIState *s = opaque;
-    pci_data_write(s->host_state.bus, PPC_PCIIO_config(addr), val, size);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    pci_data_write(phb->bus, PPC_PCIIO_config(addr), val, size);
 }
 
 static uint64_t ppc_pci_io_read(void *opaque, target_phys_addr_t addr,
                                 unsigned int size)
 {
     PREPPCIState *s = opaque;
-    return pci_data_read(s->host_state.bus, PPC_PCIIO_config(addr), size);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    return pci_data_read(phb->bus, PPC_PCIIO_config(addr), size);
 }
 
 static const MemoryRegionOps PPC_PCIIO_ops = {
@@ -96,8 +105,8 @@
 
 static int raven_pcihost_init(SysBusDevice *dev)
 {
-    PCIHostState *h = FROM_SYSBUS(PCIHostState, dev);
-    PREPPCIState *s = DO_UPCAST(PREPPCIState, host_state, h);
+    PCIHostState *h = PCI_HOST_BRIDGE(dev);
+    PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev);
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *address_space_io = get_system_io();
     PCIBus *bus;
@@ -107,7 +116,7 @@
         sysbus_init_irq(dev, &s->irq[i]);
     }
 
-    bus = pci_register_bus(&h->busdev.qdev, NULL,
+    bus = pci_register_bus(DEVICE(dev), NULL,
                            prep_set_irq, prep_map_irq, s->irq,
                            address_space_mem, address_space_io, 0, 4);
     h->bus = bus;
@@ -166,7 +175,7 @@
     dc->no_user = 1;
 }
 
-static TypeInfo raven_info = {
+static const TypeInfo raven_info = {
     .name = "raven",
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(RavenPCIState),
@@ -183,9 +192,9 @@
     dc->no_user = 1;
 }
 
-static TypeInfo raven_pcihost_info = {
-    .name = "raven-pcihost",
-    .parent = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo raven_pcihost_info = {
+    .name = TYPE_RAVEN_PCI_HOST_BRIDGE,
+    .parent = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(PREPPCIState),
     .class_init = raven_pcihost_class_init,
 };
diff --git a/hw/spapr.c b/hw/spapr.c
index be533ee..c34b767 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -612,6 +612,7 @@
 {
     PowerPCCPU *cpu;
     CPUPPCState *env;
+    PCIHostState *phb;
     int i;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -742,6 +743,7 @@
                      SPAPR_PCI_MEM_WIN_SIZE,
                      SPAPR_PCI_IO_WIN_ADDR,
                      SPAPR_PCI_MSI_WIN_ADDR);
+    phb = PCI_HOST_BRIDGE(QLIST_FIRST(&spapr->phbs));
 
     for (i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
@@ -762,13 +764,12 @@
     }
 
     /* Graphics */
-    if (spapr_vga_init(QLIST_FIRST(&spapr->phbs)->host_state.bus)) {
+    if (spapr_vga_init(phb->bus)) {
         spapr->has_graphics = true;
     }
 
     if (usb_enabled) {
-        pci_create_simple(QLIST_FIRST(&spapr->phbs)->host_state.bus,
-                          -1, "pci-ohci");
+        pci_create_simple(phb->bus, -1, "pci-ohci");
         if (spapr->has_graphics) {
             usbdevice_create("keyboard");
             usbdevice_create("mouse");
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index b92583a..661c05b 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -48,13 +48,13 @@
 
 static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
 {
-    sPAPRPHBState *phb;
+    sPAPRPHBState *sphb;
 
-    QLIST_FOREACH(phb, &spapr->phbs, list) {
-        if (phb->buid != buid) {
+    QLIST_FOREACH(sphb, &spapr->phbs, list) {
+        if (sphb->buid != buid) {
             continue;
         }
-        return phb;
+        return sphb;
     }
 
     return NULL;
@@ -63,7 +63,9 @@
 static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid,
                            uint32_t config_addr)
 {
-    sPAPRPHBState *phb = find_phb(spapr, buid);
+    sPAPRPHBState *sphb = find_phb(spapr, buid);
+    PCIHostState *phb = PCI_HOST_BRIDGE(sphb);
+    BusState *bus = BUS(phb->bus);
     BusChild *kid;
     int devfn = (config_addr >> 8) & 0xFF;
 
@@ -71,7 +73,7 @@
         return NULL;
     }
 
-    QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
         PCIDevice *dev = (PCIDevice *)kid->child;
         if (dev->devfn == devfn) {
             return dev;
@@ -514,23 +516,24 @@
 
 static int spapr_phb_init(SysBusDevice *s)
 {
-    sPAPRPHBState *phb = DO_UPCAST(sPAPRPHBState, host_state.busdev, s);
+    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
     char *namebuf;
     int i;
     PCIBus *bus;
 
-    phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid);
-    namebuf = alloca(strlen(phb->dtbusname) + 32);
+    sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
+    namebuf = alloca(strlen(sphb->dtbusname) + 32);
 
     /* Initialize memory regions */
-    sprintf(namebuf, "%s.mmio", phb->dtbusname);
-    memory_region_init(&phb->memspace, namebuf, INT64_MAX);
+    sprintf(namebuf, "%s.mmio", sphb->dtbusname);
+    memory_region_init(&sphb->memspace, namebuf, INT64_MAX);
 
-    sprintf(namebuf, "%s.mmio-alias", phb->dtbusname);
-    memory_region_init_alias(&phb->memwindow, namebuf, &phb->memspace,
-                             SPAPR_PCI_MEM_WIN_BUS_OFFSET, phb->mem_win_size);
-    memory_region_add_subregion(get_system_memory(), phb->mem_win_addr,
-                                &phb->memwindow);
+    sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname);
+    memory_region_init_alias(&sphb->memwindow, namebuf, &sphb->memspace,
+                             SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size);
+    memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr,
+                                &sphb->memwindow);
 
     /* On ppc, we only have MMIO no specific IO space from the CPU
      * perspective.  In theory we ought to be able to embed the PCI IO
@@ -540,42 +543,42 @@
      * system io address space.  This hack to bounce things via
      * system_io works around the problem until all the users of
      * old_portion are updated */
-    sprintf(namebuf, "%s.io", phb->dtbusname);
-    memory_region_init(&phb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
+    sprintf(namebuf, "%s.io", sphb->dtbusname);
+    memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
     /* FIXME: fix to support multiple PHBs */
-    memory_region_add_subregion(get_system_io(), 0, &phb->iospace);
+    memory_region_add_subregion(get_system_io(), 0, &sphb->iospace);
 
-    sprintf(namebuf, "%s.io-alias", phb->dtbusname);
-    memory_region_init_io(&phb->iowindow, &spapr_io_ops, phb,
+    sprintf(namebuf, "%s.io-alias", sphb->dtbusname);
+    memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb,
                           namebuf, SPAPR_PCI_IO_WIN_SIZE);
-    memory_region_add_subregion(get_system_memory(), phb->io_win_addr,
-                                &phb->iowindow);
+    memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
+                                &sphb->iowindow);
 
     /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
      * we need to allocate some memory to catch those writes coming
      * from msi_notify()/msix_notify() */
     if (msi_supported) {
-        sprintf(namebuf, "%s.msi", phb->dtbusname);
-        memory_region_init_io(&phb->msiwindow, &spapr_msi_ops, phb,
+        sprintf(namebuf, "%s.msi", sphb->dtbusname);
+        memory_region_init_io(&sphb->msiwindow, &spapr_msi_ops, sphb,
                               namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000);
-        memory_region_add_subregion(get_system_memory(), phb->msi_win_addr,
-                                    &phb->msiwindow);
+        memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr,
+                                    &sphb->msiwindow);
     }
 
-    bus = pci_register_bus(&phb->host_state.busdev.qdev,
-                           phb->busname ? phb->busname : phb->dtbusname,
-                           pci_spapr_set_irq, pci_spapr_map_irq, phb,
-                           &phb->memspace, &phb->iospace,
+    bus = pci_register_bus(DEVICE(s),
+                           sphb->busname ? sphb->busname : sphb->dtbusname,
+                           pci_spapr_set_irq, pci_spapr_map_irq, sphb,
+                           &sphb->memspace, &sphb->iospace,
                            PCI_DEVFN(0, 0), PCI_NUM_PINS);
-    phb->host_state.bus = bus;
+    phb->bus = bus;
 
-    phb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
-    phb->dma_window_start = 0;
-    phb->dma_window_size = 0x40000000;
-    phb->dma = spapr_tce_new_dma_context(phb->dma_liobn, phb->dma_window_size);
-    pci_setup_iommu(bus, spapr_pci_dma_context_fn, phb);
+    sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
+    sphb->dma_window_start = 0;
+    sphb->dma_window_size = 0x40000000;
+    sphb->dma = spapr_tce_new_dma_context(sphb->dma_liobn, sphb->dma_window_size);
+    pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb);
 
-    QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
+    QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);
 
     /* Initialize the LSI table */
     for (i = 0; i < PCI_NUM_PINS; i++) {
@@ -586,7 +589,7 @@
             return -1;
         }
 
-        phb->lsi_table[i].irq = irq;
+        sphb->lsi_table[i].irq = irq;
     }
 
     return 0;
@@ -612,9 +615,9 @@
     dc->props = spapr_phb_properties;
 }
 
-static TypeInfo spapr_phb_info = {
-    .name          = "spapr-pci-host-bridge",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo spapr_phb_info = {
+    .name          = TYPE_SPAPR_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(sPAPRPHBState),
     .class_init    = spapr_phb_class_init,
 };
@@ -626,7 +629,7 @@
 {
     DeviceState *dev;
 
-    dev = qdev_create(NULL, spapr_phb_info.name);
+    dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
 
     if (busname) {
         qdev_prop_set_string(dev, "busname", g_strdup(busname));
@@ -750,8 +753,9 @@
     }
 }
 
-static void register_types(void)
+static void spapr_pci_register_types(void)
 {
     type_register_static(&spapr_phb_info);
 }
-type_init(register_types)
+
+type_init(spapr_pci_register_types)
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index 7518899..670dc62 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -29,8 +29,13 @@
 
 #define SPAPR_MSIX_MAX_DEVS 32
 
+#define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge"
+
+#define SPAPR_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(sPAPRPHBState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE)
+
 typedef struct sPAPRPHBState {
-    PCIHostState host_state;
+    PCIHostState parent_obj;
 
     uint64_t buid;
     char *busname;
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 409bcd4..d1cc680 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -38,8 +38,23 @@
 
 static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
 
+#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost"
+#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost"
+#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
+#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost"
+
+#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
+#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
+#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
+#define U3_AGP_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(UNINState, (obj), TYPE_U3_AGP_HOST_BRIDGE)
+
 typedef struct UNINState {
-    PCIHostState host_state;
+    PCIHostState parent_obj;
+
     MemoryRegion pci_mmio;
     MemoryRegion pci_hole;
 } UNINState;
@@ -100,10 +115,11 @@
                             uint64_t val, unsigned len)
 {
     UNINState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
     UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n",
                  addr, len, val);
-    pci_data_write(s->host_state.bus,
-                   unin_get_config_reg(s->host_state.config_reg, addr),
+    pci_data_write(phb->bus,
+                   unin_get_config_reg(phb->config_reg, addr),
                    val, len);
 }
 
@@ -111,10 +127,11 @@
                                unsigned len)
 {
     UNINState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
     uint32_t val;
 
-    val = pci_data_read(s->host_state.bus,
-                        unin_get_config_reg(s->host_state.config_reg, addr),
+    val = pci_data_read(phb->bus,
+                        unin_get_config_reg(phb->config_reg, addr),
                         len);
     UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n",
                  addr, len, val);
@@ -130,19 +147,17 @@
 static int pci_unin_main_init_device(SysBusDevice *dev)
 {
     PCIHostState *h;
-    UNINState *s;
 
     /* Use values found on a real PowerMac */
     /* Uninorth main bus */
-    h = FROM_SYSBUS(PCIHostState, dev);
-    s = DO_UPCAST(UNINState, host_state, h);
+    h = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
-                          &s->host_state, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
                           "pci-conf-data", 0x1000);
-    sysbus_init_mmio(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &h->conf_mem);
+    sysbus_init_mmio(dev, &h->data_mem);
 
     return 0;
 }
@@ -151,18 +166,16 @@
 static int pci_u3_agp_init_device(SysBusDevice *dev)
 {
     PCIHostState *h;
-    UNINState *s;
 
     /* Uninorth U3 AGP bus */
-    h = FROM_SYSBUS(PCIHostState, dev);
-    s = DO_UPCAST(UNINState, host_state, h);
+    h = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
-                          &s->host_state, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
                           "pci-conf-data", 0x1000);
-    sysbus_init_mmio(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio(dev, &s->host_state.data_mem);
+    sysbus_init_mmio(dev, &h->conf_mem);
+    sysbus_init_mmio(dev, &h->data_mem);
 
     return 0;
 }
@@ -170,36 +183,32 @@
 static int pci_unin_agp_init_device(SysBusDevice *dev)
 {
     PCIHostState *h;
-    UNINState *s;
 
     /* Uninorth AGP bus */
-    h = FROM_SYSBUS(PCIHostState, dev);
-    s = DO_UPCAST(UNINState, host_state, h);
+    h = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
-                          &s->host_state, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
-                          &s->host_state, "pci-conf-data", 0x1000);
-    sysbus_init_mmio(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio(dev, &s->host_state.data_mem);
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
+                          dev, "pci-conf-data", 0x1000);
+    sysbus_init_mmio(dev, &h->conf_mem);
+    sysbus_init_mmio(dev, &h->data_mem);
     return 0;
 }
 
 static int pci_unin_internal_init_device(SysBusDevice *dev)
 {
     PCIHostState *h;
-    UNINState *s;
 
     /* Uninorth internal bus */
-    h = FROM_SYSBUS(PCIHostState, dev);
-    s = DO_UPCAST(UNINState, host_state, h);
+    h = PCI_HOST_BRIDGE(dev);
 
-    memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
-                          &s->host_state, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
-                          &s->host_state, "pci-conf-data", 0x1000);
-    sysbus_init_mmio(dev, &s->host_state.conf_mem);
-    sysbus_init_mmio(dev, &s->host_state.data_mem);
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
+                          dev, "pci-conf-data", 0x1000);
+    sysbus_init_mmio(dev, &h->conf_mem);
+    sysbus_init_mmio(dev, &h->data_mem);
     return 0;
 }
 
@@ -214,26 +223,26 @@
 
     /* Use values found on a real PowerMac */
     /* Uninorth main bus */
-    dev = qdev_create(NULL, "uni-north-pci-pcihost");
+    dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
-    h = FROM_SYSBUS(PCIHostState, s);
-    d = DO_UPCAST(UNINState, host_state, h);
+    s = SYS_BUS_DEVICE(dev);
+    h = PCI_HOST_BRIDGE(s);
+    d = UNI_NORTH_PCI_HOST_BRIDGE(dev);
     memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
     memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
                              0x80000000ULL, 0x70000000ULL);
     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                 &d->pci_hole);
 
-    d->host_state.bus = pci_register_bus(dev, "pci",
-                                         pci_unin_set_irq, pci_unin_map_irq,
-                                         pic,
-                                         &d->pci_mmio,
-                                         address_space_io,
-                                         PCI_DEVFN(11, 0), 4);
+    h->bus = pci_register_bus(dev, "pci",
+                              pci_unin_set_irq, pci_unin_map_irq,
+                              pic,
+                              &d->pci_mmio,
+                              address_space_io,
+                              PCI_DEVFN(11, 0), 4);
 
 #if 0
-    pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
+    pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north");
 #endif
 
     sysbus_mmio_map(s, 0, 0xf2800000);
@@ -242,30 +251,30 @@
     /* DEC 21154 bridge */
 #if 0
     /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
-    pci_create_simple(d->host_state.bus, PCI_DEVFN(12, 0), "dec-21154");
+    pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154");
 #endif
 
     /* Uninorth AGP bus */
-    pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north-agp");
-    dev = qdev_create(NULL, "uni-north-agp-pcihost");
+    pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp");
+    dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(s, 0, 0xf0800000);
     sysbus_mmio_map(s, 1, 0xf0c00000);
 
     /* Uninorth internal bus */
 #if 0
     /* XXX: not needed for now */
-    pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0),
+    pci_create_simple(h->bus, PCI_DEVFN(14, 0),
                       "uni-north-internal-pci");
-    dev = qdev_create(NULL, "uni-north-internal-pci-pcihost");
+    dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(s, 0, 0xf4800000);
     sysbus_mmio_map(s, 1, 0xf4c00000);
 #endif
 
-    return d->host_state.bus;
+    return h->bus;
 }
 
 PCIBus *pci_pmac_u3_init(qemu_irq *pic,
@@ -279,11 +288,11 @@
 
     /* Uninorth AGP bus */
 
-    dev = qdev_create(NULL, "u3-agp-pcihost");
+    dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
-    h = FROM_SYSBUS(PCIHostState, s);
-    d = DO_UPCAST(UNINState, host_state, h);
+    s = SYS_BUS_DEVICE(dev);
+    h = PCI_HOST_BRIDGE(dev);
+    d = U3_AGP_HOST_BRIDGE(dev);
 
     memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
     memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
@@ -291,19 +300,19 @@
     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                 &d->pci_hole);
 
-    d->host_state.bus = pci_register_bus(dev, "pci",
-                                         pci_unin_set_irq, pci_unin_map_irq,
-                                         pic,
-                                         &d->pci_mmio,
-                                         address_space_io,
-                                         PCI_DEVFN(11, 0), 4);
+    h->bus = pci_register_bus(dev, "pci",
+                              pci_unin_set_irq, pci_unin_map_irq,
+                              pic,
+                              &d->pci_mmio,
+                              address_space_io,
+                              PCI_DEVFN(11, 0), 4);
 
     sysbus_mmio_map(s, 0, 0xf0800000);
     sysbus_mmio_map(s, 1, 0xf0c00000);
 
-    pci_create_simple(d->host_state.bus, 11 << 3, "u3-agp");
+    pci_create_simple(h->bus, 11 << 3, "u3-agp");
 
-    return d->host_state.bus;
+    return h->bus;
 }
 
 static int unin_main_pci_host_init(PCIDevice *d)
@@ -350,7 +359,7 @@
     k->class_id  = PCI_CLASS_BRIDGE_HOST;
 }
 
-static TypeInfo unin_main_pci_host_info = {
+static const TypeInfo unin_main_pci_host_info = {
     .name = "uni-north-pci",
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -368,7 +377,7 @@
     k->class_id  = PCI_CLASS_BRIDGE_HOST;
 }
 
-static TypeInfo u3_agp_pci_host_info = {
+static const TypeInfo u3_agp_pci_host_info = {
     .name = "u3-agp",
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -386,7 +395,7 @@
     k->class_id  = PCI_CLASS_BRIDGE_HOST;
 }
 
-static TypeInfo unin_agp_pci_host_info = {
+static const TypeInfo unin_agp_pci_host_info = {
     .name = "uni-north-agp",
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -404,7 +413,7 @@
     k->class_id  = PCI_CLASS_BRIDGE_HOST;
 }
 
-static TypeInfo unin_internal_pci_host_info = {
+static const TypeInfo unin_internal_pci_host_info = {
     .name = "uni-north-internal-pci",
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -418,9 +427,9 @@
     sbc->init = pci_unin_main_init_device;
 }
 
-static TypeInfo pci_unin_main_info = {
-    .name          = "uni-north-pci-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo pci_unin_main_info = {
+    .name          = TYPE_UNI_NORTH_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(UNINState),
     .class_init    = pci_unin_main_class_init,
 };
@@ -432,9 +441,9 @@
     sbc->init = pci_u3_agp_init_device;
 }
 
-static TypeInfo pci_u3_agp_info = {
-    .name          = "u3-agp-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo pci_u3_agp_info = {
+    .name          = TYPE_U3_AGP_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(UNINState),
     .class_init    = pci_u3_agp_class_init,
 };
@@ -446,9 +455,9 @@
     sbc->init = pci_unin_agp_init_device;
 }
 
-static TypeInfo pci_unin_agp_info = {
-    .name          = "uni-north-agp-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo pci_unin_agp_info = {
+    .name          = TYPE_UNI_NORTH_AGP_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(UNINState),
     .class_init    = pci_unin_agp_class_init,
 };
@@ -460,9 +469,9 @@
     sbc->init = pci_unin_internal_init_device;
 }
 
-static TypeInfo pci_unin_internal_info = {
-    .name          = "uni-north-internal-pci-pcihost",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo pci_unin_internal_info = {
+    .name          = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(UNINState),
     .class_init    = pci_unin_internal_class_init,
 };
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 01a7622..c7e5bc0 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -107,6 +107,7 @@
     }
 
     usb_packet_copy(p, s->setup_buf, p->iov.size);
+    p->result = 0;
     s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
     s->setup_index = 0;
 
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 9b02ff4..b13eeba 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -223,7 +223,7 @@
 static const USBDesc desc = {
     .id = {
         .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
-        .idProduct         = 0x0002,
+        .idProduct         = 0x0003,
         .bcdDevice         = 0,
         .iManufacturer     = STR_MANUFACTURER,
         .iProduct          = STR_PRODUCT,
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 104c21d..8b94b17 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -575,7 +575,12 @@
 /* flag interrupt condition */
 static inline void ehci_raise_irq(EHCIState *s, int intr)
 {
-    s->usbsts_pending |= intr;
+    if (intr & (USBSTS_PCD | USBSTS_FLR | USBSTS_HSE)) {
+        s->usbsts |= intr;
+        ehci_update_irq(s);
+    } else {
+        s->usbsts_pending |= intr;
+    }
 }
 
 /*
@@ -1182,22 +1187,23 @@
             break;
         }
 
-        if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
-            ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
-            if (s->pstate == EST_INACTIVE) {
-                SET_LAST_RUN_CLOCK(s);
-            }
-            ehci_update_halt(s);
-            s->async_stepdown = 0;
-            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
-        }
-
         /* not supporting dynamic frame list size at the moment */
         if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
             fprintf(stderr, "attempt to set frame list size -- value %d\n",
                     val & USBCMD_FLS);
             val &= ~USBCMD_FLS;
         }
+
+        if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
+            ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
+            if (s->pstate == EST_INACTIVE) {
+                SET_LAST_RUN_CLOCK(s);
+            }
+            s->usbcmd = val; /* Set usbcmd for ehci_update_halt() */
+            ehci_update_halt(s);
+            s->async_stepdown = 0;
+            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
+        }
         break;
 
     case USBSTS:
@@ -2466,13 +2472,16 @@
 
 static const VMStateDescription vmstate_ehci = {
     .name        = "ehci",
-    .version_id  = 1,
+    .version_id  = 2,
+    .minimum_version_id  = 1,
     .post_load   = usb_ehci_post_load,
     .fields      = (VMStateField[]) {
         VMSTATE_PCI_DEVICE(dev, EHCIState),
         /* mmio registers */
         VMSTATE_UINT32(usbcmd, EHCIState),
         VMSTATE_UINT32(usbsts, EHCIState),
+        VMSTATE_UINT32_V(usbsts_pending, EHCIState, 2),
+        VMSTATE_UINT32_V(usbsts_frindex, EHCIState, 2),
         VMSTATE_UINT32(usbintr, EHCIState),
         VMSTATE_UINT32(frindex, EHCIState),
         VMSTATE_UINT32(ctrldssegment, EHCIState),
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index d55be87..8df9207 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -1045,6 +1045,7 @@
 
     /* Note request is (bRequestType << 8) | bRequest */
     trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index);
+    assert(p->result == 0);
 
     switch (request) {
     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index fd8fa90..6f6d172 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -533,7 +533,6 @@
     features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
     features |= (1 << VIRTIO_BLK_F_SCSI);
 
-    features |= (1 << VIRTIO_BLK_F_CONFIG_WCE);
     if (bdrv_enable_write_cache(s->bs))
         features |= (1 << VIRTIO_BLK_F_WCE);
 
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index 35834cf..f0740d0 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -104,9 +104,11 @@
     BlockConf conf;
     char *serial;
     uint32_t scsi;
+    uint32_t config_wce;
 };
 
 #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
-        DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
+        DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
+        DEFINE_PROP_BIT("config-wce", _state, _field, VIRTIO_BLK_F_CONFIG_WCE, true)
 
 #endif
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 5e6e09e..2a3d86f 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -886,6 +886,7 @@
 #ifdef __linux__
     DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
 #endif
+    DEFINE_PROP_BIT("config-wce", VirtIOPCIProxy, blk.config_wce, 0, true),
     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
     DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 5f737ac..c1b47a8 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -24,11 +24,6 @@
 #define VIRTIO_SCSI_MAX_TARGET  255
 #define VIRTIO_SCSI_MAX_LUN     16383
 
-/* Feature Bits */
-#define VIRTIO_SCSI_F_INOUT                    0
-#define VIRTIO_SCSI_F_HOTPLUG                  1
-#define VIRTIO_SCSI_F_CHANGE                   2
-
 /* Response codes */
 #define VIRTIO_SCSI_S_OK                       0
 #define VIRTIO_SCSI_S_OVERRUN                  1
@@ -561,8 +556,6 @@
 static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
                                          uint32_t requested_features)
 {
-    requested_features |= (1UL << VIRTIO_SCSI_F_HOTPLUG);
-    requested_features |= (1UL << VIRTIO_SCSI_F_CHANGE);
     return requested_features;
 }
 
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index 4bc889d..91924f6 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -21,6 +21,11 @@
 /* The ID for virtio_scsi */
 #define VIRTIO_ID_SCSI  8
 
+/* Feature Bits */
+#define VIRTIO_SCSI_F_INOUT                    0
+#define VIRTIO_SCSI_F_HOTPLUG                  1
+#define VIRTIO_SCSI_F_CHANGE                   2
+
 struct VirtIOSCSIConf {
     uint32_t num_queues;
     uint32_t max_sectors;
@@ -31,6 +36,8 @@
     DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_field), \
     DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
     DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \
-    DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
+    DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128), \
+    DEFINE_PROP_BIT("hotplug", _state, _features_field, VIRTIO_SCSI_F_HOTPLUG, true), \
+    DEFINE_PROP_BIT("param_change", _state, _features_field, VIRTIO_SCSI_F_CHANGE, true)
 
 #endif /* _QEMU_VIRTIO_SCSI_H */
diff --git a/iohandler.c b/iohandler.c
index 3c74de6..dea4355 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -77,6 +77,7 @@
         ioh->fd_write = fd_write;
         ioh->opaque = opaque;
         ioh->deleted = 0;
+        qemu_notify_event();
     }
     return 0;
 }
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 41c869b..1174306 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2848,7 +2848,7 @@
     if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
         return -TARGET_EFAULT;
 
-    host_mb = malloc(msgsz+sizeof(long));
+    host_mb = g_malloc(msgsz+sizeof(long));
     ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg));
 
     if (ret > 0) {
@@ -2863,11 +2863,11 @@
     }
 
     target_mb->mtype = tswapal(host_mb->mtype);
-    free(host_mb);
 
 end:
     if (target_mb)
         unlock_user_struct(target_mb, msgp, 1);
+    g_free(host_mb);
     return ret;
 }
 
diff --git a/qapi-schema.json b/qapi-schema.json
index 37f47e1..bd8ad74 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2454,3 +2454,42 @@
 #
 ##
 { 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }
+
+##
+# @TargetType
+#
+# Target CPU emulation type
+#
+# These parameters correspond to the softmmu binary CPU name that is currently
+# running.
+#
+# Since: 1.2.0
+##
+{ 'enum': 'TargetType',
+  'data': [ 'alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel',
+            'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'or32',
+            'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4', 'sparc64',
+            'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }
+
+##
+# @TargetInfo:
+#
+# Information describing the QEMU target.
+#
+# @arch: the target architecture (eg "x86_64", "i386", etc)
+#
+# Since: 1.2.0
+##
+{ 'type': 'TargetInfo',
+  'data': { 'arch': 'TargetType' } }
+
+##
+# @query-target:
+#
+# Return information about the target for this QEMU
+#
+# Returns: TargetInfo
+#
+# Since: 1.2.0
+##
+{ 'command': 'query-target', 'returns': 'TargetInfo' }
diff --git a/qemu-ga.c b/qemu-ga.c
index 8f87621..26671fe 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -247,6 +247,9 @@
     pidfd = open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
     if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) {
         g_critical("Cannot lock pid file, %s", strerror(errno));
+        if (pidfd != -1) {
+            close(pidfd);
+        }
         return false;
     }
 
diff --git a/qemu-img.texi b/qemu-img.texi
index 77c6d0b..6b42e35 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -4,6 +4,16 @@
 @c man end
 @end example
 
+@c man begin DESCRIPTION
+qemu-img allows you to create, convert and modify images offline. It can handle
+all image formats supported by QEMU.
+
+@b{Warning:} Never use qemu-img to modify images in use by a running virtual
+machine or any other process; this may destroy the image. Also, be aware that
+querying an image that is being modified by another process may encounter
+inconsistent state.
+@c man end
+
 @c man begin OPTIONS
 
 The following commands are supported:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 8671bf3..3745a21 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2509,3 +2509,8 @@
         .mhandler.cmd_new = qmp_marshal_input_query_cpu_definitions,
     },
 
+    {
+        .name       = "query-target",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_target,
+    },
diff --git a/softmmu-semi.h b/softmmu-semi.h
index 648cb95..bcb979a 100644
--- a/softmmu-semi.h
+++ b/softmmu-semi.h
@@ -40,7 +40,7 @@
     uint8_t *p;
     /* TODO: Make this something that isn't fixed size.  */
     p = malloc(len);
-    if (copy)
+    if (p && copy)
         cpu_memory_rw_debug(env, addr, p, len, 0);
     return p;
 }
@@ -52,6 +52,9 @@
     uint8_t c;
     /* TODO: Make this something that isn't fixed size.  */
     s = p = malloc(1024);
+    if (!s) {
+        return NULL;
+    }
     do {
         cpu_memory_rw_debug(env, addr, &c, 1, 0);
         addr++;
diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c
index 2495206..73bde58 100644
--- a/target-arm/arm-semi.c
+++ b/target-arm/arm-semi.c
@@ -194,18 +194,19 @@
         if (!(s = lock_user_string(ARG(0))))
             /* FIXME - should this error code be -TARGET_EFAULT ? */
             return (uint32_t)-1;
-        if (ARG(1) >= 12)
+        if (ARG(1) >= 12) {
+            unlock_user(s, ARG(0), 0);
             return (uint32_t)-1;
+        }
         if (strcmp(s, ":tt") == 0) {
-            if (ARG(1) < 4)
-                return STDIN_FILENO;
-            else
-                return STDOUT_FILENO;
+            int result_fileno = ARG(1) < 4 ? STDIN_FILENO : STDOUT_FILENO;
+            unlock_user(s, ARG(0), 0);
+            return result_fileno;
         }
         if (use_gdb_syscalls()) {
             gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0),
 			   (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]);
-            return env->regs[0];
+            ret = env->regs[0];
         } else {
             ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
         }
diff --git a/xen-all.c b/xen-all.c
index 61def2e..f76b051 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -712,7 +712,8 @@
 
             for (i = 0; i < req->count; i++) {
                 tmp = do_inp(req->addr, req->size);
-                cpu_physical_memory_write(req->data + (sign * i * req->size),
+                cpu_physical_memory_write(
+                        req->data + (sign * i * (int64_t)req->size),
                         (uint8_t *) &tmp, req->size);
             }
         }
@@ -723,7 +724,8 @@
             for (i = 0; i < req->count; i++) {
                 uint32_t tmp = 0;
 
-                cpu_physical_memory_read(req->data + (sign * i * req->size),
+                cpu_physical_memory_read(
+                        req->data + (sign * i * (int64_t)req->size),
                         (uint8_t*) &tmp, req->size);
                 do_outp(req->addr, req->size, tmp);
             }
@@ -740,12 +742,14 @@
     if (!req->data_is_ptr) {
         if (req->dir == IOREQ_READ) {
             for (i = 0; i < req->count; i++) {
-                cpu_physical_memory_read(req->addr + (sign * i * req->size),
+                cpu_physical_memory_read(
+                        req->addr + (sign * i * (int64_t)req->size),
                         (uint8_t *) &req->data, req->size);
             }
         } else if (req->dir == IOREQ_WRITE) {
             for (i = 0; i < req->count; i++) {
-                cpu_physical_memory_write(req->addr + (sign * i * req->size),
+                cpu_physical_memory_write(
+                        req->addr + (sign * i * (int64_t)req->size),
                         (uint8_t *) &req->data, req->size);
             }
         }
@@ -754,16 +758,20 @@
 
         if (req->dir == IOREQ_READ) {
             for (i = 0; i < req->count; i++) {
-                cpu_physical_memory_read(req->addr + (sign * i * req->size),
+                cpu_physical_memory_read(
+                        req->addr + (sign * i * (int64_t)req->size),
                         (uint8_t*) &tmp, req->size);
-                cpu_physical_memory_write(req->data + (sign * i * req->size),
+                cpu_physical_memory_write(
+                        req->data + (sign * i * (int64_t)req->size),
                         (uint8_t*) &tmp, req->size);
             }
         } else if (req->dir == IOREQ_WRITE) {
             for (i = 0; i < req->count; i++) {
-                cpu_physical_memory_read(req->data + (sign * i * req->size),
+                cpu_physical_memory_read(
+                        req->data + (sign * i * (int64_t)req->size),
                         (uint8_t*) &tmp, req->size);
-                cpu_physical_memory_write(req->addr + (sign * i * req->size),
+                cpu_physical_memory_write(
+                        req->addr + (sign * i * (int64_t)req->size),
                         (uint8_t*) &tmp, req->size);
             }
         }
diff --git a/xen-mapcache.c b/xen-mapcache.c
index 59ba085..9cd6db3 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -320,10 +320,6 @@
     target_phys_addr_t size;
     int found = 0;
 
-    if (mapcache->last_address_vaddr == buffer) {
-        mapcache->last_address_index = -1;
-    }
-
     QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
         if (reventry->vaddr_req == buffer) {
             paddr_index = reventry->paddr_index;
@@ -342,6 +338,11 @@
     QTAILQ_REMOVE(&mapcache->locked_entries, reventry, next);
     g_free(reventry);
 
+    if (mapcache->last_address_index == paddr_index) {
+        mapcache->last_address_index = -1;
+        mapcache->last_address_vaddr = NULL;
+    }
+
     entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
     while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
         pentry = entry;