summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile.objs6
-rw-r--r--VERSION2
-rw-r--r--arch_init.c11
-rw-r--r--block/sheepdog.c1
-rwxr-xr-xconfigure113
-rw-r--r--dma-helpers.c4
-rw-r--r--exec.c21
-rw-r--r--hw/alpha_typhoon.c26
-rw-r--r--hw/boards.h3
-rw-r--r--hw/bonito.c152
-rw-r--r--hw/dec_pci.c31
-rw-r--r--hw/dec_pci.h2
-rw-r--r--hw/grackle_pci.c65
-rw-r--r--hw/gt64xxx.c67
-rw-r--r--hw/i82378.c1
-rw-r--r--hw/msix.c8
-rw-r--r--hw/pc.c31
-rw-r--r--hw/pc_piix.c4
-rw-r--r--hw/pci_host.c12
-rw-r--r--hw/pci_host.h5
-rw-r--r--hw/piix_pci.c22
-rw-r--r--hw/ppc440_bamboo.c3
-rw-r--r--hw/ppc4xx.h2
-rw-r--r--hw/ppc4xx_pci.c27
-rw-r--r--hw/ppc_mac.h1
-rw-r--r--hw/ppc_prep.c4
-rw-r--r--hw/ppce500_pci.c24
-rw-r--r--hw/prep_pci.c33
-rw-r--r--hw/scsi-bus.c2
-rw-r--r--hw/spapr.c13
-rw-r--r--hw/spapr_pci.c94
-rw-r--r--hw/spapr_pci.h7
-rw-r--r--hw/unin_pci.c185
-rw-r--r--hw/virtio-blk.c1
-rw-r--r--hw/virtio-blk.h3
-rw-r--r--iohandler.c1
-rw-r--r--json-parser.c230
-rw-r--r--linux-user/syscall.c4
-rw-r--r--osdep.c8
-rw-r--r--osdep.h7
-rw-r--r--pc-bios/README2
-rw-r--r--pc-bios/openbios-ppcbin729876 -> 729876 bytes
-rw-r--r--pc-bios/openbios-sparc32bin381764 -> 381764 bytes
-rw-r--r--pc-bios/openbios-sparc64bin1598648 -> 1598648 bytes
-rw-r--r--qapi-schema.json39
-rw-r--r--qemu-char.c7
-rw-r--r--qemu-config.c18
-rw-r--r--qemu-config.h1
-rw-r--r--qemu-ga.c3
-rw-r--r--qemu-options.hx15
-rw-r--r--qemu-seccomp.c141
-rw-r--r--qemu-seccomp.h22
-rw-r--r--qlist.c13
-rw-r--r--qlist.h1
-rw-r--r--qmp-commands.hx5
-rw-r--r--rules.mak2
-rw-r--r--softmmu-semi.h5
-rw-r--r--sysemu.h1
-rw-r--r--target-arm/arm-semi.c13
-rw-r--r--tests/check-qjson.c53
-rw-r--r--vl.c53
61 files changed, 1146 insertions, 484 deletions
diff --git a/Makefile.objs b/Makefile.objs
index 309d066286..4412757309 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -97,6 +97,12 @@ common-obj-y += qemu-timer.o qemu-timer-common.o
 common-obj-$(CONFIG_SLIRP) += slirp/
 
 ######################################################################
+# libseccomp
+ifeq ($(CONFIG_SECCOMP),y)
+common-obj-y += qemu-seccomp.o
+endif
+
+######################################################################
 # libuser
 
 user-obj-y =
diff --git a/VERSION b/VERSION
index da44c7f348..69658cdda2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.50
+1.1.90
diff --git a/arch_init.c b/arch_init.c
index 9b46bfcaa5..5a1173e29a 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 @@ int xen_available(void)
     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/sheepdog.c b/block/sheepdog.c
index a04ad99ead..df4f44107b 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -485,6 +485,7 @@ static int connect_to_sdog(const char *addr, const char *port)
             if (errno == EINTR) {
                 goto reconnect;
             }
+            close(fd);
             break;
         }
 
diff --git a/configure b/configure
index edf9da44b5..d97fd81709 100755
--- a/configure
+++ b/configure
@@ -218,6 +218,7 @@ zlib="yes"
 guest_agent="yes"
 libiscsi=""
 coroutine=""
+seccomp=""
 
 # parse CC options first
 for opt do
@@ -298,6 +299,41 @@ EOF
   compile_object
 }
 
+if check_define __linux__ ; then
+  targetos="Linux"
+elif check_define _WIN32 ; then
+  targetos='MINGW32'
+elif check_define __OpenBSD__ ; then
+  targetos='OpenBSD'
+elif check_define __sun__ ; then
+  targetos='SunOS'
+elif check_define __HAIKU__ ; then
+  targetos='Haiku'
+else
+  targetos=`uname -s`
+fi
+
+# Some host OSes need non-standard checks for which CPU to use.
+# Note that these checks are broken for cross-compilation: if you're
+# cross-compiling to one of these OSes then you'll need to specify
+# the correct CPU with the --cpu option.
+case $targetos in
+Darwin)
+  # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can
+  # run 64-bit userspace code.
+  # If the user didn't specify a CPU explicitly and the kernel says this is
+  # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code.
+  if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then
+    cpu="x86_64"
+  fi
+  ;;
+SunOS)
+  # `uname -m` returns i86pc even on an x86_64 box, so default based on isainfo
+  if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then
+    cpu="x86_64"
+  fi
+esac
+
 if test ! -z "$cpu" ; then
   # command line argument
   :
@@ -372,19 +408,6 @@ if test -z "$ARCH"; then
 fi
 
 # OS specific
-if check_define __linux__ ; then
-  targetos="Linux"
-elif check_define _WIN32 ; then
-  targetos='MINGW32'
-elif check_define __OpenBSD__ ; then
-  targetos='OpenBSD'
-elif check_define __sun__ ; then
-  targetos='SunOS'
-elif check_define __HAIKU__ ; then
-  targetos='Haiku'
-else
-  targetos=`uname -s`
-fi
 
 case $targetos in
 CYGWIN*)
@@ -434,12 +457,6 @@ OpenBSD)
 Darwin)
   bsd="yes"
   darwin="yes"
-  # on Leopard most of the system is 32-bit, so we have to ask the kernel it if we can
-  # run 64-bit userspace code
-  if [ "$cpu" = "i386" ] ; then
-    is_x86_64=`sysctl -n hw.optional.x86_64`
-    [ "$is_x86_64" = "1" ] && cpu=x86_64
-  fi
   if [ "$cpu" = "x86_64" ] ; then
     QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
     LDFLAGS="-arch x86_64 $LDFLAGS"
@@ -451,6 +468,9 @@ Darwin)
   audio_possible_drivers="coreaudio sdl fmod"
   LDFLAGS="-framework CoreFoundation -framework IOKit $LDFLAGS"
   libs_softmmu="-F/System/Library/Frameworks -framework Cocoa -framework IOKit $libs_softmmu"
+  # Disable attempts to use ObjectiveC features in os/object.h since they
+  # won't work when we're compiling with gcc as a C compiler.
+  QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
 ;;
 SunOS)
   solaris="yes"
@@ -460,12 +480,6 @@ SunOS)
   smbd="${SMBD-/usr/sfw/sbin/smbd}"
   needs_libsunmath="no"
   solarisrev=`uname -r | cut -f2 -d.`
-  # have to select again, because `uname -m` returns i86pc
-  # even on an x86_64 box.
-  solariscpu=`isainfo -k`
-  if test "${solariscpu}" = "amd64" ; then
-    cpu="x86_64"
-  fi
   if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
     if test "$solarisrev" -le 9 ; then
       if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then
@@ -530,6 +544,13 @@ fi
 : ${python=${PYTHON-python}}
 : ${smbd=${SMBD-/usr/sbin/smbd}}
 
+# Default objcc to clang if available, otherwise use CC
+if has clang; then
+  objcc=clang
+else
+  objcc="$cc"
+fi
+
 if test "$mingw32" = "yes" ; then
   EXESUF=".exe"
   QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
@@ -573,6 +594,8 @@ for opt do
   ;;
   --host-cc=*) host_cc="$optarg"
   ;;
+  --objcc=*) objcc="$optarg"
+  ;;
   --make=*) make="$optarg"
   ;;
   --install=*) install="$optarg"
@@ -842,6 +865,10 @@ for opt do
   ;;
   --disable-guest-agent) guest_agent="no"
   ;;
+  --enable-seccomp) seccomp="yes"
+  ;;
+  --disable-seccomp) seccomp="no"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -1015,6 +1042,7 @@ echo "  --cross-prefix=PREFIX    use PREFIX for compile tools [$cross_prefix]"
 echo "  --cc=CC                  use C compiler CC [$cc]"
 echo "  --host-cc=CC             use C compiler CC [$host_cc] for code run at"
 echo "                           build time"
+echo "  --objcc=OBJCC            use Objective-C compiler OBJCC [$objcc]"
 echo "  --extra-cflags=CFLAGS    append extra C compiler flags QEMU_CFLAGS"
 echo "  --extra-ldflags=LDFLAGS  append extra linker flags LDFLAGS"
 echo "  --make=MAKE              use specified make [$make]"
@@ -1129,6 +1157,8 @@ echo "  --disable-usb-redir      disable usb network redirection support"
 echo "  --enable-usb-redir       enable usb network redirection support"
 echo "  --disable-guest-agent    disable building of the QEMU Guest Agent"
 echo "  --enable-guest-agent     enable building of the QEMU Guest Agent"
+echo "  --disable-seccomp        disable seccomp support"
+echo "  --enable-seccomp         enables seccomp support"
 echo "  --with-coroutine=BACKEND coroutine backend. Supported options:"
 echo "                           gthread, ucontext, sigaltstack, windows"
 echo ""
@@ -1391,6 +1421,20 @@ EOF
 fi
 
 ##########################################
+# libseccomp check
+
+if test "$seccomp" != "no" ; then
+    if $pkg_config libseccomp --modversion >/dev/null 2>&1; then
+        LIBS=`$pkg_config --libs libseccomp`
+	seccomp="yes"
+    else
+	seccomp="no"
+	if test "$seccomp" = "yes"; then
+            feature_not_found "libseccomp"
+	fi
+    fi
+fi
+##########################################
 # xen probe
 
 if test "$xen" != "no" ; then
@@ -3045,6 +3089,7 @@ fi
 echo "Source path       $source_path"
 echo "C compiler        $cc"
 echo "Host C compiler   $host_cc"
+echo "Objective-C compiler $objcc"
 echo "CFLAGS            $CFLAGS"
 echo "QEMU_CFLAGS       $QEMU_CFLAGS"
 echo "LDFLAGS           $LDFLAGS"
@@ -3119,6 +3164,7 @@ echo "usb net redir     $usb_redir"
 echo "OpenGL support    $opengl"
 echo "libiscsi support  $libiscsi"
 echo "build guest agent $guest_agent"
+echo "seccomp support   $seccomp"
 echo "coroutine backend $coroutine_backend"
 
 if test "$sdl_too_old" = "yes"; then
@@ -3414,6 +3460,10 @@ if test "$libiscsi" = "yes" ; then
   echo "CONFIG_LIBISCSI=y" >> $config_host_mak
 fi
 
+if test "$seccomp" = "yes"; then
+  echo "CONFIG_SECCOMP=y" >> $config_host_mak
+fi
+
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
   echo "CONFIG_BSD=y" >> $config_host_mak
@@ -3508,6 +3558,7 @@ echo "PYTHON=$python" >> $config_host_mak
 echo "CC=$cc" >> $config_host_mak
 echo "CC_I386=$cc_i386" >> $config_host_mak
 echo "HOST_CC=$host_cc" >> $config_host_mak
+echo "OBJCC=$objcc" >> $config_host_mak
 echo "AR=$ar" >> $config_host_mak
 echo "OBJCOPY=$objcopy" >> $config_host_mak
 echo "LD=$ld" >> $config_host_mak
@@ -3783,14 +3834,19 @@ case "$target_arch2" in
   ;;
 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
@@ -3881,6 +3937,11 @@ if test "$target_bsd_user" = "yes" ; then
   echo "CONFIG_BSD_USER=y" >> $config_target_mak
 fi
 
+# the static way of configuring available audio cards requires this workaround
+if test "$target_user_only" != "yes" && grep -q CONFIG_PCSPK $source_path/default-configs/$target.mak; then
+  echo "CONFIG_PCSPK=y" >> $config_target_mak
+fi
+
 # generate QEMU_CFLAGS/LDFLAGS for targets
 
 cflags=""
diff --git a/dma-helpers.c b/dma-helpers.c
index 13593d1b42..433d8b21b3 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -24,8 +24,8 @@ static void do_dma_memory_set(dma_addr_t addr, uint8_t c, dma_addr_t len)
     while (len > 0) {
         l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
         cpu_physical_memory_rw(addr, fillbuf, l, true);
-        len -= len;
-        addr += len;
+        len -= l;
+        addr += l;
     }
 }
 
diff --git a/exec.c b/exec.c
index 929db5cf0a..58347664b2 100644
--- a/exec.c
+++ b/exec.c
@@ -2475,6 +2475,24 @@ static ram_addr_t last_ram_offset(void)
     return last;
 }
 
+static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
+{
+    int ret;
+    QemuOpts *machine_opts;
+
+    /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts &&
+        !qemu_opt_get_bool(machine_opts, "dump-guest-core", true)) {
+        ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP);
+        if (ret) {
+            perror("qemu_madvise");
+            fprintf(stderr, "madvise doesn't support MADV_DONTDUMP, "
+                            "but dump_guest_core=off specified\n");
+        }
+    }
+}
+
 void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
 {
     RAMBlock *new_block, *block;
@@ -2554,6 +2572,8 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
            0, size >> TARGET_PAGE_BITS);
     cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff);
 
+    qemu_ram_setup_dump(new_block->host, size);
+
     if (kvm_enabled())
         kvm_setup_guest_memory(new_block->host, size);
 
@@ -2670,6 +2690,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
                     exit(1);
                 }
                 qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
+                qemu_ram_setup_dump(vaddr, length);
             }
             return;
         }
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 872e1122e8..b7cf4e2900 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 @@ typedef struct TyphoonPchip {
     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 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
     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 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
     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 @@ static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)
     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/boards.h b/hw/boards.h
index 59c01d0367..a2e0a54497 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -12,11 +12,14 @@ typedef void QEMUMachineInitFunc(ram_addr_t ram_size,
                                  const char *initrd_filename,
                                  const char *cpu_model);
 
+typedef void QEMUMachineResetFunc(void);
+
 typedef struct QEMUMachine {
     const char *name;
     const char *alias;
     const char *desc;
     QEMUMachineInitFunc *init;
+    QEMUMachineResetFunc *reset;
     int use_scsi;
     int max_cpus;
     unsigned int no_serial:1,
diff --git a/hw/bonito.c b/hw/bonito.c
index 77786f8883..6084ac48fa 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 @@ typedef struct PCIBonitoState
 
 } 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 @@ static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr,
                                   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 @@ static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr,
 {
 
     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 const MemoryRegionOps bonito_cop_ops = {
 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 @@ static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr)
     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 @@ static void bonito_spciconf_writeb(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;
 
@@ -449,24 +466,26 @@ static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr,
     }
 
     /* 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 @@ static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr,
     }
 
     /* 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 @@ static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr,
     }
 
     /* 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 @@ static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr)
     }
 
     /* 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 @@ static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr)
     }
 
     /* 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 @@ static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr)
     }
 
     /* 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 const MemoryRegionOps bonito_spciconf_ops = {
 
 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 const VMStateDescription vmstate_bonito = {
 
 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 @@ static int bonito_initfn(PCIDevice *dev)
     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 @@ static int bonito_initfn(PCIDevice *dev)
 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 @@ static void bonito_class_init(ObjectClass *klass, void *data)
     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 @@ static void bonito_pcihost_class_init(ObjectClass *klass, void *data)
     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 37337bf4b6..c30ade38bd 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 @@ static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
     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 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
 
 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 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
     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 @@ static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data)
     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 79264bac84..17dc0c2b0a 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 81ff3a339a..67da307284 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 @@ static void pci_grackle_set_irq(void *opaque, int irq_num, int level)
     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 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
     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 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data)
     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 @@ static void pci_grackle_class_init(ObjectClass *klass, void *data)
     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 a2d0e5a2c3..e95e664833 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 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
                             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 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
         /* 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 @@ static uint64_t gt64120_readl (void *opaque,
                                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 @@ static uint64_t gt64120_readl (void *opaque,
 
     /* 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 @@ static void gt64120_reset(void *opaque)
 
 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 @@ static void gt64120_pci_class_init(ObjectClass *klass, void *data)
     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 @@ static void gt64120_class_init(ObjectClass *klass, void *data)
     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 9b11d907eb..2123c142aa 100644
--- a/hw/i82378.c
+++ b/hw/i82378.c
@@ -225,7 +225,6 @@ static int pci_i82378_init(PCIDevice *dev)
     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/msix.c b/hw/msix.c
index 800fc32f0b..aea340b7c7 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -307,13 +307,9 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
         return -EINVAL;
     }
 
-    if (asprintf(&name, "%s-msix", dev->name) == -1) {
-        return -ENOMEM;
-    }
-
+    name = g_strdup_printf("%s-msix", dev->name);
     memory_region_init(&dev->msix_exclusive_bar, name, MSIX_EXCLUSIVE_BAR_SIZE);
-
-    free(name);
+    g_free(name);
 
     ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
                     MSIX_EXCLUSIVE_BAR_TABLE_OFFSET, &dev->msix_exclusive_bar,
diff --git a/hw/pc.c b/hw/pc.c
index 3ed1a3caa2..112739a278 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -338,32 +338,37 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     /* various important CMOS locations needed by PC/Bochs bios */
 
     /* memory size */
-    val = 640; /* base memory in K */
+    /* base memory (first MiB) */
+    val = MIN(ram_size / 1024, 640);
     rtc_set_memory(s, 0x15, val);
     rtc_set_memory(s, 0x16, val >> 8);
-
-    val = (ram_size / 1024) - 1024;
+    /* extended memory (next 64MiB) */
+    if (ram_size > 1024 * 1024) {
+        val = (ram_size - 1024 * 1024) / 1024;
+    } else {
+        val = 0;
+    }
     if (val > 65535)
         val = 65535;
     rtc_set_memory(s, 0x17, val);
     rtc_set_memory(s, 0x18, val >> 8);
     rtc_set_memory(s, 0x30, val);
     rtc_set_memory(s, 0x31, val >> 8);
-
-    if (above_4g_mem_size) {
-        rtc_set_memory(s, 0x5b, (unsigned int)above_4g_mem_size >> 16);
-        rtc_set_memory(s, 0x5c, (unsigned int)above_4g_mem_size >> 24);
-        rtc_set_memory(s, 0x5d, (uint64_t)above_4g_mem_size >> 32);
-    }
-
-    if (ram_size > (16 * 1024 * 1024))
-        val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
-    else
+    /* memory between 16MiB and 4GiB */
+    if (ram_size > 16 * 1024 * 1024) {
+        val = (ram_size - 16 * 1024 * 1024) / 65536;
+    } else {
         val = 0;
+    }
     if (val > 65535)
         val = 65535;
     rtc_set_memory(s, 0x34, val);
     rtc_set_memory(s, 0x35, val >> 8);
+    /* memory above 4GiB */
+    val = above_4g_mem_size / 65536;
+    rtc_set_memory(s, 0x5b, val);
+    rtc_set_memory(s, 0x5c, val >> 8);
+    rtc_set_memory(s, 0x5d, val >> 16);
 
     /* set the number of CPU */
     rtc_set_memory(s, 0x5f, smp_cpus - 1);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 0c0096fd7e..d68dbb2320 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -375,6 +375,10 @@ static QEMUMachine pc_machine_v1_2 = {
             .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 804177891a..3950e943c0 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -165,4 +165,16 @@ const MemoryRegionOps pci_host_data_be_ops = {
     .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 359e38f63b..4b9c300fcf 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 c497a014af..537fc1973c 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 const VMStateDescription vmstate_i440fx = {
 
 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 @@ static PCIBus *i440fx_common_init(const char *device_name,
     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 @@ static void piix3_class_init(ObjectClass *klass, void *data)
     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 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data)
     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 @@ static void i440fx_class_init(ObjectClass *klass, void *data)
     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 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
     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 0dd4dab318..c198071170 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -216,7 +216,8 @@ static void bamboo_init(ram_addr_t ram_size,
                       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 b511020aeb..5cd78b6291 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -53,6 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
                         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 203c3cdc47..a14fd426c1 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -45,11 +45,14 @@ struct PCITargetMap {
     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 @@ static uint64_t pci4xx_cfgaddr_read(void *opaque, target_phys_addr_t addr,
                                     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 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
     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 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data)
     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 @@ static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data)
     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 af75e45cc2..7d084184fc 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -55,6 +55,7 @@ qemu_irq *heathrow_pic_init(MemoryRegion **pmem,
                             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 7a876164c9..592b7b255f 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -471,7 +471,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
     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 @@ static void ppc_prep_init (ram_addr_t ram_size,
     }
 
     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 0f60b24134..92b1dc0534 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -72,8 +72,14 @@ struct pci_inbound {
     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 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
     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 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
     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 @@ static void e500_pcihost_class_init(ObjectClass *klass, void *data)
     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 38dbff44a1..cc44e61987 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 @@ static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr)
 {
     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 @@ static void ppc_pci_io_write(void *opaque, target_phys_addr_t addr,
                              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 void prep_set_irq(void *opaque, int irq_num, int level)
 
 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 @@ static int raven_pcihost_init(SysBusDevice *dev)
         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 @@ static void raven_class_init(ObjectClass *klass, void *data)
     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 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data)
     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/scsi-bus.c b/hw/scsi-bus.c
index b8a857d145..4981a02436 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -761,6 +761,7 @@ static int ata_passthrough_12_xfer_size(SCSIDevice *dev, uint8_t *buf)
     switch (length) {
     case 0:
     case 3: /* USB-specific.  */
+    default:
         xfer = 0;
         break;
     case 1:
@@ -784,6 +785,7 @@ static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf)
     switch (length) {
     case 0:
     case 3: /* USB-specific.  */
+    default:
         xfer = 0;
         break;
     case 1:
diff --git a/hw/spapr.c b/hw/spapr.c
index 5178721d49..c34b767c6e 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -49,6 +49,7 @@
 #include "vga-pci.h"
 
 #include "exec-memory.h"
+#include "hw/usb.h"
 
 #include <libfdt.h>
 
@@ -611,6 +612,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 {
     PowerPCCPU *cpu;
     CPUPPCState *env;
+    PCIHostState *phb;
     int i;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -741,6 +743,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
                      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];
@@ -761,10 +764,18 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     }
 
     /* 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(phb->bus, -1, "pci-ohci");
+        if (spapr->has_graphics) {
+            usbdevice_create("keyboard");
+            usbdevice_create("mouse");
+        }
+    }
+
     if (rma_size < (MIN_RMA_SLOF << 20)) {
         fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
                 "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index b92583a991..661c05bc30 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 sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
 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 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid,
         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 DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque,
 
 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 @@ static int spapr_phb_init(SysBusDevice *s)
      * 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 @@ static int spapr_phb_init(SysBusDevice *s)
             return -1;
         }
 
-        phb->lsi_table[i].irq = irq;
+        sphb->lsi_table[i].irq = irq;
     }
 
     return 0;
@@ -612,9 +615,9 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
     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 @@ void spapr_create_phb(sPAPREnvironment *spapr,
 {
     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 @@ void spapr_pci_rtas_init(void)
     }
 }
 
-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 7518899b85..670dc62a19 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 409bcd4cc6..d1cc68062b 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 @@ static void unin_data_write(void *opaque, target_phys_addr_t addr,
                             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 @@ static uint64_t unin_data_read(void *opaque, target_phys_addr_t addr,
                                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 const MemoryRegionOps unin_data_ops = {
 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_unin_main_init_device(SysBusDevice *dev)
 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_u3_agp_init_device(SysBusDevice *dev)
 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);
-
-    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);
+    h = PCI_HOST_BRIDGE(dev);
+
+    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);
-
-    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);
+    h = PCI_HOST_BRIDGE(dev);
+
+    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 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
 
     /* 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 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
     /* 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 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
 
     /* 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 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
     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 @@ static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
     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 @@ static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
     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 @@ static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
     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 @@ static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
     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 @@ static void pci_unin_main_class_init(ObjectClass *klass, void *data)
     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 @@ static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
     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 @@ static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
     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 @@ static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
     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/virtio-blk.c b/hw/virtio-blk.c
index fd8fa90792..6f6d172fd0 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -533,7 +533,6 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
     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 35834cf493..651a000b9f 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -107,6 +107,7 @@ struct VirtIOBlkConf
 };
 
 #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/iohandler.c b/iohandler.c
index 3c74de612b..dea43552d2 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -77,6 +77,7 @@ int qemu_set_fd_handler2(int fd,
         ioh->fd_write = fd_write;
         ioh->opaque = opaque;
         ioh->deleted = 0;
+        qemu_notify_event();
     }
     return 0;
 }
diff --git a/json-parser.c b/json-parser.c
index 849e2156da..457291b161 100644
--- a/json-parser.c
+++ b/json-parser.c
@@ -27,6 +27,11 @@
 typedef struct JSONParserContext
 {
     Error *err;
+    struct {
+        QObject **buf;
+        size_t pos;
+        size_t count;
+    } tokens;
 } JSONParserContext;
 
 #define BUG_ON(cond) assert(!(cond))
@@ -40,7 +45,7 @@ typedef struct JSONParserContext
  * 4) deal with premature EOI
  */
 
-static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap);
+static QObject *parse_value(JSONParserContext *ctxt, va_list *ap);
 
 /**
  * Token manipulators
@@ -270,27 +275,111 @@ out:
     return NULL;
 }
 
+static QObject *parser_context_pop_token(JSONParserContext *ctxt)
+{
+    QObject *token;
+    g_assert(ctxt->tokens.pos < ctxt->tokens.count);
+    token = ctxt->tokens.buf[ctxt->tokens.pos];
+    ctxt->tokens.pos++;
+    return token;
+}
+
+/* Note: parser_context_{peek|pop}_token do not increment the
+ * token object's refcount. In both cases the references will continue
+ * to be tracked and cleaned up in parser_context_free(), so do not
+ * attempt to free the token object.
+ */
+static QObject *parser_context_peek_token(JSONParserContext *ctxt)
+{
+    QObject *token;
+    g_assert(ctxt->tokens.pos < ctxt->tokens.count);
+    token = ctxt->tokens.buf[ctxt->tokens.pos];
+    return token;
+}
+
+static JSONParserContext parser_context_save(JSONParserContext *ctxt)
+{
+    JSONParserContext saved_ctxt = {0};
+    saved_ctxt.tokens.pos = ctxt->tokens.pos;
+    saved_ctxt.tokens.count = ctxt->tokens.count;
+    saved_ctxt.tokens.buf = ctxt->tokens.buf;
+    return saved_ctxt;
+}
+
+static void parser_context_restore(JSONParserContext *ctxt,
+                                   JSONParserContext saved_ctxt)
+{
+    ctxt->tokens.pos = saved_ctxt.tokens.pos;
+    ctxt->tokens.count = saved_ctxt.tokens.count;
+    ctxt->tokens.buf = saved_ctxt.tokens.buf;
+}
+
+static void tokens_append_from_iter(QObject *obj, void *opaque)
+{
+    JSONParserContext *ctxt = opaque;
+    g_assert(ctxt->tokens.pos < ctxt->tokens.count);
+    ctxt->tokens.buf[ctxt->tokens.pos++] = obj;
+    qobject_incref(obj);
+}
+
+static JSONParserContext *parser_context_new(QList *tokens)
+{
+    JSONParserContext *ctxt;
+    size_t count;
+
+    if (!tokens) {
+        return NULL;
+    }
+
+    count = qlist_size(tokens);
+    if (count == 0) {
+        return NULL;
+    }
+
+    ctxt = g_malloc0(sizeof(JSONParserContext));
+    ctxt->tokens.pos = 0;
+    ctxt->tokens.count = count;
+    ctxt->tokens.buf = g_malloc(count * sizeof(QObject *));
+    qlist_iter(tokens, tokens_append_from_iter, ctxt);
+    ctxt->tokens.pos = 0;
+
+    return ctxt;
+}
+
+/* to support error propagation, ctxt->err must be freed separately */
+static void parser_context_free(JSONParserContext *ctxt)
+{
+    int i;
+    if (ctxt) {
+        for (i = 0; i < ctxt->tokens.count; i++) {
+            qobject_decref(ctxt->tokens.buf[i]);
+        }
+        g_free(ctxt->tokens.buf);
+        g_free(ctxt);
+    }
+}
+
 /**
  * Parsing rules
  */
-static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_list *ap)
+static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
 {
     QObject *key = NULL, *token = NULL, *value, *peek;
-    QList *working = qlist_copy(*tokens);
+    JSONParserContext saved_ctxt = parser_context_save(ctxt);
 
-    peek = qlist_peek(working);
+    peek = parser_context_peek_token(ctxt);
     if (peek == NULL) {
         parse_error(ctxt, NULL, "premature EOI");
         goto out;
     }
 
-    key = parse_value(ctxt, &working, ap);
+    key = parse_value(ctxt, ap);
     if (!key || qobject_type(key) != QTYPE_QSTRING) {
         parse_error(ctxt, peek, "key is not a string in object");
         goto out;
     }
 
-    token = qlist_pop(working);
+    token = parser_context_pop_token(ctxt);
     if (token == NULL) {
         parse_error(ctxt, NULL, "premature EOI");
         goto out;
@@ -301,7 +390,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l
         goto out;
     }
 
-    value = parse_value(ctxt, &working, ap);
+    value = parse_value(ctxt, ap);
     if (value == NULL) {
         parse_error(ctxt, token, "Missing value in dict");
         goto out;
@@ -309,28 +398,24 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l
 
     qdict_put_obj(dict, qstring_get_str(qobject_to_qstring(key)), value);
 
-    qobject_decref(token);
     qobject_decref(key);
-    QDECREF(*tokens);
-    *tokens = working;
 
     return 0;
 
 out:
-    qobject_decref(token);
+    parser_context_restore(ctxt, saved_ctxt);
     qobject_decref(key);
-    QDECREF(working);
 
     return -1;
 }
 
-static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *ap)
+static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
 {
     QDict *dict = NULL;
     QObject *token, *peek;
-    QList *working = qlist_copy(*tokens);
+    JSONParserContext saved_ctxt = parser_context_save(ctxt);
 
-    token = qlist_pop(working);
+    token = parser_context_pop_token(ctxt);
     if (token == NULL) {
         goto out;
     }
@@ -338,23 +423,22 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a
     if (!token_is_operator(token, '{')) {
         goto out;
     }
-    qobject_decref(token);
     token = NULL;
 
     dict = qdict_new();
 
-    peek = qlist_peek(working);
+    peek = parser_context_peek_token(ctxt);
     if (peek == NULL) {
         parse_error(ctxt, NULL, "premature EOI");
         goto out;
     }
 
     if (!token_is_operator(peek, '}')) {
-        if (parse_pair(ctxt, dict, &working, ap) == -1) {
+        if (parse_pair(ctxt, dict, ap) == -1) {
             goto out;
         }
 
-        token = qlist_pop(working);
+        token = parser_context_pop_token(ctxt);
         if (token == NULL) {
             parse_error(ctxt, NULL, "premature EOI");
             goto out;
@@ -365,59 +449,52 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a
                 parse_error(ctxt, token, "expected separator in dict");
                 goto out;
             }
-            qobject_decref(token);
             token = NULL;
 
-            if (parse_pair(ctxt, dict, &working, ap) == -1) {
+            if (parse_pair(ctxt, dict, ap) == -1) {
                 goto out;
             }
 
-            token = qlist_pop(working);
+            token = parser_context_pop_token(ctxt);
             if (token == NULL) {
                 parse_error(ctxt, NULL, "premature EOI");
                 goto out;
             }
         }
-        qobject_decref(token);
         token = NULL;
     } else {
-        token = qlist_pop(working);
-        qobject_decref(token);
+        token = parser_context_pop_token(ctxt);
         token = NULL;
     }
 
-    QDECREF(*tokens);
-    *tokens = working;
-
     return QOBJECT(dict);
 
 out:
-    qobject_decref(token);
-    QDECREF(working);
+    parser_context_restore(ctxt, saved_ctxt);
     QDECREF(dict);
     return NULL;
 }
 
-static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap)
+static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
 {
     QList *list = NULL;
     QObject *token, *peek;
-    QList *working = qlist_copy(*tokens);
+    JSONParserContext saved_ctxt = parser_context_save(ctxt);
 
-    token = qlist_pop(working);
+    token = parser_context_pop_token(ctxt);
     if (token == NULL) {
         goto out;
     }
 
     if (!token_is_operator(token, '[')) {
+        token = NULL;
         goto out;
     }
-    qobject_decref(token);
     token = NULL;
 
     list = qlist_new();
 
-    peek = qlist_peek(working);
+    peek = parser_context_peek_token(ctxt);
     if (peek == NULL) {
         parse_error(ctxt, NULL, "premature EOI");
         goto out;
@@ -426,7 +503,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
     if (!token_is_operator(peek, ']')) {
         QObject *obj;
 
-        obj = parse_value(ctxt, &working, ap);
+        obj = parse_value(ctxt, ap);
         if (obj == NULL) {
             parse_error(ctxt, token, "expecting value");
             goto out;
@@ -434,7 +511,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
 
         qlist_append_obj(list, obj);
 
-        token = qlist_pop(working);
+        token = parser_context_pop_token(ctxt);
         if (token == NULL) {
             parse_error(ctxt, NULL, "premature EOI");
             goto out;
@@ -446,10 +523,9 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
                 goto out;
             }
 
-            qobject_decref(token);
             token = NULL;
 
-            obj = parse_value(ctxt, &working, ap);
+            obj = parse_value(ctxt, ap);
             if (obj == NULL) {
                 parse_error(ctxt, token, "expecting value");
                 goto out;
@@ -457,39 +533,33 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
 
             qlist_append_obj(list, obj);
 
-            token = qlist_pop(working);
+            token = parser_context_pop_token(ctxt);
             if (token == NULL) {
                 parse_error(ctxt, NULL, "premature EOI");
                 goto out;
             }
         }
 
-        qobject_decref(token);
         token = NULL;
     } else {
-        token = qlist_pop(working);
-        qobject_decref(token);
+        token = parser_context_pop_token(ctxt);
         token = NULL;
     }
 
-    QDECREF(*tokens);
-    *tokens = working;
-
     return QOBJECT(list);
 
 out:
-    qobject_decref(token);
-    QDECREF(working);
+    parser_context_restore(ctxt, saved_ctxt);
     QDECREF(list);
     return NULL;
 }
 
-static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens)
+static QObject *parse_keyword(JSONParserContext *ctxt)
 {
     QObject *token, *ret;
-    QList *working = qlist_copy(*tokens);
+    JSONParserContext saved_ctxt = parser_context_save(ctxt);
 
-    token = qlist_pop(working);
+    token = parser_context_pop_token(ctxt);
     if (token == NULL) {
         goto out;
     }
@@ -507,29 +577,24 @@ static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens)
         goto out;
     }
 
-    qobject_decref(token);
-    QDECREF(*tokens);
-    *tokens = working;
-
     return ret;
 
 out: 
-    qobject_decref(token);
-    QDECREF(working);
+    parser_context_restore(ctxt, saved_ctxt);
 
     return NULL;
 }
 
-static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *ap)
+static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
 {
     QObject *token = NULL, *obj;
-    QList *working = qlist_copy(*tokens);
+    JSONParserContext saved_ctxt = parser_context_save(ctxt);
 
     if (ap == NULL) {
         goto out;
     }
 
-    token = qlist_pop(working);
+    token = parser_context_pop_token(ctxt);
     if (token == NULL) {
         goto out;
     }
@@ -553,25 +618,20 @@ static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *a
         goto out;
     }
 
-    qobject_decref(token);
-    QDECREF(*tokens);
-    *tokens = working;
-
     return obj;
 
 out:
-    qobject_decref(token);
-    QDECREF(working);
+    parser_context_restore(ctxt, saved_ctxt);
 
     return NULL;
 }
 
-static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens)
+static QObject *parse_literal(JSONParserContext *ctxt)
 {
     QObject *token, *obj;
-    QList *working = qlist_copy(*tokens);
+    JSONParserContext saved_ctxt = parser_context_save(ctxt);
 
-    token = qlist_pop(working);
+    token = parser_context_pop_token(ctxt);
     if (token == NULL) {
         goto out;
     }
@@ -591,35 +651,30 @@ static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens)
         goto out;
     }
 
-    qobject_decref(token);
-    QDECREF(*tokens);
-    *tokens = working;
-
     return obj;
 
 out:
-    qobject_decref(token);
-    QDECREF(working);
+    parser_context_restore(ctxt, saved_ctxt);
 
     return NULL;
 }
 
-static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap)
+static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
 {
     QObject *obj;
 
-    obj = parse_object(ctxt, tokens, ap);
+    obj = parse_object(ctxt, ap);
     if (obj == NULL) {
-        obj = parse_array(ctxt, tokens, ap);
+        obj = parse_array(ctxt, ap);
     }
     if (obj == NULL) {
-        obj = parse_escape(ctxt, tokens, ap);
+        obj = parse_escape(ctxt, ap);
     }
     if (obj == NULL) {
-        obj = parse_keyword(ctxt, tokens);
+        obj = parse_keyword(ctxt);
     } 
     if (obj == NULL) {
-        obj = parse_literal(ctxt, tokens);
+        obj = parse_literal(ctxt);
     }
 
     return obj;
@@ -632,19 +687,18 @@ QObject *json_parser_parse(QList *tokens, va_list *ap)
 
 QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp)
 {
-    JSONParserContext ctxt = {};
-    QList *working;
+    JSONParserContext *ctxt = parser_context_new(tokens);
     QObject *result;
 
-    if (!tokens) {
+    if (!ctxt) {
         return NULL;
     }
-    working = qlist_copy(tokens);
-    result = parse_value(&ctxt, &working, ap);
 
-    QDECREF(working);
+    result = parse_value(ctxt, ap);
+
+    error_propagate(errp, ctxt->err);
 
-    error_propagate(errp, ctxt.err);
+    parser_context_free(ctxt);
 
     return result;
 }
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 41c869bfe0..11743065e9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2848,7 +2848,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
     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 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
     }
 
     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/osdep.c b/osdep.c
index 5b78ceebef..3b25297a25 100644
--- a/osdep.c
+++ b/osdep.c
@@ -113,7 +113,13 @@ static int qemu_dup_flags(int fd, int flags)
     }
 
     /* Set/unset flags that we can with fcntl */
-    setfl_flags = O_APPEND | O_ASYNC | O_DIRECT | O_NOATIME | O_NONBLOCK;
+    setfl_flags = O_APPEND | O_ASYNC | O_NONBLOCK;
+#ifdef O_NOATIME
+    setfl_flags |= O_NOATIME;
+#endif
+#ifdef O_DIRECT
+    setfl_flags |= O_DIRECT;
+#endif
     dup_flags &= ~setfl_flags;
     dup_flags |= (flags & setfl_flags);
     if (fcntl(ret, F_SETFL, dup_flags) == -1) {
diff --git a/osdep.h b/osdep.h
index d4b887d542..cb213e0295 100644
--- a/osdep.h
+++ b/osdep.h
@@ -103,6 +103,11 @@ void qemu_vfree(void *ptr);
 #else
 #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
 #endif
+#ifdef MADV_DONTDUMP
+#define QEMU_MADV_DONTDUMP MADV_DONTDUMP
+#else
+#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
+#endif
 
 #elif defined(CONFIG_POSIX_MADVISE)
 
@@ -110,6 +115,7 @@ void qemu_vfree(void *ptr);
 #define QEMU_MADV_DONTNEED  POSIX_MADV_DONTNEED
 #define QEMU_MADV_DONTFORK  QEMU_MADV_INVALID
 #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
+#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
 
 #else /* no-op */
 
@@ -117,6 +123,7 @@ void qemu_vfree(void *ptr);
 #define QEMU_MADV_DONTNEED  QEMU_MADV_INVALID
 #define QEMU_MADV_DONTFORK  QEMU_MADV_INVALID
 #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
+#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
 
 #endif
 
diff --git a/pc-bios/README b/pc-bios/README
index f4b37d66dc..fc07ebc21c 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -12,7 +12,7 @@
   1275-1994 (referred to as Open Firmware) compliant firmware.
   The included images for PowerPC (for 32 and 64 bit PPC CPUs),
   Sparc32 and Sparc64 are built from OpenBIOS SVN revision
-  1060.
+  1062.
 
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index aeae265880..1c3753d3eb 100644
--- a/pc-bios/openbios-ppc
+++ b/pc-bios/openbios-ppc
Binary files differdiff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index d90c4e59a0..6bd8e45d86 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differdiff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index 457d264228..7c06fcc5aa 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differdiff --git a/qapi-schema.json b/qapi-schema.json
index 3d2b2d175a..72b3c4d5bd 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-char.c b/qemu-char.c
index 10d1504948..398baf1e04 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2141,14 +2141,17 @@ typedef struct {
 
 static void tcp_chr_accept(void *opaque);
 
+static void tcp_chr_connect(void *opaque);
+
 static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     TCPCharDriver *s = chr->opaque;
     if (s->connected) {
         return send_all(s->fd, buf, len);
     } else {
-        /* XXX: indicate an error ? */
-        return len;
+        /* (Re-)connect for unconnected writing */
+        tcp_chr_connect(chr);
+        return 0;
     }
 }
 
diff --git a/qemu-config.c b/qemu-config.c
index 5c3296b8c6..c05ffbc444 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -362,6 +362,19 @@ static QemuOptsList qemu_global_opts = {
     },
 };
 
+QemuOptsList qemu_sandbox_opts = {
+    .name = "sandbox",
+    .implied_opt_name = "enable",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_sandbox_opts.head),
+    .desc = {
+        {
+            .name = "enable",
+            .type = QEMU_OPT_BOOL,
+        },
+        { /* end of list */ }
+    },
+};
+
 static QemuOptsList qemu_mon_opts = {
     .name = "mon",
     .implied_opt_name = "chardev",
@@ -595,6 +608,10 @@ static QemuOptsList qemu_machine_opts = {
             .name = "dt_compatible",
             .type = QEMU_OPT_STRING,
             .help = "Overrides the \"compatible\" property of the dt root node",
+        }, {
+            .name = "dump-guest-core",
+            .type = QEMU_OPT_BOOL,
+            .help = "Include guest memory in  a core dump",
         },
         { /* End of list */ }
     },
@@ -641,6 +658,7 @@ static QemuOptsList *vm_config_groups[32] = {
     &qemu_machine_opts,
     &qemu_boot_opts,
     &qemu_iscsi_opts,
+    &qemu_sandbox_opts,
     NULL,
 };
 
diff --git a/qemu-config.h b/qemu-config.h
index 12ddf3ed97..5557562c33 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -6,6 +6,7 @@
 extern QemuOptsList qemu_fsdev_opts;
 extern QemuOptsList qemu_virtfs_opts;
 extern QemuOptsList qemu_spice_opts;
+extern QemuOptsList qemu_sandbox_opts;
 
 QemuOptsList *qemu_find_opts(const char *group);
 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
diff --git a/qemu-ga.c b/qemu-ga.c
index 8f87621ae4..26671fee3f 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -247,6 +247,9 @@ static bool ga_open_pidfile(const char *pidfile)
     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-options.hx b/qemu-options.hx
index 47cb5bd311..3c411c427e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -37,7 +37,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
     "                property accel=accel1[:accel2[:...]] selects accelerator\n"
     "                supported accelerators are kvm, xen, tcg (default: tcg)\n"
     "                kernel_irqchip=on|off controls accelerated irqchip support\n"
-    "                kvm_shadow_mem=size of KVM shadow MMU\n",
+    "                kvm_shadow_mem=size of KVM shadow MMU\n"
+    "                dump-guest-core=on|off include guest memory in a core dump (default=on)\n",
     QEMU_ARCH_ALL)
 STEXI
 @item -machine [type=]@var{name}[,prop=@var{value}[,...]]
@@ -54,6 +55,8 @@ to initialize.
 Enables in-kernel irqchip support for the chosen accelerator when available.
 @item kvm_shadow_mem=size
 Defines the size of the KVM shadow MMU.
+@item dump-guest-core=on|off
+Include guest memory in a core dump. The default is on.
 @end table
 ETEXI
 
@@ -2720,6 +2723,16 @@ STEXI
 Old param mode (ARM only).
 ETEXI
 
+DEF("sandbox", HAS_ARG, QEMU_OPTION_sandbox, \
+    "-sandbox <arg>  Enable seccomp mode 2 system call filter (default 'off').\n",
+    QEMU_ARCH_ALL)
+STEXI
+@item -sandbox
+@findex -sandbox
+Enable Seccomp mode 2 system call filter. 'on' will enable syscall filtering and 'off' will
+disable it.  The default is 'off'.
+ETEXI
+
 DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig,
     "-readconfig <file>\n", QEMU_ARCH_ALL)
 STEXI
diff --git a/qemu-seccomp.c b/qemu-seccomp.c
new file mode 100644
index 0000000000..64329a3c09
--- /dev/null
+++ b/qemu-seccomp.c
@@ -0,0 +1,141 @@
+/*
+ * QEMU seccomp mode 2 support with libseccomp
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Eduardo Otubo    <eotubo@br.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include <stdio.h>
+#include <seccomp.h>
+#include "qemu-seccomp.h"
+
+struct QemuSeccompSyscall {
+    int32_t num;
+    uint8_t priority;
+};
+
+static const struct QemuSeccompSyscall seccomp_whitelist[] = {
+    { SCMP_SYS(timer_settime), 255 },
+    { SCMP_SYS(timer_gettime), 254 },
+    { SCMP_SYS(futex), 253 },
+    { SCMP_SYS(select), 252 },
+    { SCMP_SYS(recvfrom), 251 },
+    { SCMP_SYS(sendto), 250 },
+    { SCMP_SYS(read), 249 },
+    { SCMP_SYS(brk), 248 },
+    { SCMP_SYS(clone), 247 },
+    { SCMP_SYS(mmap), 247 },
+    { SCMP_SYS(mprotect), 246 },
+    { SCMP_SYS(execve), 245 },
+    { SCMP_SYS(open), 245 },
+    { SCMP_SYS(ioctl), 245 },
+    { SCMP_SYS(recvmsg), 245 },
+    { SCMP_SYS(sendmsg), 245 },
+    { SCMP_SYS(accept), 245 },
+    { SCMP_SYS(connect), 245 },
+    { SCMP_SYS(gettimeofday), 245 },
+    { SCMP_SYS(readlink), 245 },
+    { SCMP_SYS(access), 245 },
+    { SCMP_SYS(prctl), 245 },
+    { SCMP_SYS(signalfd), 245 },
+#if defined(__i386__)
+    { SCMP_SYS(fcntl64), 245 },
+    { SCMP_SYS(fstat64), 245 },
+    { SCMP_SYS(stat64), 245 },
+    { SCMP_SYS(getgid32), 245 },
+    { SCMP_SYS(getegid32), 245 },
+    { SCMP_SYS(getuid32), 245 },
+    { SCMP_SYS(geteuid32), 245 },
+    { SCMP_SYS(sigreturn), 245 },
+    { SCMP_SYS(_newselect), 245 },
+    { SCMP_SYS(_llseek), 245 },
+    { SCMP_SYS(mmap2), 245},
+    { SCMP_SYS(sigprocmask), 245 },
+#elif defined(__x86_64__)
+    { SCMP_SYS(sched_getparam), 245},
+    { SCMP_SYS(sched_getscheduler), 245},
+    { SCMP_SYS(fstat), 245},
+    { SCMP_SYS(clock_getres), 245},
+    { SCMP_SYS(sched_get_priority_min), 245},
+    { SCMP_SYS(sched_get_priority_max), 245},
+    { SCMP_SYS(stat), 245},
+    { SCMP_SYS(socket), 245},
+    { SCMP_SYS(setsockopt), 245},
+    { SCMP_SYS(uname), 245},
+    { SCMP_SYS(semget), 245},
+#endif
+    { SCMP_SYS(eventfd2), 245 },
+    { SCMP_SYS(dup), 245 },
+    { SCMP_SYS(gettid), 245 },
+    { SCMP_SYS(timer_create), 245 },
+    { SCMP_SYS(exit), 245 },
+    { SCMP_SYS(clock_gettime), 245 },
+    { SCMP_SYS(time), 245 },
+    { SCMP_SYS(restart_syscall), 245 },
+    { SCMP_SYS(pwrite64), 245 },
+    { SCMP_SYS(chown), 245 },
+    { SCMP_SYS(openat), 245 },
+    { SCMP_SYS(getdents), 245 },
+    { SCMP_SYS(timer_delete), 245 },
+    { SCMP_SYS(exit_group), 245 },
+    { SCMP_SYS(rt_sigreturn), 245 },
+    { SCMP_SYS(sync), 245 },
+    { SCMP_SYS(pread64), 245 },
+    { SCMP_SYS(madvise), 245 },
+    { SCMP_SYS(set_robust_list), 245 },
+    { SCMP_SYS(lseek), 245 },
+    { SCMP_SYS(pselect6), 245 },
+    { SCMP_SYS(fork), 245 },
+    { SCMP_SYS(bind), 245 },
+    { SCMP_SYS(listen), 245 },
+    { SCMP_SYS(eventfd), 245 },
+    { SCMP_SYS(rt_sigprocmask), 245 },
+    { SCMP_SYS(write), 244 },
+    { SCMP_SYS(fcntl), 243 },
+    { SCMP_SYS(tgkill), 242 },
+    { SCMP_SYS(rt_sigaction), 242 },
+    { SCMP_SYS(pipe2), 242 },
+    { SCMP_SYS(munmap), 242 },
+    { SCMP_SYS(mremap), 242 },
+    { SCMP_SYS(getsockname), 242 },
+    { SCMP_SYS(getpeername), 242 },
+    { SCMP_SYS(fdatasync), 242 },
+    { SCMP_SYS(close), 242 }
+};
+
+int seccomp_start(void)
+{
+    int rc = 0;
+    unsigned int i = 0;
+    scmp_filter_ctx ctx;
+
+    ctx = seccomp_init(SCMP_ACT_KILL);
+    if (ctx == NULL) {
+        goto seccomp_return;
+    }
+
+    for (i = 0; i < ARRAY_SIZE(seccomp_whitelist); i++) {
+        rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_whitelist[i].num, 0);
+        if (rc < 0) {
+            goto seccomp_return;
+        }
+        rc = seccomp_syscall_priority(ctx, seccomp_whitelist[i].num,
+                                      seccomp_whitelist[i].priority);
+        if (rc < 0) {
+            goto seccomp_return;
+        }
+    }
+
+    rc = seccomp_load(ctx);
+
+  seccomp_return:
+    seccomp_release(ctx);
+    return rc;
+}
diff --git a/qemu-seccomp.h b/qemu-seccomp.h
new file mode 100644
index 0000000000..b2fc3f8c3c
--- /dev/null
+++ b/qemu-seccomp.h
@@ -0,0 +1,22 @@
+/*
+ * QEMU seccomp mode 2 support with libseccomp
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Eduardo Otubo    <eotubo@br.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#ifndef QEMU_SECCOMP_H
+#define QEMU_SECCOMP_H
+
+#include <seccomp.h>
+#include "osdep.h"
+
+int seccomp_start(void);
+#endif
diff --git a/qlist.c b/qlist.c
index 88498b157f..b48ec5b914 100644
--- a/qlist.c
+++ b/qlist.c
@@ -124,6 +124,19 @@ int qlist_empty(const QList *qlist)
     return QTAILQ_EMPTY(&qlist->head);
 }
 
+static void qlist_size_iter(QObject *obj, void *opaque)
+{
+    size_t *count = opaque;
+    (*count)++;
+}
+
+size_t qlist_size(const QList *qlist)
+{
+    size_t count = 0;
+    qlist_iter(qlist, qlist_size_iter, &count);
+    return count;
+}
+
 /**
  * qobject_to_qlist(): Convert a QObject into a QList
  */
diff --git a/qlist.h b/qlist.h
index d426bd4a4b..ae776f99c3 100644
--- a/qlist.h
+++ b/qlist.h
@@ -49,6 +49,7 @@ void qlist_iter(const QList *qlist,
 QObject *qlist_pop(QList *qlist);
 QObject *qlist_peek(QList *qlist);
 int qlist_empty(const QList *qlist);
+size_t qlist_size(const QList *qlist);
 QList *qobject_to_qlist(const QObject *obj);
 
 static inline const QListEntry *qlist_first(const QList *qlist)
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 2ce4ce6556..00d798fe55 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2509,3 +2509,8 @@ EQMP
         .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/rules.mak b/rules.mak
index a28494679a..1b173aa981 100644
--- a/rules.mak
+++ b/rules.mak
@@ -29,7 +29,7 @@ endif
 	$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  AS    $(TARGET_DIR)$@")
 
 %.o: %.m
-	$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  OBJC  $(TARGET_DIR)$@")
+	$(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  OBJC  $(TARGET_DIR)$@")
 
 LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(sort $(1)) $(LIBS),"  LINK  $(TARGET_DIR)$@")
 
diff --git a/softmmu-semi.h b/softmmu-semi.h
index 648cb959d8..bcb979a5b0 100644
--- a/softmmu-semi.h
+++ b/softmmu-semi.h
@@ -40,7 +40,7 @@ static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len,
     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 @@ static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr)
     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/sysemu.h b/sysemu.h
index 4669348a12..65552acee5 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -62,6 +62,7 @@ int qemu_powerdown_requested(void);
 void qemu_system_killed(int signal, pid_t pid);
 void qemu_kill_report(void);
 extern qemu_irq qemu_system_powerdown;
+void qemu_devices_reset(void);
 void qemu_system_reset(bool report);
 
 void qemu_add_exit_notifier(Notifier *notify);
diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c
index 24952061cf..73bde584ab 100644
--- a/target-arm/arm-semi.c
+++ b/target-arm/arm-semi.c
@@ -194,18 +194,19 @@ uint32_t do_arm_semihosting(CPUARMState *env)
         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/tests/check-qjson.c b/tests/check-qjson.c
index 526e25ef6d..3b896f5f9c 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -466,6 +466,58 @@ static void simple_dict(void)
     }
 }
 
+/*
+ * this generates json of the form:
+ * a(0,m) = [0, 1, ..., m-1]
+ * a(n,m) = {
+ *            'key0': a(0,m),
+ *            'key1': a(1,m),
+ *            ...
+ *            'key(n-1)': a(n-1,m)
+ *          }
+ */
+static void gen_test_json(GString *gstr, int nest_level_max,
+                          int elem_count)
+{
+    int i;
+
+    g_assert(gstr);
+    if (nest_level_max == 0) {
+        g_string_append(gstr, "[");
+        for (i = 0; i < elem_count; i++) {
+            g_string_append_printf(gstr, "%d", i);
+            if (i < elem_count - 1) {
+                g_string_append_printf(gstr, ", ");
+            }
+        }
+        g_string_append(gstr, "]");
+        return;
+    }
+
+    g_string_append(gstr, "{");
+    for (i = 0; i < nest_level_max; i++) {
+        g_string_append_printf(gstr, "'key%d': ", i);
+        gen_test_json(gstr, i, elem_count);
+        if (i < nest_level_max - 1) {
+            g_string_append(gstr, ",");
+        }
+    }
+    g_string_append(gstr, "}");
+}
+
+static void large_dict(void)
+{
+    GString *gstr = g_string_new("");
+    QObject *obj;
+
+    gen_test_json(gstr, 10, 100);
+    obj = qobject_from_json(gstr->str);
+    g_assert(obj != NULL);
+
+    qobject_decref(obj);
+    g_string_free(gstr, true);
+}
+
 static void simple_list(void)
 {
     int i;
@@ -706,6 +758,7 @@ int main(int argc, char **argv)
     g_test_add_func("/literals/keyword", keyword_literal);
 
     g_test_add_func("/dicts/simple_dict", simple_dict);
+    g_test_add_func("/dicts/large_dict", large_dict);
     g_test_add_func("/lists/simple_list", simple_list);
 
     g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
diff --git a/vl.c b/vl.c
index d01256a6a3..7c577fa544 100644
--- a/vl.c
+++ b/vl.c
@@ -63,6 +63,11 @@
 #include <linux/ppdev.h>
 #include <linux/parport.h>
 #endif
+
+#ifdef CONFIG_SECCOMP
+#include "qemu-seccomp.h"
+#endif
+
 #ifdef __sun__
 #include <sys/stat.h>
 #include <sys/ethernet.h>
@@ -765,6 +770,26 @@ static int bt_parse(const char *opt)
     return 1;
 }
 
+static int parse_sandbox(QemuOpts *opts, void *opaque)
+{
+    /* FIXME: change this to true for 1.3 */
+    if (qemu_opt_get_bool(opts, "enable", false)) {
+#ifdef CONFIG_SECCOMP
+        if (seccomp_start() < 0) {
+            qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                          "failed to install seccomp syscall filter in the kernel");
+            return -1;
+        }
+#else
+        qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                      "sandboxing request but seccomp is not compiled into this build");
+        return -1;
+#endif
+    }
+
+    return 0;
+}
+
 /***********************************************************/
 /* QEMU Block devices */
 
@@ -1439,7 +1464,7 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
     }
 }
 
-void qemu_system_reset(bool report)
+void qemu_devices_reset(void)
 {
     QEMUResetEntry *re, *nre;
 
@@ -1447,6 +1472,15 @@ void qemu_system_reset(bool report)
     QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
         re->func(re->opaque);
     }
+}
+
+void qemu_system_reset(bool report)
+{
+    if (current_machine && current_machine->reset) {
+        current_machine->reset();
+    } else {
+        qemu_devices_reset();
+    }
     if (report) {
         monitor_protocol_event(QEVENT_RESET, NULL);
     }
@@ -2701,6 +2735,7 @@ int main(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_m: {
                 int64_t value;
+                uint64_t sz;
                 char *end;
 
                 value = strtosz(optarg, &end);
@@ -2708,12 +2743,12 @@ int main(int argc, char **argv, char **envp)
                     fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
                     exit(1);
                 }
-
-                if (value != (uint64_t)(ram_addr_t)value) {
+                sz = QEMU_ALIGN_UP((uint64_t)value, 8192);
+                ram_size = sz;
+                if (ram_size != sz) {
                     fprintf(stderr, "qemu: ram size too large\n");
                     exit(1);
                 }
-                ram_size = value;
                 break;
             }
             case QEMU_OPTION_mempath:
@@ -3247,6 +3282,12 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_qtest_log:
                 qtest_log = optarg;
                 break;
+            case QEMU_OPTION_sandbox:
+                opts = qemu_opts_parse(qemu_find_opts("sandbox"), optarg, 1);
+                if (!opts) {
+                    exit(0);
+                }
+                break;
             default:
                 os_parse_cmd_args(popt->index, optarg);
             }
@@ -3254,6 +3295,10 @@ int main(int argc, char **argv, char **envp)
     }
     loc_set_none();
 
+    if (qemu_opts_foreach(qemu_find_opts("sandbox"), parse_sandbox, NULL, 0)) {
+        exit(1);
+    }
+
     if (machine == NULL) {
         fprintf(stderr, "No machine found.\n");
         exit(1);