summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--default-configs/i386-softmmu.mak1
-rw-r--r--default-configs/x86_64-softmmu.mak1
-rw-r--r--device-hotplug.c7
-rw-r--r--exec.c2
-rw-r--r--hmp-commands.hx32
-rw-r--r--hw/9pfs/virtio-9p-device.c2
-rw-r--r--hw/9pfs/virtio-9p.h18
-rw-r--r--hw/acpi/Makefile.objs1
-rw-r--r--hw/acpi/aml-build.c889
-rw-r--r--hw/acpi/bios-linker-loader.c4
-rw-r--r--hw/acpi/ich9.c14
-rw-r--r--hw/acpi/memory_hotplug.c3
-rw-r--r--hw/acpi/pcihp.c18
-rw-r--r--hw/acpi/piix4.c15
-rw-r--r--hw/audio/ac97.c5
-rw-r--r--hw/audio/es1370.c5
-rw-r--r--hw/audio/intel-hda.c6
-rw-r--r--hw/block/virtio-blk.c31
-rw-r--r--hw/char/serial-pci.c22
-rw-r--r--hw/char/virtio-serial-bus.c4
-rw-r--r--hw/core/qdev-properties.c21
-rw-r--r--hw/core/qdev.c8
-rw-r--r--hw/display/cirrus_vga.c11
-rw-r--r--hw/display/qxl.c36
-rw-r--r--hw/display/vga-pci.c11
-rw-r--r--hw/display/vmware_vga.c6
-rw-r--r--hw/i2c/smbus_ich9.c5
-rw-r--r--hw/i386/Makefile.objs4
-rw-r--r--hw/i386/acpi-build.c1191
-rw-r--r--hw/i386/acpi-dsdt-cpu-hotplug.dsl17
-rw-r--r--hw/i386/acpi-dsdt-isa.dsl11
-rw-r--r--hw/i386/acpi-dsdt-mem-hotplug.dsl36
-rw-r--r--hw/i386/acpi-dsdt-pci-crs.dsl92
-rw-r--r--hw/i386/acpi-dsdt.dsl46
-rw-r--r--hw/i386/acpi-dsdt.hex.generated676
-rw-r--r--hw/i386/kvm/pci-assign.c10
-rw-r--r--hw/i386/pc.c23
-rw-r--r--hw/i386/pc_piix.c3
-rw-r--r--hw/i386/pc_q35.c3
-rw-r--r--hw/i386/q35-acpi-dsdt.dsl19
-rw-r--r--hw/i386/q35-acpi-dsdt.hex.generated628
-rw-r--r--hw/i386/ssdt-mem.dsl77
-rw-r--r--hw/i386/ssdt-mem.hex.generated213
-rw-r--r--hw/i386/ssdt-misc.dsl122
-rw-r--r--hw/i386/ssdt-misc.hex.generated399
-rw-r--r--hw/i386/ssdt-pcihp.dsl100
-rw-r--r--hw/i386/ssdt-pcihp.hex.generated251
-rw-r--r--hw/i386/ssdt-proc.dsl63
-rw-r--r--hw/i386/ssdt-proc.hex.generated134
-rw-r--r--hw/i386/ssdt-tpm.hex.generated6
-rw-r--r--hw/ide/cmd646.c5
-rw-r--r--hw/ide/ich.c13
-rw-r--r--hw/ide/piix.c10
-rw-r--r--hw/ide/via.c6
-rw-r--r--hw/ipack/tpci200.c6
-rw-r--r--hw/isa/i82378.c6
-rw-r--r--hw/isa/lpc_ich9.c14
-rw-r--r--hw/isa/piix4.c5
-rw-r--r--hw/isa/vt82c686.c24
-rw-r--r--hw/misc/applesmc.c5
-rw-r--r--hw/misc/pci-testdev.c6
-rw-r--r--hw/net/e1000.c6
-rw-r--r--hw/net/eepro100.c6
-rw-r--r--hw/net/lance.c3
-rw-r--r--hw/net/ne2000.c6
-rw-r--r--hw/net/pcnet-pci.c6
-rw-r--r--hw/net/pcnet.c4
-rw-r--r--hw/net/pcnet.h2
-rw-r--r--hw/net/rtl8139.c6
-rw-r--r--hw/net/vhost_net.c2
-rw-r--r--hw/net/virtio-net.c57
-rw-r--r--hw/net/vmxnet3.c6
-rw-r--r--hw/pci-bridge/dec.c5
-rw-r--r--hw/pci-host/apb.c5
-rw-r--r--hw/pci-host/bonito.c6
-rw-r--r--hw/pci-host/grackle.c5
-rw-r--r--hw/pci-host/piix.c12
-rw-r--r--hw/pci-host/ppce500.c6
-rw-r--r--hw/pci-host/prep.c6
-rw-r--r--hw/pci-host/q35.c5
-rw-r--r--hw/pci-host/uninorth.c20
-rw-r--r--hw/pci-host/versatile.c5
-rw-r--r--hw/pci/Makefile.objs2
-rw-r--r--hw/pci/pci-hotplug-old.c342
-rw-r--r--hw/pci/pci.c127
-rw-r--r--hw/s390x/s390-virtio-bus.h36
-rw-r--r--hw/s390x/s390-virtio.h7
-rw-r--r--hw/s390x/virtio-ccw.c12
-rw-r--r--hw/scsi/virtio-scsi.c9
-rw-r--r--hw/sd/sdhci.c5
-rw-r--r--hw/tpm/tpm_int.h1
-rw-r--r--hw/tpm/tpm_passthrough.c37
-rw-r--r--hw/tpm/tpm_tis.c131
-rw-r--r--hw/tpm/tpm_tis.h2
-rw-r--r--hw/usb/hcd-ehci-pci.c6
-rw-r--r--hw/usb/hcd-xhci.c6
-rw-r--r--hw/virtio/dataplane/vring.c10
-rw-r--r--hw/virtio/virtio-balloon.c2
-rw-r--r--hw/virtio/virtio-bus.c14
-rw-r--r--hw/virtio/virtio-mmio.c2
-rw-r--r--hw/virtio/virtio-pci.c63
-rw-r--r--hw/virtio/virtio.c33
-rw-r--r--hw/watchdog/wdt_i6300esb.c6
-rw-r--r--include/hw/acpi/aml-build.h191
-rw-r--r--include/hw/acpi/ich9.h4
-rw-r--r--include/hw/acpi/pc-hotplug.h1
-rw-r--r--include/hw/acpi/pcihp.h7
-rw-r--r--include/hw/i386/pc.h1
-rw-r--r--include/hw/isa/isa.h11
-rw-r--r--include/hw/pci/pci.h10
-rw-r--r--include/hw/qdev-properties.h4
-rw-r--r--include/hw/virtio/dataplane/vring-accessors.h2
-rw-r--r--include/hw/virtio/dataplane/vring.h2
-rw-r--r--include/hw/virtio/virtio-balloon.h35
-rw-r--r--include/hw/virtio/virtio-blk.h77
-rw-r--r--include/hw/virtio/virtio-bus.h3
-rw-r--r--include/hw/virtio/virtio-net.h151
-rw-r--r--include/hw/virtio/virtio-rng.h4
-rw-r--r--include/hw/virtio/virtio-scsi.h120
-rw-r--r--include/hw/virtio/virtio-serial.h40
-rw-r--r--include/hw/virtio/virtio.h71
-rw-r--r--include/net/tap.h24
-rw-r--r--include/standard-headers/asm-s390/kvm_virtio.h64
-rw-r--r--include/standard-headers/asm-s390/virtio-ccw.h21
-rw-r--r--include/standard-headers/linux/if_ether.h1
-rw-r--r--include/standard-headers/linux/types.h2
-rw-r--r--include/standard-headers/linux/virtio_9p.h44
-rw-r--r--include/standard-headers/linux/virtio_balloon.h59
-rw-r--r--include/standard-headers/linux/virtio_blk.h143
-rw-r--r--include/standard-headers/linux/virtio_config.h64
-rw-r--r--include/standard-headers/linux/virtio_console.h78
-rw-r--r--include/standard-headers/linux/virtio_ids.h43
-rw-r--r--include/standard-headers/linux/virtio_net.h233
-rw-r--r--include/standard-headers/linux/virtio_pci.h193
-rw-r--r--include/standard-headers/linux/virtio_ring.h (renamed from include/hw/virtio/virtio_ring.h)132
-rw-r--r--include/standard-headers/linux/virtio_rng.h8
-rw-r--r--include/standard-headers/linux/virtio_scsi.h164
-rw-r--r--include/standard-headers/linux/virtio_types.h46
-rw-r--r--include/sysemu/blockdev.h2
-rw-r--r--include/sysemu/sysemu.h5
-rw-r--r--include/sysemu/tpm_backend.h2
-rw-r--r--linux-headers/linux/virtio_config.h58
-rw-r--r--linux-headers/linux/virtio_ring.h164
-rw-r--r--net/vhost-user.c16
-rwxr-xr-xscripts/update-linux-headers.sh52
-rw-r--r--stubs/Makefile.objs1
-rw-r--r--stubs/pci-drive-hot-add.c10
-rw-r--r--tests/acpi-test-data/pc/DSDTbin3621 -> 2970 bytes
-rw-r--r--tests/acpi-test-data/pc/SSDTbin2279 -> 2476 bytes
-rw-r--r--tests/acpi-test-data/pc/SSDT.bridgebin0 -> 4335 bytes
-rw-r--r--tests/acpi-test-data/q35/DSDTbin8211 -> 7608 bytes
-rw-r--r--tests/acpi-test-data/q35/SSDTbin560 -> 681 bytes
-rw-r--r--tests/acpi-test-data/q35/SSDT.bridgebin0 -> 698 bytes
-rw-r--r--tests/bios-tables-test.c45
-rw-r--r--vl.c34
155 files changed, 3587 insertions, 5289 deletions
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 0b8ce4bbf8..6a74e00399 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -26,7 +26,6 @@ CONFIG_APPLESMC=y
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_TPM_TIS=$(CONFIG_TPM)
-CONFIG_PCI_HOTPLUG_OLD=y
 CONFIG_MC146818RTC=y
 CONFIG_PAM=y
 CONFIG_PCI_PIIX=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 6add04a2f6..46b87ddb43 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -26,7 +26,6 @@ CONFIG_APPLESMC=y
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_TPM_TIS=$(CONFIG_TPM)
-CONFIG_PCI_HOTPLUG_OLD=y
 CONFIG_MC146818RTC=y
 CONFIG_PAM=y
 CONFIG_PCI_PIIX=y
diff --git a/device-hotplug.c b/device-hotplug.c
index 833d8748d5..68b94967c5 100644
--- a/device-hotplug.c
+++ b/device-hotplug.c
@@ -30,7 +30,7 @@
 #include "sysemu/sysemu.h"
 #include "monitor/monitor.h"
 
-DriveInfo *add_init_drive(const char *optstr)
+static DriveInfo *add_init_drive(const char *optstr)
 {
     DriveInfo *dinfo;
     QemuOpts *opts;
@@ -69,9 +69,8 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "OK\n");
         break;
     default:
-        if (pci_drive_hot_add(mon, qdict, dinfo)) {
-            goto err;
-        }
+        monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
+        goto err;
     }
     return;
 
diff --git a/exec.c b/exec.c
index c85321a38b..6a5adab502 100644
--- a/exec.c
+++ b/exec.c
@@ -1347,6 +1347,8 @@ int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp)
 
     assert(block);
 
+    newsize = TARGET_PAGE_ALIGN(newsize);
+
     if (block->used_length == newsize) {
         return 0;
     }
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 81f276b209..d5022d843c 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1149,38 +1149,6 @@ STEXI
 Add drive to PCI storage controller.
 ETEXI
 
-#if defined(CONFIG_PCI_HOTPLUG_OLD)
-    {
-        .name       = "pci_add",
-        .args_type  = "pci_addr:s,type:s,opts:s?",
-        .params     = "auto|[[<domain>:]<bus>:]<slot> nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...",
-        .help       = "hot-add PCI device",
-        .mhandler.cmd = hmp_pci_add,
-    },
-#endif
-
-STEXI
-@item pci_add
-@findex pci_add
-Hot-add PCI device.
-ETEXI
-
-#if defined(CONFIG_PCI_HOTPLUG_OLD)
-    {
-        .name       = "pci_del",
-        .args_type  = "pci_addr:s",
-        .params     = "[[<domain>:]<bus>:]<slot>",
-        .help       = "hot remove PCI device",
-        .mhandler.cmd = hmp_pci_del,
-    },
-#endif
-
-STEXI
-@item pci_del
-@findex pci_del
-Hot remove PCI device.
-ETEXI
-
     {
         .name       = "pcie_aer_inject_error",
         .args_type  = "advisory_non_fatal:-a,correctable:-c,"
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 2572747629..30492ecb02 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -23,7 +23,7 @@
 
 static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
 {
-    features |= 1 << VIRTIO_9P_MOUNT_TAG;
+    virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG);
     return features;
 }
 
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 2c3603aed0..58dafa9e14 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -7,16 +7,14 @@
 #include <utime.h>
 #include <sys/resource.h>
 #include <glib.h>
+#include "standard-headers/linux/virtio_9p.h"
 #include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-9p.h"
 #include "fsdev/file-op-9p.h"
 #include "fsdev/virtio-9p-marshal.h"
 #include "qemu/thread.h"
 #include "block/coroutine.h"
 
-/* The feature bitmap for virtio 9P */
-/* The mount point is specified in a config variable */
-#define VIRTIO_9P_MOUNT_TAG 0
-
 enum {
     P9_TLERROR = 6,
     P9_RLERROR,
@@ -144,10 +142,6 @@ struct V9fsPDU
  * 1) change user needs to set groups and stuff
  */
 
-/* from Linux's linux/virtio_9p.h */
-
-/* The ID for virtio console */
-#define VIRTIO_ID_9P    9
 #define MAX_REQ         128
 #define MAX_TAG_LEN     32
 
@@ -277,14 +271,6 @@ typedef struct V9fsWriteState {
     int cnt;
 } V9fsWriteState;
 
-struct virtio_9p_config
-{
-    /* number of characters in tag */
-    uint16_t tag_len;
-    /* Variable size tag name */
-    uint8_t tag[0];
-} QEMU_PACKED;
-
 typedef struct V9fsMkState {
     V9fsPDU *pdu;
     size_t offset;
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index ee82073338..b9fefa7635 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -2,3 +2,4 @@ common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o pcihp.o cpu_hotplug.o
 common-obj-$(CONFIG_ACPI) += memory_hotplug.o
 common-obj-$(CONFIG_ACPI) += acpi_interface.o
 common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
+common-obj-$(CONFIG_ACPI) += aml-build.o
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
new file mode 100644
index 0000000000..876cada4b2
--- /dev/null
+++ b/hw/acpi/aml-build.c
@@ -0,0 +1,889 @@
+/* Support for generating ACPI tables and passing them to Guests
+ *
+ * Copyright (C) 2015 Red Hat Inc
+ *
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ * Author: Igor Mammedov <imammedo@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include "hw/acpi/aml-build.h"
+#include "qemu/bswap.h"
+
+static GArray *build_alloc_array(void)
+{
+    return g_array_new(false, true /* clear */, 1);
+}
+
+static void build_free_array(GArray *array)
+{
+    g_array_free(array, true);
+}
+
+static void build_prepend_byte(GArray *array, uint8_t val)
+{
+    g_array_prepend_val(array, val);
+}
+
+static void build_append_byte(GArray *array, uint8_t val)
+{
+    g_array_append_val(array, val);
+}
+
+static void build_append_array(GArray *array, GArray *val)
+{
+    g_array_append_vals(array, val->data, val->len);
+}
+
+#define ACPI_NAMESEG_LEN 4
+
+static void
+build_append_nameseg(GArray *array, const char *seg)
+{
+    /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
+    int len;
+
+    len = strlen(seg);
+    assert(len <= ACPI_NAMESEG_LEN);
+
+    g_array_append_vals(array, seg, len);
+    /* Pad up to ACPI_NAMESEG_LEN characters if necessary. */
+    g_array_append_vals(array, "____", ACPI_NAMESEG_LEN - len);
+}
+
+static void
+build_append_namestringv(GArray *array, const char *format, va_list ap)
+{
+    /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
+    char *s;
+    int len;
+    va_list va_len;
+    char **segs;
+    char **segs_iter;
+    int seg_count = 0;
+
+    va_copy(va_len, ap);
+    len = vsnprintf(NULL, 0, format, va_len);
+    va_end(va_len);
+    len += 1;
+    s = g_new(typeof(*s), len);
+
+    len = vsnprintf(s, len, format, ap);
+
+    segs = g_strsplit(s, ".", 0);
+    g_free(s);
+
+    /* count segments */
+    segs_iter = segs;
+    while (*segs_iter) {
+        ++segs_iter;
+        ++seg_count;
+    }
+    /*
+     * ACPI 5.0 spec: 20.2.2 Name Objects Encoding:
+     * "SegCount can be from 1 to 255"
+     */
+    assert(seg_count > 0 && seg_count <= 255);
+
+    /* handle RootPath || PrefixPath */
+    s = *segs;
+    while (*s == '\\' || *s == '^') {
+        build_append_byte(array, *s);
+        ++s;
+    }
+
+    switch (seg_count) {
+    case 1:
+        if (!*s) {
+            build_append_byte(array, 0x0); /* NullName */
+        } else {
+            build_append_nameseg(array, s);
+        }
+        break;
+
+    case 2:
+        build_append_byte(array, 0x2E); /* DualNamePrefix */
+        build_append_nameseg(array, s);
+        build_append_nameseg(array, segs[1]);
+        break;
+    default:
+        build_append_byte(array, 0x2F); /* MultiNamePrefix */
+        build_append_byte(array, seg_count);
+
+        /* handle the 1st segment manually due to prefix/root path */
+        build_append_nameseg(array, s);
+
+        /* add the rest of segments */
+        segs_iter = segs + 1;
+        while (*segs_iter) {
+            build_append_nameseg(array, *segs_iter);
+            ++segs_iter;
+        }
+        break;
+    }
+    g_strfreev(segs);
+}
+
+static void build_append_namestring(GArray *array, const char *format, ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    build_append_namestringv(array, format, ap);
+    va_end(ap);
+}
+
+/* 5.4 Definition Block Encoding */
+enum {
+    PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */
+    PACKAGE_LENGTH_2BYTE_SHIFT = 4,
+    PACKAGE_LENGTH_3BYTE_SHIFT = 12,
+    PACKAGE_LENGTH_4BYTE_SHIFT = 20,
+};
+
+static void
+build_prepend_package_length(GArray *package, unsigned length, bool incl_self)
+{
+    uint8_t byte;
+    unsigned length_bytes;
+
+    if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) {
+        length_bytes = 1;
+    } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) {
+        length_bytes = 2;
+    } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) {
+        length_bytes = 3;
+    } else {
+        length_bytes = 4;
+    }
+
+    /*
+     * NamedField uses PkgLength encoding but it doesn't include length
+     * of PkgLength itself.
+     */
+    if (incl_self) {
+        /*
+         * PkgLength is the length of the inclusive length of the data
+         * and PkgLength's length itself when used for terms with
+         * explitit length.
+         */
+        length += length_bytes;
+    }
+
+    switch (length_bytes) {
+    case 1:
+        byte = length;
+        build_prepend_byte(package, byte);
+        return;
+    case 4:
+        byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT;
+        build_prepend_byte(package, byte);
+        length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1;
+        /* fall through */
+    case 3:
+        byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT;
+        build_prepend_byte(package, byte);
+        length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1;
+        /* fall through */
+    case 2:
+        byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT;
+        build_prepend_byte(package, byte);
+        length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1;
+        /* fall through */
+    }
+    /*
+     * Most significant two bits of byte zero indicate how many following bytes
+     * are in PkgLength encoding.
+     */
+    byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length;
+    build_prepend_byte(package, byte);
+}
+
+static void
+build_append_pkg_length(GArray *array, unsigned length, bool incl_self)
+{
+    GArray *tmp = build_alloc_array();
+
+    build_prepend_package_length(tmp, length, incl_self);
+    build_append_array(array, tmp);
+    build_free_array(tmp);
+}
+
+static void build_package(GArray *package, uint8_t op)
+{
+    build_prepend_package_length(package, package->len, true);
+    build_prepend_byte(package, op);
+}
+
+static void build_extop_package(GArray *package, uint8_t op)
+{
+    build_package(package, op);
+    build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
+}
+
+static void build_append_int_noprefix(GArray *table, uint64_t value, int size)
+{
+    int i;
+
+    for (i = 0; i < size; ++i) {
+        build_append_byte(table, value & 0xFF);
+        value = value >> 8;
+    }
+}
+
+static void build_append_int(GArray *table, uint64_t value)
+{
+    if (value == 0x00) {
+        build_append_byte(table, 0x00); /* ZeroOp */
+    } else if (value == 0x01) {
+        build_append_byte(table, 0x01); /* OneOp */
+    } else if (value <= 0xFF) {
+        build_append_byte(table, 0x0A); /* BytePrefix */
+        build_append_int_noprefix(table, value, 1);
+    } else if (value <= 0xFFFF) {
+        build_append_byte(table, 0x0B); /* WordPrefix */
+        build_append_int_noprefix(table, value, 2);
+    } else if (value <= 0xFFFFFFFF) {
+        build_append_byte(table, 0x0C); /* DWordPrefix */
+        build_append_int_noprefix(table, value, 4);
+    } else {
+        build_append_byte(table, 0x0E); /* QWordPrefix */
+        build_append_int_noprefix(table, value, 8);
+    }
+}
+
+static GPtrArray *alloc_list;
+
+static Aml *aml_alloc(void)
+{
+    Aml *var = g_new0(typeof(*var), 1);
+
+    g_ptr_array_add(alloc_list, var);
+    var->block_flags = AML_NO_OPCODE;
+    var->buf = build_alloc_array();
+    return var;
+}
+
+static Aml *aml_opcode(uint8_t op)
+{
+    Aml *var = aml_alloc();
+
+    var->op  = op;
+    var->block_flags = AML_OPCODE;
+    return var;
+}
+
+static Aml *aml_bundle(uint8_t op, AmlBlockFlags flags)
+{
+    Aml *var = aml_alloc();
+
+    var->op  = op;
+    var->block_flags = flags;
+    return var;
+}
+
+static void aml_free(gpointer data, gpointer user_data)
+{
+    Aml *var = data;
+    build_free_array(var->buf);
+}
+
+Aml *init_aml_allocator(void)
+{
+    Aml *var;
+
+    assert(!alloc_list);
+    alloc_list = g_ptr_array_new();
+    var = aml_alloc();
+    return var;
+}
+
+void free_aml_allocator(void)
+{
+    g_ptr_array_foreach(alloc_list, aml_free, NULL);
+    g_ptr_array_free(alloc_list, true);
+    alloc_list = 0;
+}
+
+/* pack data with DefBuffer encoding */
+static void build_buffer(GArray *array, uint8_t op)
+{
+    GArray *data = build_alloc_array();
+
+    build_append_int(data, array->len);
+    g_array_prepend_vals(array, data->data, data->len);
+    build_free_array(data);
+    build_package(array, op);
+}
+
+void aml_append(Aml *parent_ctx, Aml *child)
+{
+    switch (child->block_flags) {
+    case AML_OPCODE:
+        build_append_byte(parent_ctx->buf, child->op);
+        break;
+    case AML_EXT_PACKAGE:
+        build_extop_package(child->buf, child->op);
+        break;
+    case AML_PACKAGE:
+        build_package(child->buf, child->op);
+        break;
+    case AML_RES_TEMPLATE:
+        build_append_byte(child->buf, 0x79); /* EndTag */
+        /*
+         * checksum operations are treated as succeeded if checksum
+         * field is zero. [ACPI Spec 1.0b, 6.4.2.8 End Tag]
+         */
+        build_append_byte(child->buf, 0);
+        /* fall through, to pack resources in buffer */
+    case AML_BUFFER:
+        build_buffer(child->buf, child->op);
+        break;
+    case AML_NO_OPCODE:
+        break;
+    default:
+        assert(0);
+        break;
+    }
+    build_append_array(parent_ctx->buf, child->buf);
+}
+
+/* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefScope */
+Aml *aml_scope(const char *name_format, ...)
+{
+    va_list ap;
+    Aml *var = aml_bundle(0x10 /* ScopeOp */, AML_PACKAGE);
+    va_start(ap, name_format);
+    build_append_namestringv(var->buf, name_format, ap);
+    va_end(ap);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */
+Aml *aml_return(Aml *val)
+{
+    Aml *var = aml_opcode(0xA4 /* ReturnOp */);
+    aml_append(var, val);
+    return var;
+}
+
+/*
+ * ACPI 1.0b: 16.2.3 Data Objects Encoding:
+ * encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp
+ */
+Aml *aml_int(const uint64_t val)
+{
+    Aml *var = aml_alloc();
+    build_append_int(var->buf, val);
+    return var;
+}
+
+/*
+ * helper to construct NameString, which returns Aml object
+ * for using with aml_append or other aml_* terms
+ */
+Aml *aml_name(const char *name_format, ...)
+{
+    va_list ap;
+    Aml *var = aml_alloc();
+    va_start(ap, name_format);
+    build_append_namestringv(var->buf, name_format, ap);
+    va_end(ap);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefName */
+Aml *aml_name_decl(const char *name, Aml *val)
+{
+    Aml *var = aml_opcode(0x08 /* NameOp */);
+    build_append_namestring(var->buf, "%s", name);
+    aml_append(var, val);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.6.1 Arg Objects Encoding */
+Aml *aml_arg(int pos)
+{
+    Aml *var;
+    uint8_t op = 0x68 /* ARG0 op */ + pos;
+
+    assert(pos <= 6);
+    var = aml_opcode(op);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefStore */
+Aml *aml_store(Aml *val, Aml *target)
+{
+    Aml *var = aml_opcode(0x70 /* StoreOp */);
+    aml_append(var, val);
+    aml_append(var, target);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAnd */
+Aml *aml_and(Aml *arg1, Aml *arg2)
+{
+    Aml *var = aml_opcode(0x7B /* AndOp */);
+    aml_append(var, arg1);
+    aml_append(var, arg2);
+    build_append_int(var->buf, 0x00 /* NullNameOp */);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */
+Aml *aml_notify(Aml *arg1, Aml *arg2)
+{
+    Aml *var = aml_opcode(0x86 /* NotifyOp */);
+    aml_append(var, arg1);
+    aml_append(var, arg2);
+    return var;
+}
+
+/* helper to call method with 1 argument */
+Aml *aml_call1(const char *method, Aml *arg1)
+{
+    Aml *var = aml_alloc();
+    build_append_namestring(var->buf, "%s", method);
+    aml_append(var, arg1);
+    return var;
+}
+
+/* helper to call method with 2 arguments */
+Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2)
+{
+    Aml *var = aml_alloc();
+    build_append_namestring(var->buf, "%s", method);
+    aml_append(var, arg1);
+    aml_append(var, arg2);
+    return var;
+}
+
+/* helper to call method with 3 arguments */
+Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3)
+{
+    Aml *var = aml_alloc();
+    build_append_namestring(var->buf, "%s", method);
+    aml_append(var, arg1);
+    aml_append(var, arg2);
+    aml_append(var, arg3);
+    return var;
+}
+
+/* helper to call method with 4 arguments */
+Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4)
+{
+    Aml *var = aml_alloc();
+    build_append_namestring(var->buf, "%s", method);
+    aml_append(var, arg1);
+    aml_append(var, arg2);
+    aml_append(var, arg3);
+    aml_append(var, arg4);
+    return var;
+}
+
+/* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */
+Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
+            uint8_t aln, uint8_t len)
+{
+    Aml *var = aml_alloc();
+    build_append_byte(var->buf, 0x47); /* IO port descriptor */
+    build_append_byte(var->buf, dec);
+    build_append_byte(var->buf, min_base & 0xff);
+    build_append_byte(var->buf, (min_base >> 8) & 0xff);
+    build_append_byte(var->buf, max_base & 0xff);
+    build_append_byte(var->buf, (max_base >> 8) & 0xff);
+    build_append_byte(var->buf, aln);
+    build_append_byte(var->buf, len);
+    return var;
+}
+
+/*
+ * ACPI 1.0b: 6.4.2.1.1 ASL Macro for IRQ Descriptor
+ *
+ * More verbose description at:
+ * ACPI 5.0: 19.5.64 IRQNoFlags (Interrupt Resource Descriptor Macro)
+ *           6.4.2.1 IRQ Descriptor
+ */
+Aml *aml_irq_no_flags(uint8_t irq)
+{
+    uint16_t irq_mask;
+    Aml *var = aml_alloc();
+
+    assert(irq < 16);
+    build_append_byte(var->buf, 0x22); /* IRQ descriptor 2 byte form */
+
+    irq_mask = 1U << irq;
+    build_append_byte(var->buf, irq_mask & 0xFF); /* IRQ mask bits[7:0] */
+    build_append_byte(var->buf, irq_mask >> 8); /* IRQ mask bits[15:8] */
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */
+Aml *aml_equal(Aml *arg1, Aml *arg2)
+{
+    Aml *var = aml_opcode(0x93 /* LequalOp */);
+    aml_append(var, arg1);
+    aml_append(var, arg2);
+    build_append_int(var->buf, 0x00); /* NullNameOp */
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefIfElse */
+Aml *aml_if(Aml *predicate)
+{
+    Aml *var = aml_bundle(0xA0 /* IfOp */, AML_PACKAGE);
+    aml_append(var, predicate);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */
+Aml *aml_method(const char *name, int arg_count)
+{
+    Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE);
+    build_append_namestring(var->buf, "%s", name);
+    build_append_byte(var->buf, arg_count); /* MethodFlags: ArgCount */
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefDevice */
+Aml *aml_device(const char *name_format, ...)
+{
+    va_list ap;
+    Aml *var = aml_bundle(0x82 /* DeviceOp */, AML_EXT_PACKAGE);
+    va_start(ap, name_format);
+    build_append_namestringv(var->buf, name_format, ap);
+    va_end(ap);
+    return var;
+}
+
+/* ACPI 1.0b: 6.4.1 ASL Macros for Resource Descriptors */
+Aml *aml_resource_template(void)
+{
+    /* ResourceTemplate is a buffer of Resources with EndTag at the end */
+    Aml *var = aml_bundle(0x11 /* BufferOp */, AML_RES_TEMPLATE);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefBuffer */
+Aml *aml_buffer(void)
+{
+    Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefPackage */
+Aml *aml_package(uint8_t num_elements)
+{
+    Aml *var = aml_bundle(0x12 /* PackageOp */, AML_PACKAGE);
+    build_append_byte(var->buf, num_elements);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */
+Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
+                          uint32_t offset, uint32_t len)
+{
+    Aml *var = aml_alloc();
+    build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
+    build_append_byte(var->buf, 0x80); /* OpRegionOp */
+    build_append_namestring(var->buf, "%s", name);
+    build_append_byte(var->buf, rs);
+    build_append_int(var->buf, offset);
+    build_append_int(var->buf, len);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: NamedField */
+Aml *aml_named_field(const char *name, unsigned length)
+{
+    Aml *var = aml_alloc();
+    build_append_nameseg(var->buf, name);
+    build_append_pkg_length(var->buf, length, false);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: ReservedField */
+Aml *aml_reserved_field(unsigned length)
+{
+    Aml *var = aml_alloc();
+    /* ReservedField  := 0x00 PkgLength */
+    build_append_byte(var->buf, 0x00);
+    build_append_pkg_length(var->buf, length, false);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefField */
+Aml *aml_field(const char *name, AmlFieldFlags flags)
+{
+    Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE);
+    build_append_namestring(var->buf, "%s", name);
+    build_append_byte(var->buf, flags);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */
+Aml *aml_string(const char *name_format, ...)
+{
+    Aml *var = aml_opcode(0x0D /* StringPrefix */);
+    va_list ap, va_len;
+    char *s;
+    int len;
+
+    va_start(ap, name_format);
+    va_copy(va_len, ap);
+    len = vsnprintf(NULL, 0, name_format, va_len);
+    va_end(va_len);
+    len += 1;
+    s = g_new0(typeof(*s), len);
+
+    len = vsnprintf(s, len, name_format, ap);
+    va_end(ap);
+
+    g_array_append_vals(var->buf, s, len);
+    build_append_byte(var->buf, 0x0); /* NullChar */
+    g_free(s);
+
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.6.2 Local Objects Encoding */
+Aml *aml_local(int num)
+{
+    Aml *var;
+    uint8_t op = 0x60 /* Local0Op */ + num;
+
+    assert(num <= 7);
+    var = aml_opcode(op);
+    return var;
+}
+
+/* ACPI 2.0a: 17.2.2 Data Objects Encoding: DefVarPackage */
+Aml *aml_varpackage(uint32_t num_elements)
+{
+    Aml *var = aml_bundle(0x13 /* VarPackageOp */, AML_PACKAGE);
+    build_append_int(var->buf, num_elements);
+    return var;
+}
+
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefProcessor */
+Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len,
+                   const char *name_format, ...)
+{
+    va_list ap;
+    Aml *var = aml_bundle(0x83 /* ProcessorOp */, AML_EXT_PACKAGE);
+    va_start(ap, name_format);
+    build_append_namestringv(var->buf, name_format, ap);
+    va_end(ap);
+    build_append_byte(var->buf, proc_id); /* ProcID */
+    build_append_int_noprefix(var->buf, pblk_addr, sizeof(pblk_addr));
+    build_append_byte(var->buf, pblk_len); /* PblkLen */
+    return var;
+}
+
+static uint8_t Hex2Digit(char c)
+{
+    if (c >= 'A') {
+        return c - 'A' + 10;
+    }
+
+    return c - '0';
+}
+
+/* ACPI 1.0b: 15.2.3.6.4.1 EISAID Macro - Convert EISA ID String To Integer */
+Aml *aml_eisaid(const char *str)
+{
+    Aml *var = aml_alloc();
+    uint32_t id;
+
+    g_assert(strlen(str) == 7);
+    id = (str[0] - 0x40) << 26 |
+    (str[1] - 0x40) << 21 |
+    (str[2] - 0x40) << 16 |
+    Hex2Digit(str[3]) << 12 |
+    Hex2Digit(str[4]) << 8 |
+    Hex2Digit(str[5]) << 4 |
+    Hex2Digit(str[6]);
+
+    build_append_byte(var->buf, 0x0C); /* DWordPrefix */
+    build_append_int_noprefix(var->buf, bswap32(id), sizeof(id));
+    return var;
+}
+
+/* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor: bytes 3-5 */
+static Aml *aml_as_desc_header(AmlResourceType type, AmlMinFixed min_fixed,
+                               AmlMaxFixed max_fixed, AmlDecode dec,
+                               uint8_t type_flags)
+{
+    uint8_t flags = max_fixed | min_fixed | dec;
+    Aml *var = aml_alloc();
+
+    build_append_byte(var->buf, type);
+    build_append_byte(var->buf, flags);
+    build_append_byte(var->buf, type_flags); /* Type Specific Flags */
+    return var;
+}
+
+/* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor */
+static Aml *aml_word_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
+                             AmlMaxFixed max_fixed, AmlDecode dec,
+                             uint16_t addr_gran, uint16_t addr_min,
+                             uint16_t addr_max, uint16_t addr_trans,
+                             uint16_t len, uint8_t type_flags)
+{
+    Aml *var = aml_alloc();
+
+    build_append_byte(var->buf, 0x88); /* Word Address Space Descriptor */
+    /* minimum length since we do not encode optional fields */
+    build_append_byte(var->buf, 0x0D);
+    build_append_byte(var->buf, 0x0);
+
+    aml_append(var,
+        aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
+    build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
+    build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
+    build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
+    build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
+    build_append_int_noprefix(var->buf, len, sizeof(len));
+    return var;
+}
+
+/* ACPI 1.0b: 6.4.3.5.3 DWord Address Space Descriptor */
+static Aml *aml_dword_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
+                              AmlMaxFixed max_fixed, AmlDecode dec,
+                              uint32_t addr_gran, uint32_t addr_min,
+                              uint32_t addr_max, uint32_t addr_trans,
+                              uint32_t len, uint8_t type_flags)
+{
+    Aml *var = aml_alloc();
+
+    build_append_byte(var->buf, 0x87); /* DWord Address Space Descriptor */
+    /* minimum length since we do not encode optional fields */
+    build_append_byte(var->buf, 23);
+    build_append_byte(var->buf, 0x0);
+
+
+    aml_append(var,
+        aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
+    build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
+    build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
+    build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
+    build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
+    build_append_int_noprefix(var->buf, len, sizeof(len));
+    return var;
+}
+
+/* ACPI 1.0b: 6.4.3.5.1 QWord Address Space Descriptor */
+static Aml *aml_qword_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
+                              AmlMaxFixed max_fixed, AmlDecode dec,
+                              uint64_t addr_gran, uint64_t addr_min,
+                              uint64_t addr_max, uint64_t addr_trans,
+                              uint64_t len, uint8_t type_flags)
+{
+    Aml *var = aml_alloc();
+
+    build_append_byte(var->buf, 0x8A); /* QWord Address Space Descriptor */
+    /* minimum length since we do not encode optional fields */
+    build_append_byte(var->buf, 0x2B);
+    build_append_byte(var->buf, 0x0);
+
+    aml_append(var,
+        aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
+    build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
+    build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
+    build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
+    build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
+    build_append_int_noprefix(var->buf, len, sizeof(len));
+    return var;
+}
+
+/*
+ * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor
+ *
+ * More verbose description at:
+ * ACPI 5.0: 19.5.141 WordBusNumber (Word Bus Number Resource Descriptor Macro)
+ */
+Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
+                         AmlDecode dec, uint16_t addr_gran,
+                         uint16_t addr_min, uint16_t addr_max,
+                         uint16_t addr_trans, uint16_t len)
+
+{
+    return aml_word_as_desc(aml_bus_number_range, min_fixed, max_fixed, dec,
+                            addr_gran, addr_min, addr_max, addr_trans, len, 0);
+}
+
+/*
+ * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor
+ *
+ * More verbose description at:
+ * ACPI 5.0: 19.5.142 WordIO (Word IO Resource Descriptor Macro)
+ */
+Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
+                 AmlDecode dec, AmlISARanges isa_ranges,
+                 uint16_t addr_gran, uint16_t addr_min,
+                 uint16_t addr_max, uint16_t addr_trans,
+                 uint16_t len)
+
+{
+    return aml_word_as_desc(aml_io_range, min_fixed, max_fixed, dec,
+                            addr_gran, addr_min, addr_max, addr_trans, len,
+                            isa_ranges);
+}
+
+/*
+ * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Space Descriptor
+ *
+ * More verbose description at:
+ * ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro)
+ */
+Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed,
+                      AmlMaxFixed max_fixed, AmlCacheble cacheable,
+                      AmlReadAndWrite read_and_write,
+                      uint32_t addr_gran, uint32_t addr_min,
+                      uint32_t addr_max, uint32_t addr_trans,
+                      uint32_t len)
+{
+    uint8_t flags = read_and_write | (cacheable << 1);
+
+    return aml_dword_as_desc(aml_memory_range, min_fixed, max_fixed,
+                             dec, addr_gran, addr_min, addr_max,
+                             addr_trans, len, flags);
+}
+
+/*
+ * ACPI 1.0b: 6.4.3.5.2 ASL Macros for QWORD Address Space Descriptor
+ *
+ * More verbose description at:
+ * ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro)
+ */
+Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
+                      AmlMaxFixed max_fixed, AmlCacheble cacheable,
+                      AmlReadAndWrite read_and_write,
+                      uint64_t addr_gran, uint64_t addr_min,
+                      uint64_t addr_max, uint64_t addr_trans,
+                      uint64_t len)
+{
+    uint8_t flags = read_and_write | (cacheable << 1);
+
+    return aml_qword_as_desc(aml_memory_range, min_fixed, max_fixed,
+                             dec, addr_gran, addr_min, addr_max,
+                             addr_trans, len, flags);
+}
diff --git a/hw/acpi/bios-linker-loader.c b/hw/acpi/bios-linker-loader.c
index 5cc4d90c16..d9382f826a 100644
--- a/hw/acpi/bios-linker-loader.c
+++ b/hw/acpi/bios-linker-loader.c
@@ -141,6 +141,7 @@ void bios_linker_loader_add_pointer(GArray *linker,
                                     uint8_t pointer_size)
 {
     BiosLinkerLoaderEntry entry;
+    size_t offset = (gchar *)pointer - table->data;
 
     memset(&entry, 0, sizeof entry);
     strncpy(entry.pointer.dest_file, dest_file,
@@ -148,7 +149,8 @@ void bios_linker_loader_add_pointer(GArray *linker,
     strncpy(entry.pointer.src_file, src_file,
             sizeof entry.pointer.src_file - 1);
     entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER);
-    entry.pointer.offset = cpu_to_le32((gchar *)pointer - table->data);
+    assert(table->len >= offset + pointer_size);
+    entry.pointer.offset = cpu_to_le32(offset);
     entry.pointer.size = pointer_size;
     assert(pointer_size == 1 || pointer_size == 2 ||
            pointer_size == 4 || pointer_size == 8);
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 884dab3d45..5352e197cb 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -397,6 +397,20 @@ void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp)
     }
 }
 
+void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
+                                      Error **errp)
+{
+    error_setg(errp, "acpi: device unplug request for not supported device"
+               " type: %s", object_get_typename(OBJECT(dev)));
+}
+
+void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
+                              Error **errp)
+{
+    error_setg(errp, "acpi: device unplug for not supported device"
+               " type: %s", object_get_typename(OBJECT(dev)));
+}
+
 void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
 {
     ICH9LPCState *s = ICH9_LPC_DEVICE(adev);
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index ed3924126f..c6580dabb7 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -168,7 +168,8 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
 {
     MemStatus *mdev;
     Error *local_err = NULL;
-    int slot = object_property_get_int(OBJECT(dev), "slot", &local_err);
+    int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+                                       &local_err);
 
     if (local_err) {
         error_propagate(errp, local_err);
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 34dedf1e8b..612fec03ee 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -297,10 +297,11 @@ static const MemoryRegionOps acpi_pcihp_io_ops = {
     },
 };
 
-void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus,
+void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus,
                      MemoryRegion *address_space_io, bool bridges_enabled)
 {
-    uint16_t io_size = ACPI_PCIHP_SIZE;
+    s->io_len = ACPI_PCIHP_SIZE;
+    s->io_base = ACPI_PCIHP_ADDR;
 
     s->root= root_bus;
     s->legacy_piix = !bridges_enabled;
@@ -308,16 +309,21 @@ void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus,
     if (s->legacy_piix) {
         unsigned *bus_bsel = g_malloc(sizeof *bus_bsel);
 
-        io_size = ACPI_PCIHP_LEGACY_SIZE;
+        s->io_len = ACPI_PCIHP_LEGACY_SIZE;
 
         *bus_bsel = ACPI_PCIHP_BSEL_DEFAULT;
         object_property_add_uint32_ptr(OBJECT(root_bus), ACPI_PCIHP_PROP_BSEL,
                                        bus_bsel, NULL);
     }
 
-    memory_region_init_io(&s->io, NULL, &acpi_pcihp_io_ops, s,
-                          "acpi-pci-hotplug", io_size);
-    memory_region_add_subregion(address_space_io, ACPI_PCIHP_ADDR, &s->io);
+    memory_region_init_io(&s->io, owner, &acpi_pcihp_io_ops, s,
+                          "acpi-pci-hotplug", s->io_len);
+    memory_region_add_subregion(address_space_io, s->io_base, &s->io);
+
+    object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_BASE_PROP, &s->io_base,
+                                   &error_abort);
+    object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_LEN_PROP, &s->io_len,
+                                   &error_abort);
 }
 
 const VMStateDescription vmstate_acpi_pcihp_pci_status = {
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 184e7e49b9..d1f11793a0 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -370,6 +370,13 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
     }
 }
 
+static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
+                                   DeviceState *dev, Error **errp)
+{
+    error_setg(errp, "acpi: device unplug for not supported device"
+               " type: %s", object_get_typename(OBJECT(dev)));
+}
+
 static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque)
 {
     PIIX4PMState *s = opaque;
@@ -420,7 +427,7 @@ static void piix4_pm_add_propeties(PIIX4PMState *s)
                                   &s->io_base, NULL);
 }
 
-static int piix4_pm_initfn(PCIDevice *dev)
+static void piix4_pm_realize(PCIDevice *dev, Error **errp)
 {
     PIIX4PMState *s = PIIX4_PM(dev);
     uint8_t *pci_conf;
@@ -470,7 +477,6 @@ static int piix4_pm_initfn(PCIDevice *dev)
     piix4_acpi_system_hot_add_init(pci_address_space_io(dev), dev->bus, s);
 
     piix4_pm_add_propeties(s);
-    return 0;
 }
 
 Object *piix4_pm_find(void)
@@ -556,7 +562,7 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                           "acpi-gpe0", GPE_LEN);
     memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
 
-    acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent,
+    acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent,
                     s->use_acpi_pci_hotplug);
 
     acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
@@ -593,7 +599,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
     AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(klass);
 
-    k->init = piix4_pm_initfn;
+    k->realize = piix4_pm_realize;
     k->config_write = pm_write_config;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3;
@@ -610,6 +616,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
     dc->hotpluggable = false;
     hc->plug = piix4_device_plug_cb;
     hc->unplug_request = piix4_device_unplug_request_cb;
+    hc->unplug = piix4_device_unplug_cb;
     adevc->ospm_status = piix4_ospm_status;
 }
 
diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c
index 111ec0e848..b17383555e 100644
--- a/hw/audio/ac97.c
+++ b/hw/audio/ac97.c
@@ -1337,7 +1337,7 @@ static void ac97_on_reset (DeviceState *dev)
     mixer_reset (s);
 }
 
-static int ac97_initfn (PCIDevice *dev)
+static void ac97_realize(PCIDevice *dev, Error **errp)
 {
     AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, dev);
     uint8_t *c = s->dev.config;
@@ -1384,7 +1384,6 @@ static int ac97_initfn (PCIDevice *dev)
     pci_register_bar (&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm);
     AUD_register_card ("ac97", &s->card);
     ac97_on_reset (&s->dev.qdev);
-    return 0;
 }
 
 static int ac97_init (PCIBus *bus)
@@ -1403,7 +1402,7 @@ static void ac97_class_init (ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS (klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS (klass);
 
-    k->init = ac97_initfn;
+    k->realize = ac97_realize;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5;
     k->revision = 0x01;
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
index e67d1ea165..8e7bcf503e 100644
--- a/hw/audio/es1370.c
+++ b/hw/audio/es1370.c
@@ -1016,7 +1016,7 @@ static void es1370_on_reset (void *opaque)
     es1370_reset (s);
 }
 
-static int es1370_initfn (PCIDevice *dev)
+static void es1370_realize(PCIDevice *dev, Error **errp)
 {
     ES1370State *s = DO_UPCAST (ES1370State, dev, dev);
     uint8_t *c = s->dev.config;
@@ -1039,7 +1039,6 @@ static int es1370_initfn (PCIDevice *dev)
 
     AUD_register_card ("es1370", &s->card);
     es1370_reset (s);
-    return 0;
 }
 
 static int es1370_init (PCIBus *bus)
@@ -1053,7 +1052,7 @@ static void es1370_class_init (ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS (klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS (klass);
 
-    k->init = es1370_initfn;
+    k->realize = es1370_realize;
     k->vendor_id = PCI_VENDOR_ID_ENSONIQ;
     k->device_id = PCI_DEVICE_ID_ENSONIQ_ES1370;
     k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 2885231a6d..433463e9c5 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -1126,7 +1126,7 @@ static void intel_hda_reset(DeviceState *dev)
     intel_hda_update_irq(d);
 }
 
-static int intel_hda_init(PCIDevice *pci)
+static void intel_hda_realize(PCIDevice *pci, Error **errp)
 {
     IntelHDAState *d = INTEL_HDA(pci);
     uint8_t *conf = d->pci.config;
@@ -1147,8 +1147,6 @@ static int intel_hda_init(PCIDevice *pci)
 
     hda_codec_bus_init(DEVICE(pci), &d->codecs, sizeof(d->codecs),
                        intel_hda_response, intel_hda_xfer);
-
-    return 0;
 }
 
 static void intel_hda_exit(PCIDevice *pci)
@@ -1245,7 +1243,7 @@ static void intel_hda_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = intel_hda_init;
+    k->realize = intel_hda_realize;
     k->exit = intel_hda_exit;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO;
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index cb71772f95..1e5b918620 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -667,11 +667,11 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
     memset(&blkcfg, 0, sizeof(blkcfg));
     virtio_stq_p(vdev, &blkcfg.capacity, capacity);
     virtio_stl_p(vdev, &blkcfg.seg_max, 128 - 2);
-    virtio_stw_p(vdev, &blkcfg.cylinders, conf->cyls);
+    virtio_stw_p(vdev, &blkcfg.geometry.cylinders, conf->cyls);
     virtio_stl_p(vdev, &blkcfg.blk_size, blk_size);
     virtio_stw_p(vdev, &blkcfg.min_io_size, conf->min_io_size / blk_size);
     virtio_stw_p(vdev, &blkcfg.opt_io_size, conf->opt_io_size / blk_size);
-    blkcfg.heads = conf->heads;
+    blkcfg.geometry.heads = conf->heads;
     /*
      * We must ensure that the block device capacity is a multiple of
      * the logical block size. If that is not the case, let's use
@@ -684,9 +684,9 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
      * per track (cylinder).
      */
     if (blk_getlength(s->blk) /  conf->heads / conf->secs % blk_size) {
-        blkcfg.sectors = conf->secs & ~s->sector_mask;
+        blkcfg.geometry.sectors = conf->secs & ~s->sector_mask;
     } else {
-        blkcfg.sectors = conf->secs;
+        blkcfg.geometry.sectors = conf->secs;
     }
     blkcfg.size_max = 0;
     blkcfg.physical_block_exp = get_physical_block_exp(conf);
@@ -711,20 +711,20 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
 {
     VirtIOBlock *s = VIRTIO_BLK(vdev);
 
-    features |= (1 << VIRTIO_BLK_F_SEG_MAX);
-    features |= (1 << VIRTIO_BLK_F_GEOMETRY);
-    features |= (1 << VIRTIO_BLK_F_TOPOLOGY);
-    features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
-    features |= (1 << VIRTIO_BLK_F_SCSI);
+    virtio_add_feature(&features, VIRTIO_BLK_F_SEG_MAX);
+    virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY);
+    virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
+    virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
+    virtio_add_feature(&features, VIRTIO_BLK_F_SCSI);
 
     if (s->conf.config_wce) {
-        features |= (1 << VIRTIO_BLK_F_CONFIG_WCE);
+        virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
     }
     if (blk_enable_write_cache(s->blk)) {
-        features |= (1 << VIRTIO_BLK_F_WCE);
+        virtio_add_feature(&features, VIRTIO_BLK_F_WCE);
     }
     if (blk_is_read_only(s->blk)) {
-        features |= 1 << VIRTIO_BLK_F_RO;
+        virtio_add_feature(&features, VIRTIO_BLK_F_RO);
     }
 
     return features;
@@ -733,7 +733,6 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
 static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
 {
     VirtIOBlock *s = VIRTIO_BLK(vdev);
-    uint32_t features;
 
     if (s->dataplane && !(status & (VIRTIO_CONFIG_S_DRIVER |
                                     VIRTIO_CONFIG_S_DRIVER_OK))) {
@@ -744,8 +743,6 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
         return;
     }
 
-    features = vdev->guest_features;
-
     /* A guest that supports VIRTIO_BLK_F_CONFIG_WCE must be able to send
      * cache flushes.  Thus, the "auto writethrough" behavior is never
      * necessary for guests that support the VIRTIO_BLK_F_CONFIG_WCE feature.
@@ -761,10 +758,10 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
      *
      * s->blk would erroneously be placed in writethrough mode.
      */
-    if (!(features & (1 << VIRTIO_BLK_F_CONFIG_WCE))) {
+    if (!virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) {
         aio_context_acquire(blk_get_aio_context(s->blk));
         blk_set_enable_write_cache(s->blk,
-                                   !!(features & (1 << VIRTIO_BLK_F_WCE)));
+                                   virtio_has_feature(vdev, VIRTIO_BLK_F_WCE));
         aio_context_release(blk_get_aio_context(s->blk));
     }
 }
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index f05c9b4d86..467c3b4f9a 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -48,7 +48,7 @@ typedef struct PCIMultiSerialState {
     uint8_t      prog_if;
 } PCIMultiSerialState;
 
-static int serial_pci_init(PCIDevice *dev)
+static void serial_pci_realize(PCIDevice *dev, Error **errp)
 {
     PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
     SerialState *s = &pci->state;
@@ -57,9 +57,8 @@ static int serial_pci_init(PCIDevice *dev)
     s->baudbase = 115200;
     serial_realize_core(s, &err);
     if (err != NULL) {
-        qerror_report_err(err);
-        error_free(err);
-        return -1;
+        error_propagate(errp, err);
+        return;
     }
 
     pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
@@ -68,7 +67,6 @@ static int serial_pci_init(PCIDevice *dev)
 
     memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8);
     pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
-    return 0;
 }
 
 static void multi_serial_irq_mux(void *opaque, int n, int level)
@@ -85,7 +83,7 @@ static void multi_serial_irq_mux(void *opaque, int n, int level)
     pci_set_irq(&pci->dev, pending);
 }
 
-static int multi_serial_pci_init(PCIDevice *dev)
+static void multi_serial_pci_realize(PCIDevice *dev, Error **errp)
 {
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
     PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev);
@@ -116,9 +114,8 @@ static int multi_serial_pci_init(PCIDevice *dev)
         s->baudbase = 115200;
         serial_realize_core(s, &err);
         if (err != NULL) {
-            qerror_report_err(err);
-            error_free(err);
-            return -1;
+            error_propagate(errp, err);
+            return;
         }
         s->irq = pci->irqs[i];
         pci->name[i] = g_strdup_printf("uart #%d", i+1);
@@ -126,7 +123,6 @@ static int multi_serial_pci_init(PCIDevice *dev)
                               pci->name[i], 8);
         memory_region_add_subregion(&pci->iobar, 8 * i, &s->io);
     }
-    return 0;
 }
 
 static void serial_pci_exit(PCIDevice *dev)
@@ -203,7 +199,7 @@ static void serial_pci_class_initfn(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
-    pc->init = serial_pci_init;
+    pc->realize = serial_pci_realize;
     pc->exit = serial_pci_exit;
     pc->vendor_id = PCI_VENDOR_ID_REDHAT;
     pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL;
@@ -218,7 +214,7 @@ static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
-    pc->init = multi_serial_pci_init;
+    pc->realize = multi_serial_pci_realize;
     pc->exit = multi_serial_pci_exit;
     pc->vendor_id = PCI_VENDOR_ID_REDHAT;
     pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL2;
@@ -233,7 +229,7 @@ static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
-    pc->init = multi_serial_pci_init;
+    pc->realize = multi_serial_pci_realize;
     pc->exit = multi_serial_pci_exit;
     pc->vendor_id = PCI_VENDOR_ID_REDHAT;
     pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL4;
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 47fbb34bdd..9a029d2130 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -75,7 +75,7 @@ static VirtIOSerialPort *find_port_by_name(char *name)
 static bool use_multiport(VirtIOSerial *vser)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(vser);
-    return vdev->guest_features & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
+    return virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT);
 }
 
 static size_t write_to_port(VirtIOSerialPort *port,
@@ -474,7 +474,7 @@ static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
     vser = VIRTIO_SERIAL(vdev);
 
     if (vser->bus.max_nr_ports > 1) {
-        features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT);
+        virtio_add_feature(&features, VIRTIO_CONSOLE_F_MULTIPORT);
     }
     return features;
 }
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 2e47f70eb4..5a4e4d5ec8 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -990,8 +990,8 @@ int qdev_prop_check_globals(void)
     return ret;
 }
 
-void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
-                                    Error **errp)
+static void qdev_prop_set_globals_for_type(DeviceState *dev,
+                                const char *typename)
 {
     GlobalProperty *prop;
 
@@ -1004,25 +1004,22 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
         prop->used = true;
         object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
         if (err != NULL) {
-            error_propagate(errp, err);
+            assert(prop->user_provided);
+            error_report("Warning: global %s.%s=%s ignored (%s)",
+                         prop->driver, prop->property, prop->value,
+                         error_get_pretty(err));
+            error_free(err);
             return;
         }
     }
 }
 
-void qdev_prop_set_globals(DeviceState *dev, Error **errp)
+void qdev_prop_set_globals(DeviceState *dev)
 {
     ObjectClass *class = object_get_class(OBJECT(dev));
 
     do {
-        Error *err = NULL;
-
-        qdev_prop_set_globals_for_type(dev, object_class_get_name(class),
-                                       &err);
-        if (err != NULL) {
-            error_propagate(errp, err);
-            return;
-        }
+        qdev_prop_set_globals_for_type(dev, object_class_get_name(class));
         class = object_class_get_parent(class);
     } while (class);
 }
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index a02a4cb2ab..6be58669f7 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -1196,13 +1196,7 @@ static void device_initfn(Object *obj)
 
 static void device_post_init(Object *obj)
 {
-    Error *err = NULL;
-    qdev_prop_set_globals(DEVICE(obj), &err);
-    if (err) {
-        qerror_report_err(err);
-        error_free(err);
-        exit(EXIT_FAILURE);
-    }
+    qdev_prop_set_globals(DEVICE(obj));
 }
 
 /* Unlink device from bus and free the structure.  */
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index ec923c8c4b..8765a7e1d0 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -3006,7 +3006,7 @@ static const TypeInfo isa_cirrus_vga_info = {
  *
  ***************************************/
 
-static int pci_cirrus_vga_initfn(PCIDevice *dev)
+static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp)
 {
      PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
      CirrusVGAState *s = &d->cirrus_vga;
@@ -3017,9 +3017,9 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
        Also accept 8 MB/16 MB for backward compatibility. */
      if (s->vga.vram_size_mb != 4 && s->vga.vram_size_mb != 8 &&
          s->vga.vram_size_mb != 16) {
-         error_report("Invalid cirrus_vga ram size '%u'",
-                      s->vga.vram_size_mb);
-         return -1;
+         error_setg(errp, "Invalid cirrus_vga ram size '%u'",
+                    s->vga.vram_size_mb);
+         return;
      }
      /* setup VGA */
      vga_common_init(&s->vga, OBJECT(dev), true);
@@ -3044,7 +3044,6 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
      if (device_id == CIRRUS_ID_CLGD5446) {
          pci_register_bar(&d->dev, 1, 0, &s->cirrus_mmio_io);
      }
-     return 0;
 }
 
 static Property pci_vga_cirrus_properties[] = {
@@ -3058,7 +3057,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_cirrus_vga_initfn;
+    k->realize = pci_cirrus_vga_realize;
     k->romfile = VGABIOS_CIRRUS_FILENAME;
     k->vendor_id = PCI_VENDOR_ID_CIRRUS;
     k->device_id = CIRRUS_ID_CLGD5446;
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 762f75dc2d..b6d65b9487 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1913,7 +1913,7 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl)
     qxl->vram_size = pow2ceil(qxl->vram_size);
 }
 
-static int qxl_init_common(PCIQXLDevice *qxl)
+static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp)
 {
     uint8_t* config = qxl->pci.config;
     uint32_t pci_device_rev;
@@ -1945,9 +1945,9 @@ static int qxl_init_common(PCIQXLDevice *qxl)
         io_size = pow2ceil(QXL_IO_RANGE_SIZE);
         break;
     default:
-        error_report("Invalid revision %d for qxl device (max %d)",
-                     qxl->revision, QXL_DEFAULT_REVISION);
-        return -1;
+        error_setg(errp, "Invalid revision %d for qxl device (max %d)",
+                   qxl->revision, QXL_DEFAULT_REVISION);
+        return;
     }
 
     pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
@@ -2011,9 +2011,9 @@ static int qxl_init_common(PCIQXLDevice *qxl)
 
     qxl->ssd.qxl.base.sif = &qxl_interface.base;
     if (qemu_spice_add_display_interface(&qxl->ssd.qxl, qxl->vga.con) != 0) {
-        error_report("qxl interface %d.%d not supported by spice-server",
-                     SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
-        return -1;
+        error_setg(errp, "qxl interface %d.%d not supported by spice-server",
+                   SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
+        return;
     }
     qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
 
@@ -2022,15 +2022,13 @@ static int qxl_init_common(PCIQXLDevice *qxl)
 
     qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
     qxl->ssd.cursor_bh = qemu_bh_new(qemu_spice_cursor_refresh_bh, &qxl->ssd);
-
-    return 0;
 }
 
-static int qxl_init_primary(PCIDevice *dev)
+static void qxl_realize_primary(PCIDevice *dev, Error **errp)
 {
     PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
     VGACommonState *vga = &qxl->vga;
-    int rc;
+    Error *local_err = NULL;
 
     qxl->id = 0;
     qxl_init_ramsize(qxl);
@@ -2047,18 +2045,18 @@ static int qxl_init_primary(PCIDevice *dev)
     vga->con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
     qemu_spice_display_init_common(&qxl->ssd);
 
-    rc = qxl_init_common(qxl);
-    if (rc != 0) {
-        return rc;
+    qxl_realize_common(qxl, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
     }
 
     qxl->ssd.dcl.ops = &display_listener_ops;
     qxl->ssd.dcl.con = vga->con;
     register_displaychangelistener(&qxl->ssd.dcl);
-    return rc;
 }
 
-static int qxl_init_secondary(PCIDevice *dev)
+static void qxl_realize_secondary(PCIDevice *dev, Error **errp)
 {
     static int device_id = 1;
     PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
@@ -2071,7 +2069,7 @@ static int qxl_init_secondary(PCIDevice *dev)
     qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
     qxl->vga.con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
 
-    return qxl_init_common(qxl);
+    qxl_realize_common(qxl, errp);
 }
 
 static void qxl_pre_save(void *opaque)
@@ -2284,7 +2282,7 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = qxl_init_primary;
+    k->realize = qxl_realize_primary;
     k->romfile = "vgabios-qxl.bin";
     k->vendor_id = REDHAT_PCI_VENDOR_ID;
     k->device_id = QXL_DEVICE_ID_STABLE;
@@ -2309,7 +2307,7 @@ static void qxl_secondary_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = qxl_init_secondary;
+    k->realize = qxl_realize_secondary;
     k->vendor_id = REDHAT_PCI_VENDOR_ID;
     k->device_id = QXL_DEVICE_ID_STABLE;
     k->class_id = PCI_CLASS_DISPLAY_OTHER;
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index 53739e4f79..d67f748af4 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -189,7 +189,7 @@ static const MemoryRegionOps pci_vga_qext_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static int pci_std_vga_initfn(PCIDevice *dev)
+static void pci_std_vga_realize(PCIDevice *dev, Error **errp)
 {
     PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
     VGACommonState *s = &d->vga;
@@ -232,11 +232,9 @@ static int pci_std_vga_initfn(PCIDevice *dev)
         /* compatibility with pc-0.13 and older */
         vga_init_vbe(s, OBJECT(dev), pci_address_space(dev));
     }
-
-    return 0;
 }
 
-static int pci_secondary_vga_initfn(PCIDevice *dev)
+static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp)
 {
     PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
     VGACommonState *s = &d->vga;
@@ -268,7 +266,6 @@ static int pci_secondary_vga_initfn(PCIDevice *dev)
     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
     pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
 
-    return 0;
 }
 
 static void pci_secondary_vga_reset(DeviceState *dev)
@@ -298,7 +295,7 @@ static void vga_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_std_vga_initfn;
+    k->realize = pci_std_vga_realize;
     k->romfile = "vgabios-stdvga.bin";
     k->vendor_id = PCI_VENDOR_ID_QEMU;
     k->device_id = PCI_DEVICE_ID_QEMU_VGA;
@@ -314,7 +311,7 @@ static void secondary_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_secondary_vga_initfn;
+    k->realize = pci_secondary_vga_realize;
     k->vendor_id = PCI_VENDOR_ID_QEMU;
     k->device_id = PCI_DEVICE_ID_QEMU_VGA;
     k->class_id = PCI_CLASS_DISPLAY_OTHER;
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 1751f19793..c17ddd1fcd 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -1298,7 +1298,7 @@ static const MemoryRegionOps vmsvga_io_ops = {
     },
 };
 
-static int pci_vmsvga_initfn(PCIDevice *dev)
+static void pci_vmsvga_realize(PCIDevice *dev, Error **errp)
 {
     struct pci_vmsvga_state_s *s = VMWARE_SVGA(dev);
 
@@ -1323,8 +1323,6 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
         /* compatibility with pc-0.13 and older */
         vga_init_vbe(&s->chip.vga, OBJECT(dev), pci_address_space(dev));
     }
-
-    return 0;
 }
 
 static Property vga_vmware_properties[] = {
@@ -1338,7 +1336,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_vmsvga_initfn;
+    k->realize = pci_vmsvga_realize;
     k->romfile = "vgabios-vmware.bin";
     k->vendor_id = PCI_VENDOR_ID_VMWARE;
     k->device_id = SVGA_PCI_DEVICE_ID;
diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c
index 0803dc4d18..91d4d322ca 100644
--- a/hw/i2c/smbus_ich9.c
+++ b/hw/i2c/smbus_ich9.c
@@ -71,7 +71,7 @@ static void ich9_smbus_write_config(PCIDevice *d, uint32_t address,
     }
 }
 
-static int ich9_smbus_initfn(PCIDevice *d)
+static void ich9_smbus_realize(PCIDevice *d, Error **errp)
 {
     ICH9SMBState *s = ICH9_SMB_DEVICE(d);
 
@@ -84,7 +84,6 @@ static int ich9_smbus_initfn(PCIDevice *d)
     pm_smbus_init(&d->qdev, &s->smb);
     pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
                      &s->smb.io);
-    return 0;
 }
 
 static void ich9_smb_class_init(ObjectClass *klass, void *data)
@@ -98,7 +97,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_SERIAL_SMBUS;
     dc->vmsd = &vmstate_ich9_smbus;
     dc->desc = "ICH9 SMBUS Bridge";
-    k->init = ich9_smbus_initfn;
+    k->realize = ich9_smbus_realize;
     k->config_write = ich9_smbus_write_config;
     /*
      * Reason: part of ICH9 southbridge, needs to be wired up by
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 2b678ef2a6..e058a39147 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -7,10 +7,8 @@ obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
 obj-y += acpi-build.o
-hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \
-	hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \
+hw/i386/acpi-build.o: hw/i386/acpi-build.c \
 	hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \
-	hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex \
 	hw/i386/ssdt-tpm.hex
 
 iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 4944249b84..d0a5c85e10 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -54,6 +54,8 @@
 #include "hw/i386/q35-acpi-dsdt.hex"
 #include "hw/i386/acpi-dsdt.hex"
 
+#include "hw/acpi/aml-build.h"
+
 #include "qapi/qmp/qint.h"
 #include "qom/qom-qobject.h"
 #include "exec/ram_addr.h"
@@ -99,15 +101,21 @@ typedef struct AcpiPmInfo {
     uint32_t gpe0_blk;
     uint32_t gpe0_blk_len;
     uint32_t io_base;
+    uint16_t cpu_hp_io_base;
+    uint16_t cpu_hp_io_len;
+    uint16_t mem_hp_io_base;
+    uint16_t mem_hp_io_len;
+    uint16_t pcihp_io_base;
+    uint16_t pcihp_io_len;
 } AcpiPmInfo;
 
 typedef struct AcpiMiscInfo {
     bool has_hpet;
     bool has_tpm;
-    DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
     const unsigned char *dsdt_code;
     unsigned dsdt_size;
     uint16_t pvpanic_port;
+    uint16_t applesmc_io_base;
 } AcpiMiscInfo;
 
 typedef struct AcpiBuildPciBusHotplugState {
@@ -119,7 +127,6 @@ typedef struct AcpiBuildPciBusHotplugState {
 
 static void acpi_get_dsdt(AcpiMiscInfo *info)
 {
-    uint16_t *applesmc_sta;
     Object *piix = piix4_pm_find();
     Object *lpc = ich9_lpc_find();
     assert(!!piix != !!lpc);
@@ -127,17 +134,11 @@ static void acpi_get_dsdt(AcpiMiscInfo *info)
     if (piix) {
         info->dsdt_code = AcpiDsdtAmlCode;
         info->dsdt_size = sizeof AcpiDsdtAmlCode;
-        applesmc_sta = piix_dsdt_applesmc_sta;
     }
     if (lpc) {
         info->dsdt_code = Q35AcpiDsdtAmlCode;
         info->dsdt_size = sizeof Q35AcpiDsdtAmlCode;
-        applesmc_sta = q35_dsdt_applesmc_sta;
     }
-
-    /* Patch in appropriate value for AppleSMC _STA */
-    *(uint8_t *)(info->dsdt_code + *applesmc_sta) =
-        applesmc_find() ? 0x0b : 0x00;
 }
 
 static
@@ -172,14 +173,26 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
     Object *obj = NULL;
     QObject *o;
 
+    pm->pcihp_io_base = 0;
+    pm->pcihp_io_len = 0;
     if (piix) {
         obj = piix;
+        pm->cpu_hp_io_base = PIIX4_CPU_HOTPLUG_IO_BASE;
+        pm->pcihp_io_base =
+            object_property_get_int(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
+        pm->pcihp_io_len =
+            object_property_get_int(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
     }
     if (lpc) {
         obj = lpc;
+        pm->cpu_hp_io_base = ICH9_CPU_HOTPLUG_IO_BASE;
     }
     assert(obj);
 
+    pm->cpu_hp_io_len = ACPI_GPE_PROC_LEN;
+    pm->mem_hp_io_base = ACPI_MEMORY_HOTPLUG_BASE;
+    pm->mem_hp_io_len = ACPI_MEMORY_HOTPLUG_IO_LEN;
+
     /* Fill in optional s3/s4 related properties */
     o = object_property_get_qobject(obj, ACPI_PM_PROP_S3_DISABLED, NULL);
     if (o) {
@@ -228,6 +241,7 @@ static void acpi_get_misc_info(AcpiMiscInfo *info)
     info->has_hpet = hpet_find();
     info->has_tpm = tpm_find();
     info->pvpanic_port = pvpanic_port();
+    info->applesmc_io_base = applesmc_port();
 }
 
 static void acpi_get_pci_info(PcPciInfo *info)
@@ -280,208 +294,6 @@ build_header(GArray *linker, GArray *table_data,
                                     table_data->data, h, len, &h->checksum);
 }
 
-static inline GArray *build_alloc_array(void)
-{
-    return g_array_new(false, true /* clear */, 1);
-}
-
-static inline void build_free_array(GArray *array)
-{
-    g_array_free(array, true);
-}
-
-static inline void build_prepend_byte(GArray *array, uint8_t val)
-{
-    g_array_prepend_val(array, val);
-}
-
-static inline void build_append_byte(GArray *array, uint8_t val)
-{
-    g_array_append_val(array, val);
-}
-
-static inline void build_append_array(GArray *array, GArray *val)
-{
-    g_array_append_vals(array, val->data, val->len);
-}
-
-#define ACPI_NAMESEG_LEN 4
-
-static void GCC_FMT_ATTR(2, 3)
-build_append_nameseg(GArray *array, const char *format, ...)
-{
-    /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
-    char s[] = "XXXX";
-    int len;
-    va_list args;
-
-    va_start(args, format);
-    len = vsnprintf(s, sizeof s, format, args);
-    va_end(args);
-
-    assert(len <= ACPI_NAMESEG_LEN);
-
-    g_array_append_vals(array, s, len);
-    /* Pad up to ACPI_NAMESEG_LEN characters if necessary. */
-    g_array_append_vals(array, "____", ACPI_NAMESEG_LEN - len);
-}
-
-/* 5.4 Definition Block Encoding */
-enum {
-    PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */
-    PACKAGE_LENGTH_2BYTE_SHIFT = 4,
-    PACKAGE_LENGTH_3BYTE_SHIFT = 12,
-    PACKAGE_LENGTH_4BYTE_SHIFT = 20,
-};
-
-static void build_prepend_package_length(GArray *package, unsigned min_bytes)
-{
-    uint8_t byte;
-    unsigned length = package->len;
-    unsigned length_bytes;
-
-    if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) {
-        length_bytes = 1;
-    } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) {
-        length_bytes = 2;
-    } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) {
-        length_bytes = 3;
-    } else {
-        length_bytes = 4;
-    }
-
-    /* Force length to at least min_bytes.
-     * This wastes memory but that's how bios did it.
-     */
-    length_bytes = MAX(length_bytes, min_bytes);
-
-    /* PkgLength is the length of the inclusive length of the data. */
-    length += length_bytes;
-
-    switch (length_bytes) {
-    case 1:
-        byte = length;
-        build_prepend_byte(package, byte);
-        return;
-    case 4:
-        byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT;
-        build_prepend_byte(package, byte);
-        length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1;
-        /* fall through */
-    case 3:
-        byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT;
-        build_prepend_byte(package, byte);
-        length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1;
-        /* fall through */
-    case 2:
-        byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT;
-        build_prepend_byte(package, byte);
-        length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1;
-        /* fall through */
-    }
-    /*
-     * Most significant two bits of byte zero indicate how many following bytes
-     * are in PkgLength encoding.
-     */
-    byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length;
-    build_prepend_byte(package, byte);
-}
-
-static void build_package(GArray *package, uint8_t op, unsigned min_bytes)
-{
-    build_prepend_package_length(package, min_bytes);
-    build_prepend_byte(package, op);
-}
-
-static void build_extop_package(GArray *package, uint8_t op)
-{
-    build_package(package, op, 1);
-    build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
-}
-
-static void build_append_value(GArray *table, uint32_t value, int size)
-{
-    uint8_t prefix;
-    int i;
-
-    switch (size) {
-    case 1:
-        prefix = 0x0A; /* BytePrefix */
-        break;
-    case 2:
-        prefix = 0x0B; /* WordPrefix */
-        break;
-    case 4:
-        prefix = 0x0C; /* DWordPrefix */
-        break;
-    default:
-        assert(0);
-        return;
-    }
-    build_append_byte(table, prefix);
-    for (i = 0; i < size; ++i) {
-        build_append_byte(table, value & 0xFF);
-        value = value >> 8;
-    }
-}
-
-static void build_append_int(GArray *table, uint32_t value)
-{
-    if (value == 0x00) {
-        build_append_byte(table, 0x00); /* ZeroOp */
-    } else if (value == 0x01) {
-        build_append_byte(table, 0x01); /* OneOp */
-    } else if (value <= 0xFF) {
-        build_append_value(table, value, 1);
-    } else if (value <= 0xFFFF) {
-        build_append_value(table, value, 2);
-    } else {
-        build_append_value(table, value, 4);
-    }
-}
-
-static GArray *build_alloc_method(const char *name, uint8_t arg_count)
-{
-    GArray *method = build_alloc_array();
-
-    build_append_nameseg(method, "%s", name);
-    build_append_byte(method, arg_count); /* MethodFlags: ArgCount */
-
-    return method;
-}
-
-static void build_append_and_cleanup_method(GArray *device, GArray *method)
-{
-    uint8_t op = 0x14; /* MethodOp */
-
-    build_package(method, op, 0);
-
-    build_append_array(device, method);
-    build_free_array(method);
-}
-
-static void build_append_notify_target_ifequal(GArray *method,
-                                               GArray *target_name,
-                                               uint32_t value, int size)
-{
-    GArray *notify = build_alloc_array();
-    uint8_t op = 0xA0; /* IfOp */
-
-    build_append_byte(notify, 0x93); /* LEqualOp */
-    build_append_byte(notify, 0x68); /* Arg0Op */
-    build_append_value(notify, value, size);
-    build_append_byte(notify, 0x86); /* NotifyOp */
-    build_append_array(notify, target_name);
-    build_append_byte(notify, 0x69); /* Arg1Op */
-
-    /* Pack it up */
-    build_package(notify, op, 1);
-
-    build_append_array(method, notify);
-
-    build_free_array(notify);
-}
-
 /* End here */
 #define ACPI_PORT_SMI_CMD           0x00b2 /* TODO: this is APM_CNT_IOPORT */
 
@@ -508,24 +320,6 @@ static void acpi_align_size(GArray *blob, unsigned align)
     g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
 }
 
-/* Set a value within table in a safe manner */
-#define ACPI_BUILD_SET_LE(table, size, off, bits, val) \
-    do { \
-        uint64_t ACPI_BUILD_SET_LE_val = cpu_to_le64(val); \
-        memcpy(acpi_data_get_ptr(table, size, off, \
-                                 (bits) / BITS_PER_BYTE), \
-               &ACPI_BUILD_SET_LE_val, \
-               (bits) / BITS_PER_BYTE); \
-    } while (0)
-
-static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size,
-                                      unsigned off, unsigned size)
-{
-    assert(off + size > off);
-    assert(off + size <= table_size);
-    return table_data + off;
-}
-
 static inline void acpi_add_table(GArray *table_offsets, GArray *table_data)
 {
     uint32_t offset = cpu_to_le32(table_data->len);
@@ -673,115 +467,8 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
                  table_data->len - madt_start, 1);
 }
 
-/* Encode a hex value */
-static inline char acpi_get_hex(uint32_t val)
-{
-    val &= 0x0f;
-    return (val <= 9) ? ('0' + val) : ('A' + val - 10);
-}
-
-#include "hw/i386/ssdt-proc.hex"
-
-/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */
-#define ACPI_PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2)
-#define ACPI_PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4)
-#define ACPI_PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start)
-#define ACPI_PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start)
-#define ACPI_PROC_AML (ssdp_proc_aml + *ssdt_proc_start)
-
-/* 0x5B 0x82 DeviceOp PkgLength NameString */
-#define ACPI_PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1)
-#define ACPI_PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start)
-#define ACPI_PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start)
-#define ACPI_PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start)
-#define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
-#define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
-
-#define ACPI_PCINOHP_OFFSET_HEX (*ssdt_pcinohp_name - *ssdt_pcinohp_start + 1)
-#define ACPI_PCINOHP_OFFSET_ADR (*ssdt_pcinohp_adr - *ssdt_pcinohp_start)
-#define ACPI_PCINOHP_SIZEOF (*ssdt_pcinohp_end - *ssdt_pcinohp_start)
-#define ACPI_PCINOHP_AML (ssdp_pcihp_aml + *ssdt_pcinohp_start)
-
-#define ACPI_PCIVGA_OFFSET_HEX (*ssdt_pcivga_name - *ssdt_pcivga_start + 1)
-#define ACPI_PCIVGA_OFFSET_ADR (*ssdt_pcivga_adr - *ssdt_pcivga_start)
-#define ACPI_PCIVGA_SIZEOF (*ssdt_pcivga_end - *ssdt_pcivga_start)
-#define ACPI_PCIVGA_AML (ssdp_pcihp_aml + *ssdt_pcivga_start)
-
-#define ACPI_PCIQXL_OFFSET_HEX (*ssdt_pciqxl_name - *ssdt_pciqxl_start + 1)
-#define ACPI_PCIQXL_OFFSET_ADR (*ssdt_pciqxl_adr - *ssdt_pciqxl_start)
-#define ACPI_PCIQXL_SIZEOF (*ssdt_pciqxl_end - *ssdt_pciqxl_start)
-#define ACPI_PCIQXL_AML (ssdp_pcihp_aml + *ssdt_pciqxl_start)
-
-#include "hw/i386/ssdt-mem.hex"
-
-/* 0x5B 0x82 DeviceOp PkgLength NameString DimmID */
-#define ACPI_MEM_OFFSET_HEX (*ssdt_mem_name - *ssdt_mem_start + 2)
-#define ACPI_MEM_OFFSET_ID (*ssdt_mem_id - *ssdt_mem_start + 7)
-#define ACPI_MEM_SIZEOF (*ssdt_mem_end - *ssdt_mem_start)
-#define ACPI_MEM_AML (ssdm_mem_aml + *ssdt_mem_start)
-
-#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
-#define ACPI_SSDT_HEADER_LENGTH 36
-
-#include "hw/i386/ssdt-misc.hex"
-#include "hw/i386/ssdt-pcihp.hex"
 #include "hw/i386/ssdt-tpm.hex"
 
-static void
-build_append_notify_method(GArray *device, const char *name,
-                           const char *format, int count)
-{
-    int i;
-    GArray *method = build_alloc_method(name, 2);
-
-    for (i = 0; i < count; i++) {
-        GArray *target = build_alloc_array();
-        build_append_nameseg(target, format, i);
-        assert(i < 256); /* Fits in 1 byte */
-        build_append_notify_target_ifequal(method, target, i, 1);
-        build_free_array(target);
-    }
-
-    build_append_and_cleanup_method(device, method);
-}
-
-static void patch_pcihp(int slot, uint8_t *ssdt_ptr)
-{
-    unsigned devfn = PCI_DEVFN(slot, 0);
-
-    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
-    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX + 1] = acpi_get_hex(devfn);
-    ssdt_ptr[ACPI_PCIHP_OFFSET_ID] = slot;
-    ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
-}
-
-static void patch_pcinohp(int slot, uint8_t *ssdt_ptr)
-{
-    unsigned devfn = PCI_DEVFN(slot, 0);
-
-    ssdt_ptr[ACPI_PCINOHP_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
-    ssdt_ptr[ACPI_PCINOHP_OFFSET_HEX + 1] = acpi_get_hex(devfn);
-    ssdt_ptr[ACPI_PCINOHP_OFFSET_ADR + 2] = slot;
-}
-
-static void patch_pcivga(int slot, uint8_t *ssdt_ptr)
-{
-    unsigned devfn = PCI_DEVFN(slot, 0);
-
-    ssdt_ptr[ACPI_PCIVGA_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
-    ssdt_ptr[ACPI_PCIVGA_OFFSET_HEX + 1] = acpi_get_hex(devfn);
-    ssdt_ptr[ACPI_PCIVGA_OFFSET_ADR + 2] = slot;
-}
-
-static void patch_pciqxl(int slot, uint8_t *ssdt_ptr)
-{
-    unsigned devfn = PCI_DEVFN(slot, 0);
-
-    ssdt_ptr[ACPI_PCIQXL_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
-    ssdt_ptr[ACPI_PCIQXL_OFFSET_HEX + 1] = acpi_get_hex(devfn);
-    ssdt_ptr[ACPI_PCIQXL_OFFSET_ADR + 2] = slot;
-}
-
 /* Assign BSEL property to all buses.  In the future, this can be changed
  * to only assign to buses that support hotplug.
  */
@@ -812,261 +499,155 @@ static void acpi_set_pci_info(void)
     }
 }
 
-static void build_pci_bus_state_init(AcpiBuildPciBusHotplugState *state,
-                                     AcpiBuildPciBusHotplugState *parent,
-                                     bool pcihp_bridge_en)
-{
-    state->parent = parent;
-    state->device_table = build_alloc_array();
-    state->notify_table = build_alloc_array();
-    state->pcihp_bridge_en = pcihp_bridge_en;
-}
-
-static void build_pci_bus_state_cleanup(AcpiBuildPciBusHotplugState *state)
+static void build_append_pcihp_notify_entry(Aml *method, int slot)
 {
-    build_free_array(state->device_table);
-    build_free_array(state->notify_table);
-}
-
-static void *build_pci_bus_begin(PCIBus *bus, void *parent_state)
-{
-    AcpiBuildPciBusHotplugState *parent = parent_state;
-    AcpiBuildPciBusHotplugState *child = g_malloc(sizeof *child);
-
-    build_pci_bus_state_init(child, parent, parent->pcihp_bridge_en);
+    Aml *if_ctx;
+    int32_t devfn = PCI_DEVFN(slot, 0);
 
-    return child;
+    if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot)));
+    aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1)));
+    aml_append(method, if_ctx);
 }
 
-static void build_pci_bus_end(PCIBus *bus, void *bus_state)
+static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
+                                         bool pcihp_bridge_en)
 {
-    AcpiBuildPciBusHotplugState *child = bus_state;
-    AcpiBuildPciBusHotplugState *parent = child->parent;
-    GArray *bus_table = build_alloc_array();
-    DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
-    DECLARE_BITMAP(slot_device_present, PCI_SLOT_MAX);
-    DECLARE_BITMAP(slot_device_system, PCI_SLOT_MAX);
-    DECLARE_BITMAP(slot_device_vga, PCI_SLOT_MAX);
-    DECLARE_BITMAP(slot_device_qxl, PCI_SLOT_MAX);
-    uint8_t op;
-    int i;
+    Aml *dev, *notify_method, *method;
     QObject *bsel;
-    GArray *method;
-    bool bus_hotplug_support = false;
-
-    /*
-     * Skip bridge subtree creation if bridge hotplug is disabled
-     * to make acpi tables compatible with legacy machine types.
-     */
-    if (!child->pcihp_bridge_en && bus->parent_dev) {
-        return;
-    }
-
-    if (bus->parent_dev) {
-        op = 0x82; /* DeviceOp */
-        build_append_nameseg(bus_table, "S%.02X",
-                             bus->parent_dev->devfn);
-        build_append_byte(bus_table, 0x08); /* NameOp */
-        build_append_nameseg(bus_table, "_SUN");
-        build_append_value(bus_table, PCI_SLOT(bus->parent_dev->devfn), 1);
-        build_append_byte(bus_table, 0x08); /* NameOp */
-        build_append_nameseg(bus_table, "_ADR");
-        build_append_value(bus_table, (PCI_SLOT(bus->parent_dev->devfn) << 16) |
-                           PCI_FUNC(bus->parent_dev->devfn), 4);
-    } else {
-        op = 0x10; /* ScopeOp */;
-        build_append_nameseg(bus_table, "PCI0");
-    }
+    PCIBus *sec;
+    int i;
 
     bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
     if (bsel) {
-        build_append_byte(bus_table, 0x08); /* NameOp */
-        build_append_nameseg(bus_table, "BSEL");
-        build_append_int(bus_table, qint_get_int(qobject_to_qint(bsel)));
-        memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable);
-    } else {
-        /* No bsel - no slots are hot-pluggable */
-        memset(slot_hotplug_enable, 0x00, sizeof slot_hotplug_enable);
-    }
+        int64_t bsel_val = qint_get_int(qobject_to_qint(bsel));
 
-    memset(slot_device_present, 0x00, sizeof slot_device_present);
-    memset(slot_device_system, 0x00, sizeof slot_device_present);
-    memset(slot_device_vga, 0x00, sizeof slot_device_vga);
-    memset(slot_device_qxl, 0x00, sizeof slot_device_qxl);
+        aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
+        notify_method = aml_method("DVNT", 2);
+    }
 
     for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
         DeviceClass *dc;
         PCIDeviceClass *pc;
         PCIDevice *pdev = bus->devices[i];
         int slot = PCI_SLOT(i);
+        bool hotplug_enabled_dev;
         bool bridge_in_acpi;
 
         if (!pdev) {
+            if (bsel) { /* add hotplug slots for non present devices */
+                dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
+                aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
+                aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
+                method = aml_method("_EJ0", 1);
+                aml_append(method,
+                    aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
+                );
+                aml_append(dev, method);
+                aml_append(parent_scope, dev);
+
+                build_append_pcihp_notify_entry(notify_method, slot);
+            }
             continue;
         }
 
-        set_bit(slot, slot_device_present);
         pc = PCI_DEVICE_GET_CLASS(pdev);
         dc = DEVICE_GET_CLASS(pdev);
 
         /* When hotplug for bridges is enabled, bridges are
          * described in ACPI separately (see build_pci_bus_end).
          * In this case they aren't themselves hot-pluggable.
+         * Hotplugged bridges *are* hot-pluggable.
          */
-        bridge_in_acpi = pc->is_bridge && child->pcihp_bridge_en;
+        bridge_in_acpi = pc->is_bridge && pcihp_bridge_en &&
+            !DEVICE(pdev)->hotplugged;
 
-        if (pc->class_id == PCI_CLASS_BRIDGE_ISA || bridge_in_acpi) {
-            set_bit(slot, slot_device_system);
+        hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi;
+
+        if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
+            continue;
         }
 
+        /* start to compose PCI slot descriptor */
+        dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
+        aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
+
         if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
-            set_bit(slot, slot_device_vga);
+            /* add VGA specific AML methods */
+            int s3d;
 
             if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {
-                set_bit(slot, slot_device_qxl);
+                s3d = 3;
+            } else {
+                s3d = 0;
             }
-        }
 
-        if (!dc->hotpluggable || bridge_in_acpi) {
-            clear_bit(slot, slot_hotplug_enable);
-        }
-    }
+            method = aml_method("_S1D", 0);
+            aml_append(method, aml_return(aml_int(0)));
+            aml_append(dev, method);
+
+            method = aml_method("_S2D", 0);
+            aml_append(method, aml_return(aml_int(0)));
+            aml_append(dev, method);
+
+            method = aml_method("_S3D", 0);
+            aml_append(method, aml_return(aml_int(s3d)));
+            aml_append(dev, method);
+        } else if (hotplug_enabled_dev) {
+            /* add _SUN/_EJ0 to make slot hotpluggable  */
+            aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
+
+            method = aml_method("_EJ0", 1);
+            aml_append(method,
+                aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
+            );
+            aml_append(dev, method);
+
+            if (bsel) {
+                build_append_pcihp_notify_entry(notify_method, slot);
+            }
+        } else if (bridge_in_acpi) {
+            /*
+             * device is coldplugged bridge,
+             * add child device descriptions into its scope
+             */
+            PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
 
-    /* Append Device object for each slot */
-    for (i = 0; i < PCI_SLOT_MAX; i++) {
-        bool can_eject = test_bit(i, slot_hotplug_enable);
-        bool present = test_bit(i, slot_device_present);
-        bool vga = test_bit(i, slot_device_vga);
-        bool qxl = test_bit(i, slot_device_qxl);
-        bool system = test_bit(i, slot_device_system);
-        if (can_eject) {
-            void *pcihp = acpi_data_push(bus_table,
-                                         ACPI_PCIHP_SIZEOF);
-            memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
-            patch_pcihp(i, pcihp);
-            bus_hotplug_support = true;
-        } else if (qxl) {
-            void *pcihp = acpi_data_push(bus_table,
-                                         ACPI_PCIQXL_SIZEOF);
-            memcpy(pcihp, ACPI_PCIQXL_AML, ACPI_PCIQXL_SIZEOF);
-            patch_pciqxl(i, pcihp);
-        } else if (vga) {
-            void *pcihp = acpi_data_push(bus_table,
-                                         ACPI_PCIVGA_SIZEOF);
-            memcpy(pcihp, ACPI_PCIVGA_AML, ACPI_PCIVGA_SIZEOF);
-            patch_pcivga(i, pcihp);
-        } else if (system) {
-            /* Nothing to do: system devices are in DSDT or in SSDT above. */
-        } else if (present) {
-            void *pcihp = acpi_data_push(bus_table,
-                                         ACPI_PCINOHP_SIZEOF);
-            memcpy(pcihp, ACPI_PCINOHP_AML, ACPI_PCINOHP_SIZEOF);
-            patch_pcinohp(i, pcihp);
+            build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en);
         }
+        /* slot descriptor has been composed, add it into parent context */
+        aml_append(parent_scope, dev);
     }
 
     if (bsel) {
-        method = build_alloc_method("DVNT", 2);
-
-        for (i = 0; i < PCI_SLOT_MAX; i++) {
-            GArray *notify;
-            uint8_t op;
-
-            if (!test_bit(i, slot_hotplug_enable)) {
-                continue;
-            }
-
-            notify = build_alloc_array();
-            op = 0xA0; /* IfOp */
-
-            build_append_byte(notify, 0x7B); /* AndOp */
-            build_append_byte(notify, 0x68); /* Arg0Op */
-            build_append_int(notify, 0x1U << i);
-            build_append_byte(notify, 0x00); /* NullName */
-            build_append_byte(notify, 0x86); /* NotifyOp */
-            build_append_nameseg(notify, "S%.02X", PCI_DEVFN(i, 0));
-            build_append_byte(notify, 0x69); /* Arg1Op */
-
-            /* Pack it up */
-            build_package(notify, op, 0);
-
-            build_append_array(method, notify);
-
-            build_free_array(notify);
-        }
-
-        build_append_and_cleanup_method(bus_table, method);
+        aml_append(parent_scope, notify_method);
     }
 
     /* Append PCNT method to notify about events on local and child buses.
      * Add unconditionally for root since DSDT expects it.
      */
-    if (bus_hotplug_support || child->notify_table->len || !bus->parent_dev) {
-        method = build_alloc_method("PCNT", 0);
-
-        /* If bus supports hotplug select it and notify about local events */
-        if (bsel) {
-            build_append_byte(method, 0x70); /* StoreOp */
-            build_append_int(method, qint_get_int(qobject_to_qint(bsel)));
-            build_append_nameseg(method, "BNUM");
-            build_append_nameseg(method, "DVNT");
-            build_append_nameseg(method, "PCIU");
-            build_append_int(method, 1); /* Device Check */
-            build_append_nameseg(method, "DVNT");
-            build_append_nameseg(method, "PCID");
-            build_append_int(method, 3); /* Eject Request */
-        }
-
-        /* Notify about child bus events in any case */
-        build_append_array(method, child->notify_table);
-
-        build_append_and_cleanup_method(bus_table, method);
+    method = aml_method("PCNT", 0);
 
-        /* Append description of child buses */
-        build_append_array(bus_table, child->device_table);
-
-        /* Pack it up */
-        if (bus->parent_dev) {
-            build_extop_package(bus_table, op);
-        } else {
-            build_package(bus_table, op, 0);
-        }
-
-        /* Append our bus description to parent table */
-        build_append_array(parent->device_table, bus_table);
-
-        /* Also tell parent how to notify us, invoking PCNT method.
-         * At the moment this is not needed for root as we have a single root.
-         */
-        if (bus->parent_dev) {
-            build_append_byte(parent->notify_table, '^'); /* ParentPrefixChar */
-            build_append_byte(parent->notify_table, 0x2E); /* DualNamePrefix */
-            build_append_nameseg(parent->notify_table, "S%.02X",
-                                 bus->parent_dev->devfn);
-            build_append_nameseg(parent->notify_table, "PCNT");
-        }
+    /* If bus supports hotplug select it and notify about local events */
+    if (bsel) {
+        int64_t bsel_val = qint_get_int(qobject_to_qint(bsel));
+        aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
+        aml_append(method,
+            aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */)
+        );
+        aml_append(method,
+            aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request */)
+        );
     }
 
-    qobject_decref(bsel);
-    build_free_array(bus_table);
-    build_pci_bus_state_cleanup(child);
-    g_free(child);
-}
-
-static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size)
-{
-    ACPI_BUILD_SET_LE(start, size, acpi_pci32_start[0], 32, pci->w32.begin);
-
-    ACPI_BUILD_SET_LE(start, size, acpi_pci32_end[0], 32, pci->w32.end - 1);
+    /* Notify about child bus events in any case */
+    if (pcihp_bridge_en) {
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            int32_t devfn = sec->parent_dev->devfn;
 
-    if (pci->w64.end || pci->w64.begin) {
-        ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 1);
-        ACPI_BUILD_SET_LE(start, size, acpi_pci64_start[0], 64, pci->w64.begin);
-        ACPI_BUILD_SET_LE(start, size, acpi_pci64_end[0], 64, pci->w64.end - 1);
-        ACPI_BUILD_SET_LE(start, size, acpi_pci64_length[0], 64, pci->w64.end - pci->w64.begin);
-    } else {
-        ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 0);
+            aml_append(method, aml_name("^S%.02X.PCNT", devfn));
+        }
     }
+    aml_append(parent_scope, method);
 }
 
 static void
@@ -1077,112 +658,337 @@ build_ssdt(GArray *table_data, GArray *linker,
     MachineState *machine = MACHINE(qdev_get_machine());
     uint32_t nr_mem = machine->ram_slots;
     unsigned acpi_cpus = guest_info->apic_id_limit;
-    int ssdt_start = table_data->len;
-    uint8_t *ssdt_ptr;
+    Aml *ssdt, *sb_scope, *scope, *pkg, *dev, *method, *crs, *field, *ifctx;
     int i;
 
+    ssdt = init_aml_allocator();
     /* The current AML generator can cover the APIC ID range [0..255],
      * inclusive, for VCPU hotplug. */
     QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
     g_assert(acpi_cpus <= ACPI_CPU_HOTPLUG_ID_LIMIT);
 
-    /* Copy header and patch values in the S3_ / S4_ / S5_ packages */
-    ssdt_ptr = acpi_data_push(table_data, sizeof(ssdp_misc_aml));
-    memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml));
-    if (pm->s3_disabled) {
-        ssdt_ptr[acpi_s3_name[0]] = 'X';
+    /* Reserve space for header */
+    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
+
+    scope = aml_scope("\\_SB.PCI0");
+    /* build PCI0._CRS */
+    crs = aml_resource_template();
+    aml_append(crs,
+        aml_word_bus_number(aml_min_fixed, aml_max_fixed, aml_pos_decode,
+                            0x0000, 0x0000, 0x00FF, 0x0000, 0x0100));
+    aml_append(crs, aml_io(aml_decode16, 0x0CF8, 0x0CF8, 0x01, 0x08));
+
+    aml_append(crs,
+        aml_word_io(aml_min_fixed, aml_max_fixed,
+                    aml_pos_decode, aml_entire_range,
+                    0x0000, 0x0000, 0x0CF7, 0x0000, 0x0CF8));
+    aml_append(crs,
+        aml_word_io(aml_min_fixed, aml_max_fixed,
+                    aml_pos_decode, aml_entire_range,
+                    0x0000, 0x0D00, 0xFFFF, 0x0000, 0xF300));
+    aml_append(crs,
+        aml_dword_memory(aml_pos_decode, aml_min_fixed, aml_max_fixed,
+                         aml_cacheable, aml_ReadWrite,
+                         0, 0x000A0000, 0x000BFFFF, 0, 0x00020000));
+    aml_append(crs,
+        aml_dword_memory(aml_pos_decode, aml_min_fixed, aml_max_fixed,
+                         aml_non_cacheable, aml_ReadWrite,
+                         0, pci->w32.begin, pci->w32.end - 1, 0,
+                         pci->w32.end - pci->w32.begin));
+    if (pci->w64.begin) {
+        aml_append(crs,
+            aml_qword_memory(aml_pos_decode, aml_min_fixed, aml_max_fixed,
+                             aml_cacheable, aml_ReadWrite,
+                             0, pci->w64.begin, pci->w64.end - 1, 0,
+                             pci->w64.end - pci->w64.begin));
     }
-    if (pm->s4_disabled) {
-        ssdt_ptr[acpi_s4_name[0]] = 'X';
-    } else {
-        ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt_ptr[acpi_s4_pkg[0] + 3] =
-            pm->s4_val;
+    aml_append(scope, aml_name_decl("_CRS", crs));
+
+    /* reserve GPE0 block resources */
+    dev = aml_device("GPE0");
+    aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06")));
+    aml_append(dev, aml_name_decl("_UID", aml_string("GPE0 resources")));
+    /* device present, functioning, decoding, not shown in UI */
+    aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
+    crs = aml_resource_template();
+    aml_append(crs,
+        aml_io(aml_decode16, pm->gpe0_blk, pm->gpe0_blk, 1, pm->gpe0_blk_len)
+    );
+    aml_append(dev, aml_name_decl("_CRS", crs));
+    aml_append(scope, dev);
+
+    /* reserve PCIHP resources */
+    if (pm->pcihp_io_len) {
+        dev = aml_device("PHPR");
+        aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06")));
+        aml_append(dev,
+            aml_name_decl("_UID", aml_string("PCI Hotplug resources")));
+        /* device present, functioning, decoding, not shown in UI */
+        aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
+        crs = aml_resource_template();
+        aml_append(crs,
+            aml_io(aml_decode16, pm->pcihp_io_base, pm->pcihp_io_base, 1,
+                   pm->pcihp_io_len)
+        );
+        aml_append(dev, aml_name_decl("_CRS", crs));
+        aml_append(scope, dev);
+    }
+    aml_append(ssdt, scope);
+
+    /*  create S3_ / S4_ / S5_ packages if necessary */
+    scope = aml_scope("\\");
+    if (!pm->s3_disabled) {
+        pkg = aml_package(4);
+        aml_append(pkg, aml_int(1)); /* PM1a_CNT.SLP_TYP */
+        aml_append(pkg, aml_int(1)); /* PM1b_CNT.SLP_TYP, FIXME: not impl. */
+        aml_append(pkg, aml_int(0)); /* reserved */
+        aml_append(pkg, aml_int(0)); /* reserved */
+        aml_append(scope, aml_name_decl("_S3", pkg));
     }
 
-    patch_pci_windows(pci, ssdt_ptr, sizeof(ssdp_misc_aml));
+    if (!pm->s4_disabled) {
+        pkg = aml_package(4);
+        aml_append(pkg, aml_int(pm->s4_val)); /* PM1a_CNT.SLP_TYP */
+        /* PM1b_CNT.SLP_TYP, FIXME: not impl. */
+        aml_append(pkg, aml_int(pm->s4_val));
+        aml_append(pkg, aml_int(0)); /* reserved */
+        aml_append(pkg, aml_int(0)); /* reserved */
+        aml_append(scope, aml_name_decl("_S4", pkg));
+    }
 
-    ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml),
-                      ssdt_isa_pest[0], 16, misc->pvpanic_port);
+    pkg = aml_package(4);
+    aml_append(pkg, aml_int(0)); /* PM1a_CNT.SLP_TYP */
+    aml_append(pkg, aml_int(0)); /* PM1b_CNT.SLP_TYP not impl. */
+    aml_append(pkg, aml_int(0)); /* reserved */
+    aml_append(pkg, aml_int(0)); /* reserved */
+    aml_append(scope, aml_name_decl("_S5", pkg));
+    aml_append(ssdt, scope);
+
+    if (misc->applesmc_io_base) {
+        scope = aml_scope("\\_SB.PCI0.ISA");
+        dev = aml_device("SMC");
+
+        aml_append(dev, aml_name_decl("_HID", aml_eisaid("APP0001")));
+        /* device present, functioning, decoding, not shown in UI */
+        aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
+
+        crs = aml_resource_template();
+        aml_append(crs,
+            aml_io(aml_decode16, misc->applesmc_io_base, misc->applesmc_io_base,
+                   0x01, APPLESMC_MAX_DATA_LENGTH)
+        );
+        aml_append(crs, aml_irq_no_flags(6));
+        aml_append(dev, aml_name_decl("_CRS", crs));
+
+        aml_append(scope, dev);
+        aml_append(ssdt, scope);
+    }
 
-    ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml),
-                      ssdt_mctrl_nr_slots[0], 32, nr_mem);
+    if (misc->pvpanic_port) {
+        scope = aml_scope("\\_SB.PCI0.ISA");
 
-    {
-        GArray *sb_scope = build_alloc_array();
-        uint8_t op = 0x10; /* ScopeOp */
+        dev = aml_device("PEVR");
+        aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002")));
+
+        crs = aml_resource_template();
+        aml_append(crs,
+            aml_io(aml_decode16, misc->pvpanic_port, misc->pvpanic_port, 1, 1)
+        );
+        aml_append(dev, aml_name_decl("_CRS", crs));
 
-        build_append_nameseg(sb_scope, "_SB");
+        aml_append(dev, aml_operation_region("PEOR", aml_system_io,
+                                              misc->pvpanic_port, 1));
+        field = aml_field("PEOR", aml_byte_acc);
+        aml_append(field, aml_named_field("PEPT", 8));
+        aml_append(dev, field);
+
+        method = aml_method("RDPT", 0);
+        aml_append(method, aml_store(aml_name("PEPT"), aml_local(0)));
+        aml_append(method, aml_return(aml_local(0)));
+        aml_append(dev, method);
+
+        method = aml_method("WRPT", 1);
+        aml_append(method, aml_store(aml_arg(0), aml_name("PEPT")));
+        aml_append(dev, method);
+
+        aml_append(scope, dev);
+        aml_append(ssdt, scope);
+    }
+
+    sb_scope = aml_scope("_SB");
+    {
+        /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
+        dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
+        aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06")));
+        aml_append(dev,
+            aml_name_decl("_UID", aml_string("CPU Hotplug resources"))
+        );
+        /* device present, functioning, decoding, not shown in UI */
+        aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
+        crs = aml_resource_template();
+        aml_append(crs,
+            aml_io(aml_decode16, pm->cpu_hp_io_base, pm->cpu_hp_io_base, 1,
+                   pm->cpu_hp_io_len)
+        );
+        aml_append(dev, aml_name_decl("_CRS", crs));
+        aml_append(sb_scope, dev);
+        /* declare CPU hotplug MMIO region and PRS field to access it */
+        aml_append(sb_scope, aml_operation_region(
+            "PRST", aml_system_io, pm->cpu_hp_io_base, pm->cpu_hp_io_len));
+        field = aml_field("PRST", aml_byte_acc);
+        aml_append(field, aml_named_field("PRS", 256));
+        aml_append(sb_scope, field);
 
         /* build Processor object for each processor */
         for (i = 0; i < acpi_cpus; i++) {
-            uint8_t *proc = acpi_data_push(sb_scope, ACPI_PROC_SIZEOF);
-            memcpy(proc, ACPI_PROC_AML, ACPI_PROC_SIZEOF);
-            proc[ACPI_PROC_OFFSET_CPUHEX] = acpi_get_hex(i >> 4);
-            proc[ACPI_PROC_OFFSET_CPUHEX+1] = acpi_get_hex(i);
-            proc[ACPI_PROC_OFFSET_CPUID1] = i;
-            proc[ACPI_PROC_OFFSET_CPUID2] = i;
+            dev = aml_processor(i, 0, 0, "CP%.02X", i);
+
+            method = aml_method("_MAT", 0);
+            aml_append(method, aml_return(aml_call1("CPMA", aml_int(i))));
+            aml_append(dev, method);
+
+            method = aml_method("_STA", 0);
+            aml_append(method, aml_return(aml_call1("CPST", aml_int(i))));
+            aml_append(dev, method);
+
+            method = aml_method("_EJ0", 1);
+            aml_append(method,
+                aml_return(aml_call2("CPEJ", aml_int(i), aml_arg(0)))
+            );
+            aml_append(dev, method);
+
+            aml_append(sb_scope, dev);
         }
 
         /* build this code:
          *   Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
          */
         /* Arg0 = Processor ID = APIC ID */
-        build_append_notify_method(sb_scope, "NTFY", "CP%0.02X", acpi_cpus);
-
-        /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" */
-        build_append_byte(sb_scope, 0x08); /* NameOp */
-        build_append_nameseg(sb_scope, "CPON");
-
-        {
-            GArray *package = build_alloc_array();
-            uint8_t op;
-
-            /*
-             * Note: The ability to create variable-sized packages was first introduced in ACPI 2.0. ACPI 1.0 only
-             * allowed fixed-size packages with up to 255 elements.
-             * Windows guests up to win2k8 fail when VarPackageOp is used.
-             */
-            if (acpi_cpus <= 255) {
-                op = 0x12; /* PackageOp */
-                build_append_byte(package, acpi_cpus); /* NumElements */
-            } else {
-                op = 0x13; /* VarPackageOp */
-                build_append_int(package, acpi_cpus); /* VarNumElements */
-            }
-
-            for (i = 0; i < acpi_cpus; i++) {
-                uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00;
-                build_append_byte(package, b);
-            }
-
-            build_package(package, op, 2);
-            build_append_array(sb_scope, package);
-            build_free_array(package);
+        method = aml_method("NTFY", 2);
+        for (i = 0; i < acpi_cpus; i++) {
+            ifctx = aml_if(aml_equal(aml_arg(0), aml_int(i)));
+            aml_append(ifctx,
+                aml_notify(aml_name("CP%.02X", i), aml_arg(1))
+            );
+            aml_append(method, ifctx);
         }
+        aml_append(sb_scope, method);
+
+        /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
+         *
+         * Note: The ability to create variable-sized packages was first
+         * introduced in ACPI 2.0. ACPI 1.0 only allowed fixed-size packages
+         * ith up to 255 elements. Windows guests up to win2k8 fail when
+         * VarPackageOp is used.
+         */
+        pkg = acpi_cpus <= 255 ? aml_package(acpi_cpus) :
+                                 aml_varpackage(acpi_cpus);
 
-        if (nr_mem) {
-            assert(nr_mem <= ACPI_MAX_RAM_SLOTS);
-            /* build memory devices */
-            for (i = 0; i < nr_mem; i++) {
-                char id[3];
-                uint8_t *mem = acpi_data_push(sb_scope, ACPI_MEM_SIZEOF);
-
-                snprintf(id, sizeof(id), "%02X", i);
-                memcpy(mem, ACPI_MEM_AML, ACPI_MEM_SIZEOF);
-                memcpy(mem + ACPI_MEM_OFFSET_HEX, id, 2);
-                memcpy(mem + ACPI_MEM_OFFSET_ID, id, 2);
-            }
+        for (i = 0; i < acpi_cpus; i++) {
+            uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00;
+            aml_append(pkg, aml_int(b));
+        }
+        aml_append(sb_scope, aml_name_decl("CPON", pkg));
+
+        /* build memory devices */
+        assert(nr_mem <= ACPI_MAX_RAM_SLOTS);
+        scope = aml_scope("\\_SB.PCI0." stringify(MEMORY_HOTPLUG_DEVICE));
+        aml_append(scope,
+            aml_name_decl(stringify(MEMORY_SLOTS_NUMBER), aml_int(nr_mem))
+        );
+
+        crs = aml_resource_template();
+        aml_append(crs,
+            aml_io(aml_decode16, pm->mem_hp_io_base, pm->mem_hp_io_base, 0,
+                   pm->mem_hp_io_len)
+        );
+        aml_append(scope, aml_name_decl("_CRS", crs));
+
+        aml_append(scope, aml_operation_region(
+            stringify(MEMORY_HOTPLUG_IO_REGION), aml_system_io,
+            pm->mem_hp_io_base, pm->mem_hp_io_len)
+        );
+
+        field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc);
+        aml_append(field, /* read only */
+            aml_named_field(stringify(MEMORY_SLOT_ADDR_LOW), 32));
+        aml_append(field, /* read only */
+            aml_named_field(stringify(MEMORY_SLOT_ADDR_HIGH), 32));
+        aml_append(field, /* read only */
+            aml_named_field(stringify(MEMORY_SLOT_SIZE_LOW), 32));
+        aml_append(field, /* read only */
+            aml_named_field(stringify(MEMORY_SLOT_SIZE_HIGH), 32));
+        aml_append(field, /* read only */
+            aml_named_field(stringify(MEMORY_SLOT_PROXIMITY), 32));
+        aml_append(scope, field);
+
+        field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_byte_acc);
+        aml_append(field, aml_reserved_field(160 /* bits, Offset(20) */));
+        aml_append(field, /* 1 if enabled, read only */
+            aml_named_field(stringify(MEMORY_SLOT_ENABLED), 1));
+        aml_append(field,
+            /*(read) 1 if has a insert event. (write) 1 to clear event */
+            aml_named_field(stringify(MEMORY_SLOT_INSERT_EVENT), 1));
+        aml_append(scope, field);
+
+        field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc);
+        aml_append(field, /* DIMM selector, write only */
+            aml_named_field(stringify(MEMORY_SLOT_SLECTOR), 32));
+        aml_append(field, /* _OST event code, write only */
+            aml_named_field(stringify(MEMORY_SLOT_OST_EVENT), 32));
+        aml_append(field, /* _OST status code, write only */
+            aml_named_field(stringify(MEMORY_SLOT_OST_STATUS), 32));
+        aml_append(scope, field);
+
+        aml_append(sb_scope, scope);
+
+        for (i = 0; i < nr_mem; i++) {
+            #define BASEPATH "\\_SB.PCI0." stringify(MEMORY_HOTPLUG_DEVICE) "."
+            const char *s;
+
+            dev = aml_device("MP%02X", i);
+            aml_append(dev, aml_name_decl("_UID", aml_string("0x%02X", i)));
+            aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C80")));
+
+            method = aml_method("_CRS", 0);
+            s = BASEPATH stringify(MEMORY_SLOT_CRS_METHOD);
+            aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
+            aml_append(dev, method);
+
+            method = aml_method("_STA", 0);
+            s = BASEPATH stringify(MEMORY_SLOT_STATUS_METHOD);
+            aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
+            aml_append(dev, method);
+
+            method = aml_method("_PXM", 0);
+            s = BASEPATH stringify(MEMORY_SLOT_PROXIMITY_METHOD);
+            aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
+            aml_append(dev, method);
+
+            method = aml_method("_OST", 3);
+            s = BASEPATH stringify(MEMORY_SLOT_OST_METHOD);
+            aml_append(method, aml_return(aml_call4(
+                s, aml_name("_UID"), aml_arg(0), aml_arg(1), aml_arg(2)
+            )));
+            aml_append(dev, method);
+
+            aml_append(sb_scope, dev);
+        }
 
-            /* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) {
-             *     If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ...
-             */
-            build_append_notify_method(sb_scope,
-                                       stringify(MEMORY_SLOT_NOTIFY_METHOD),
-                                       "MP%0.02X", nr_mem);
+        /* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) {
+         *     If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ...
+         */
+        method = aml_method(stringify(MEMORY_SLOT_NOTIFY_METHOD), 2);
+        for (i = 0; i < nr_mem; i++) {
+            ifctx = aml_if(aml_equal(aml_arg(0), aml_int(i)));
+            aml_append(ifctx,
+                aml_notify(aml_name("MP%.02X", i), aml_arg(1))
+            );
+            aml_append(method, ifctx);
         }
+        aml_append(sb_scope, method);
 
         {
-            AcpiBuildPciBusHotplugState hotplug_state;
             Object *pci_host;
             PCIBus *bus = NULL;
             bool ambiguous;
@@ -1192,26 +998,22 @@ build_ssdt(GArray *table_data, GArray *linker,
                 bus = PCI_HOST_BRIDGE(pci_host)->bus;
             }
 
-            build_pci_bus_state_init(&hotplug_state, NULL, pm->pcihp_bridge_en);
-
             if (bus) {
+                Aml *scope = aml_scope("PCI0");
                 /* Scan all PCI buses. Generate tables to support hotplug. */
-                pci_for_each_bus_depth_first(bus, build_pci_bus_begin,
-                                             build_pci_bus_end, &hotplug_state);
+                build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
+                aml_append(sb_scope, scope);
             }
-
-            build_append_array(sb_scope, hotplug_state.device_table);
-            build_pci_bus_state_cleanup(&hotplug_state);
         }
-
-        build_package(sb_scope, op, 3);
-        build_append_array(table_data, sb_scope);
-        build_free_array(sb_scope);
+        aml_append(ssdt, sb_scope);
     }
 
+    /* copy AML table into ACPI tables blob and patch header there */
+    g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
     build_header(linker, table_data,
-                 (void *)(table_data->data + ssdt_start),
-                 "SSDT", table_data->len - ssdt_start, 1);
+        (void *)(table_data->data + table_data->len - ssdt->buf->len),
+        "SSDT", ssdt->buf->len, 1);
+    free_aml_allocator();
 }
 
 static void
@@ -1513,7 +1315,7 @@ static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
 {
     void *linker_data = bios_linker_loader_cleanup(tables->linker);
     g_free(linker_data);
-    g_array_free(tables->rsdp, mfre);
+    g_array_free(tables->rsdp, true);
     g_array_free(tables->table_data, true);
     g_array_free(tables->tcpalog, mfre);
 }
@@ -1522,10 +1324,12 @@ typedef
 struct AcpiBuildState {
     /* Copy of table in RAM (for patching). */
     ram_addr_t table_ram;
-    uint32_t table_size;
     /* Is table patched? */
     uint8_t patched;
     PcGuestInfo *guest_info;
+    void *rsdp;
+    ram_addr_t rsdp_ram;
+    ram_addr_t linker_ram;
 } AcpiBuildState;
 
 static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
@@ -1574,6 +1378,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
     PcPciInfo pci;
     uint8_t *u;
     size_t aml_len = 0;
+    GArray *tables_blob = tables->table_data;
 
     acpi_get_cpu_info(&cpu);
     acpi_get_pm_info(&pm);
@@ -1594,74 +1399,72 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
      * We place it first since it's the only table that has alignment
      * requirements.
      */
-    facs = tables->table_data->len;
-    build_facs(tables->table_data, tables->linker, guest_info);
+    facs = tables_blob->len;
+    build_facs(tables_blob, tables->linker, guest_info);
 
     /* DSDT is pointed to by FADT */
-    dsdt = tables->table_data->len;
-    build_dsdt(tables->table_data, tables->linker, &misc);
+    dsdt = tables_blob->len;
+    build_dsdt(tables_blob, tables->linker, &misc);
 
     /* Count the size of the DSDT and SSDT, we will need it for legacy
      * sizing of ACPI tables.
      */
-    aml_len += tables->table_data->len - dsdt;
+    aml_len += tables_blob->len - dsdt;
 
     /* ACPI tables pointed to by RSDT */
-    acpi_add_table(table_offsets, tables->table_data);
-    build_fadt(tables->table_data, tables->linker, &pm, facs, dsdt);
+    acpi_add_table(table_offsets, tables_blob);
+    build_fadt(tables_blob, tables->linker, &pm, facs, dsdt);
 
-    ssdt = tables->table_data->len;
-    acpi_add_table(table_offsets, tables->table_data);
-    build_ssdt(tables->table_data, tables->linker, &cpu, &pm, &misc, &pci,
+    ssdt = tables_blob->len;
+    acpi_add_table(table_offsets, tables_blob);
+    build_ssdt(tables_blob, tables->linker, &cpu, &pm, &misc, &pci,
                guest_info);
-    aml_len += tables->table_data->len - ssdt;
+    aml_len += tables_blob->len - ssdt;
 
-    acpi_add_table(table_offsets, tables->table_data);
-    build_madt(tables->table_data, tables->linker, &cpu, guest_info);
+    acpi_add_table(table_offsets, tables_blob);
+    build_madt(tables_blob, tables->linker, &cpu, guest_info);
 
     if (misc.has_hpet) {
-        acpi_add_table(table_offsets, tables->table_data);
-        build_hpet(tables->table_data, tables->linker);
+        acpi_add_table(table_offsets, tables_blob);
+        build_hpet(tables_blob, tables->linker);
     }
     if (misc.has_tpm) {
-        acpi_add_table(table_offsets, tables->table_data);
-        build_tpm_tcpa(tables->table_data, tables->linker, tables->tcpalog);
+        acpi_add_table(table_offsets, tables_blob);
+        build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog);
 
-        acpi_add_table(table_offsets, tables->table_data);
-        build_tpm_ssdt(tables->table_data, tables->linker);
+        acpi_add_table(table_offsets, tables_blob);
+        build_tpm_ssdt(tables_blob, tables->linker);
     }
     if (guest_info->numa_nodes) {
-        acpi_add_table(table_offsets, tables->table_data);
-        build_srat(tables->table_data, tables->linker, guest_info);
+        acpi_add_table(table_offsets, tables_blob);
+        build_srat(tables_blob, tables->linker, guest_info);
     }
     if (acpi_get_mcfg(&mcfg)) {
-        acpi_add_table(table_offsets, tables->table_data);
-        build_mcfg_q35(tables->table_data, tables->linker, &mcfg);
+        acpi_add_table(table_offsets, tables_blob);
+        build_mcfg_q35(tables_blob, tables->linker, &mcfg);
     }
     if (acpi_has_iommu()) {
-        acpi_add_table(table_offsets, tables->table_data);
-        build_dmar_q35(tables->table_data, tables->linker);
+        acpi_add_table(table_offsets, tables_blob);
+        build_dmar_q35(tables_blob, tables->linker);
     }
 
     /* Add tables supplied by user (if any) */
     for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
         unsigned len = acpi_table_len(u);
 
-        acpi_add_table(table_offsets, tables->table_data);
-        g_array_append_vals(tables->table_data, u, len);
+        acpi_add_table(table_offsets, tables_blob);
+        g_array_append_vals(tables_blob, u, len);
     }
 
     /* RSDT is pointed to by RSDP */
-    rsdt = tables->table_data->len;
-    build_rsdt(tables->table_data, tables->linker, table_offsets);
+    rsdt = tables_blob->len;
+    build_rsdt(tables_blob, tables->linker, table_offsets);
 
     /* RSDP is in FSEG memory, so allocate it separately */
     build_rsdp(tables->rsdp, tables->linker, rsdt);
 
     /* We'll expose it all to Guest so we want to reduce
      * chance of size changes.
-     * RSDP is small so it's easy to keep it immutable, no need to
-     * bother with alignment.
      *
      * We used to align the tables to 4k, but of course this would
      * too simple to be enough.  4k turned out to be too small an
@@ -1685,23 +1488,23 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
             guest_info->legacy_acpi_table_size +
             ACPI_BUILD_LEGACY_CPU_AML_SIZE * max_cpus;
         int legacy_table_size =
-            ROUND_UP(tables->table_data->len - aml_len + legacy_aml_len,
+            ROUND_UP(tables_blob->len - aml_len + legacy_aml_len,
                      ACPI_BUILD_ALIGN_SIZE);
-        if (tables->table_data->len > legacy_table_size) {
+        if (tables_blob->len > legacy_table_size) {
             /* Should happen only with PCI bridges and -M pc-i440fx-2.0.  */
             error_report("Warning: migration may not work.");
         }
-        g_array_set_size(tables->table_data, legacy_table_size);
+        g_array_set_size(tables_blob, legacy_table_size);
     } else {
         /* Make sure we have a buffer in case we need to resize the tables. */
-        if (tables->table_data->len > ACPI_BUILD_TABLE_SIZE / 2) {
+        if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
             /* As of QEMU 2.1, this fires with 160 VCPUs and 255 memory slots.  */
             error_report("Warning: ACPI tables are larger than 64k.");
             error_report("Warning: migration may not work.");
             error_report("Warning: please remove CPUs, NUMA nodes, "
                          "memory slots or PCI bridges.");
         }
-        acpi_align_size(tables->table_data, ACPI_BUILD_TABLE_SIZE);
+        acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
     }
 
     acpi_align_size(tables->linker, ACPI_BUILD_ALIGN_SIZE);
@@ -1710,6 +1513,17 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
     g_array_free(table_offsets, true);
 }
 
+static void acpi_ram_update(ram_addr_t ram, GArray *data)
+{
+    uint32_t size = acpi_data_len(data);
+
+    /* Make sure RAM size is correct - in case it got changed e.g. by migration */
+    qemu_ram_resize(ram, size, &error_abort);
+
+    memcpy(qemu_get_ram_ptr(ram), data->data, size);
+    cpu_physical_memory_set_dirty_range_nocode(ram, size);
+}
+
 static void acpi_build_update(void *build_opaque, uint32_t offset)
 {
     AcpiBuildState *build_state = build_opaque;
@@ -1725,18 +1539,15 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
 
     acpi_build(build_state->guest_info, &tables);
 
-    assert(acpi_data_len(tables.table_data) == build_state->table_size);
-
-    /* Make sure RAM size is correct - in case it got changed by migration */
-    qemu_ram_resize(build_state->table_ram, build_state->table_size,
-                    &error_abort);
+    acpi_ram_update(build_state->table_ram, tables.table_data);
 
-    memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
-           build_state->table_size);
-
-    cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
-                                               build_state->table_size);
+    if (build_state->rsdp) {
+        memcpy(build_state->rsdp, tables.rsdp->data, acpi_data_len(tables.rsdp));
+    } else {
+        acpi_ram_update(build_state->rsdp_ram, tables.rsdp);
+    }
 
+    acpi_ram_update(build_state->linker_ram, tables.linker);
     acpi_build_tables_cleanup(&tables, true);
 }
 
@@ -1797,19 +1608,31 @@ void acpi_setup(PcGuestInfo *guest_info)
                                                ACPI_BUILD_TABLE_FILE,
                                                ACPI_BUILD_TABLE_MAX_SIZE);
     assert(build_state->table_ram != RAM_ADDR_MAX);
-    build_state->table_size = acpi_data_len(tables.table_data);
 
-    acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader", 0);
+    build_state->linker_ram =
+        acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
 
     fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
                     tables.tcpalog->data, acpi_data_len(tables.tcpalog));
 
-    /*
-     * RSDP is small so it's easy to keep it immutable, no need to
-     * bother with ROM blobs.
-     */
-    fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
-                    tables.rsdp->data, acpi_data_len(tables.rsdp));
+    if (!guest_info->rsdp_in_ram) {
+        /*
+         * Keep for compatibility with old machine types.
+         * Though RSDP is small, its contents isn't immutable, so
+         * we'll update it along with the rest of tables on guest access.
+         */
+        uint32_t rsdp_size = acpi_data_len(tables.rsdp);
+
+        build_state->rsdp = g_memdup(tables.rsdp->data, rsdp_size);
+        fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
+                                 acpi_build_update, build_state,
+                                 build_state->rsdp, rsdp_size);
+        build_state->rsdp_ram = (ram_addr_t)-1;
+    } else {
+        build_state->rsdp = NULL;
+        build_state->rsdp_ram = acpi_add_rom_blob(build_state, tables.rsdp,
+                                                  ACPI_BUILD_RSDP_FILE, 0);
+    }
 
     qemu_register_reset(acpi_build_reset, build_state);
     acpi_build_reset(build_state);
diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
index 268d870990..1aff74627f 100644
--- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
+++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
@@ -16,12 +16,12 @@
 /****************************************************************
  * CPU hotplug
  ****************************************************************/
-#define CPU_HOTPLUG_RESOURCE_DEVICE PRES
 
 Scope(\_SB) {
     /* Objects filled in by run-time generated SSDT */
     External(NTFY, MethodObj)
     External(CPON, PkgObj)
+    External(PRS, FieldUnitObj)
 
     /* Methods called by run-time generated SSDT Processor objects */
     Method(CPMA, 1, NotSerialized) {
@@ -54,10 +54,6 @@ Scope(\_SB) {
     }
 
 #define CPU_STATUS_LEN ACPI_GPE_PROC_LEN
-    OperationRegion(PRST, SystemIO, CPU_STATUS_BASE, CPU_STATUS_LEN)
-    Field(PRST, ByteAcc, NoLock, Preserve) {
-        PRS, 256
-    }
     Method(PRSC, 0) {
         // Local5 = active cpu bitmap
         Store(PRS, Local5)
@@ -91,15 +87,4 @@ Scope(\_SB) {
             Increment(Local0)
         }
     }
-
-    Device(CPU_HOTPLUG_RESOURCE_DEVICE) {
-        Name(_HID, EisaId("PNP0A06"))
-        Name(_UID, "CPU hotplug resources")
-
-        Name(_CRS, ResourceTemplate() {
-            IO(Decode16, CPU_STATUS_BASE, CPU_STATUS_BASE, 0, CPU_STATUS_LEN)
-        })
-
-        Name(_STA, 0xB) /* present, functioning, decoding, not shown in UI */
-    }
 }
diff --git a/hw/i386/acpi-dsdt-isa.dsl b/hw/i386/acpi-dsdt-isa.dsl
index deb37de92e..89caa1649d 100644
--- a/hw/i386/acpi-dsdt-isa.dsl
+++ b/hw/i386/acpi-dsdt-isa.dsl
@@ -16,17 +16,6 @@
 /* Common legacy ISA style devices. */
 Scope(\_SB.PCI0.ISA) {
 
-    Device (SMC) {
-        Name(_HID, EisaId("APP0001"))
-        /* _STA will be patched to 0x0B if AppleSMC is present */
-        ACPI_EXTRACT_NAME_BYTE_CONST DSDT_APPLESMC_STA
-        Name(_STA, 0xF0)
-        Name(_CRS, ResourceTemplate () {
-            IO (Decode16, 0x0300, 0x0300, 0x01, 0x20)
-            IRQNoFlags() { 6 }
-        })
-    }
-
     Device(RTC) {
         Name(_HID, EisaId("PNP0B00"))
         Name(_CRS, ResourceTemplate() {
diff --git a/hw/i386/acpi-dsdt-mem-hotplug.dsl b/hw/i386/acpi-dsdt-mem-hotplug.dsl
index 2a36c4799e..1e9ec39274 100644
--- a/hw/i386/acpi-dsdt-mem-hotplug.dsl
+++ b/hw/i386/acpi-dsdt-mem-hotplug.dsl
@@ -22,14 +22,16 @@
             External(MEMORY_SLOTS_NUMBER, IntObj)
 
             /* Memory hotplug IO registers */
-            OperationRegion(MEMORY_HOTPLUG_IO_REGION, SystemIO,
-                            ACPI_MEMORY_HOTPLUG_BASE,
-                            ACPI_MEMORY_HOTPLUG_IO_LEN)
-
-            Name(_CRS, ResourceTemplate() {
-                IO(Decode16, ACPI_MEMORY_HOTPLUG_BASE, ACPI_MEMORY_HOTPLUG_BASE,
-                   0, ACPI_MEMORY_HOTPLUG_IO_LEN, IO)
-            })
+            External(MEMORY_SLOT_ADDR_LOW, FieldUnitObj) // read only
+            External(MEMORY_SLOT_ADDR_HIGH, FieldUnitObj) // read only
+            External(MEMORY_SLOT_SIZE_LOW, FieldUnitObj) // read only
+            External(MEMORY_SLOT_SIZE_HIGH, FieldUnitObj) // read only
+            External(MEMORY_SLOT_PROXIMITY, FieldUnitObj) // read only
+            External(MEMORY_SLOT_ENABLED, FieldUnitObj) // 1 if enabled, read only
+            External(MEMORY_SLOT_INSERT_EVENT, FieldUnitObj) // (read) 1 if has a insert event. (write) 1 to clear event
+            External(MEMORY_SLOT_SLECTOR, FieldUnitObj) // DIMM selector, write only
+            External(MEMORY_SLOT_OST_EVENT, FieldUnitObj) // _OST event code, write only
+            External(MEMORY_SLOT_OST_STATUS, FieldUnitObj) // _OST status code, write only
 
             Method(_STA, 0) {
                 If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
@@ -39,25 +41,7 @@
                 Return(0xB)
             }
 
-            Field(MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
-                MEMORY_SLOT_ADDR_LOW, 32,  // read only
-                MEMORY_SLOT_ADDR_HIGH, 32, // read only
-                MEMORY_SLOT_SIZE_LOW, 32,  // read only
-                MEMORY_SLOT_SIZE_HIGH, 32, // read only
-                MEMORY_SLOT_PROXIMITY, 32, // read only
-            }
-            Field(MEMORY_HOTPLUG_IO_REGION, ByteAcc, NoLock, Preserve) {
-                Offset(20),
-                MEMORY_SLOT_ENABLED,  1, // 1 if enabled, read only
-                MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event
-            }
-
             Mutex (MEMORY_SLOT_LOCK, 0)
-            Field (MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
-                MEMORY_SLOT_SLECTOR, 32,  // DIMM selector, write only
-                MEMORY_SLOT_OST_EVENT, 32,  // _OST event code, write only
-                MEMORY_SLOT_OST_STATUS, 32,  // _OST status code, write only
-            }
 
             Method(MEMORY_SLOT_SCAN_METHOD, 0) {
                 If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
diff --git a/hw/i386/acpi-dsdt-pci-crs.dsl b/hw/i386/acpi-dsdt-pci-crs.dsl
deleted file mode 100644
index 4648e90366..0000000000
--- a/hw/i386/acpi-dsdt-pci-crs.dsl
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* PCI CRS (current resources) definition. */
-Scope(\_SB.PCI0) {
-
-    Name(CRES, ResourceTemplate() {
-        WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
-            0x0000,             // Address Space Granularity
-            0x0000,             // Address Range Minimum
-            0x00FF,             // Address Range Maximum
-            0x0000,             // Address Translation Offset
-            0x0100,             // Address Length
-            ,, )
-        IO(Decode16,
-            0x0CF8,             // Address Range Minimum
-            0x0CF8,             // Address Range Maximum
-            0x01,               // Address Alignment
-            0x08,               // Address Length
-            )
-        BOARD_SPECIFIC_PCI_RESOURSES
-        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
-            0x00000000,         // Address Space Granularity
-            0x000A0000,         // Address Range Minimum
-            0x000BFFFF,         // Address Range Maximum
-            0x00000000,         // Address Translation Offset
-            0x00020000,         // Address Length
-            ,, , AddressRangeMemory, TypeStatic)
-        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
-            0x00000000,         // Address Space Granularity
-            0xE0000000,         // Address Range Minimum
-            0xFEBFFFFF,         // Address Range Maximum
-            0x00000000,         // Address Translation Offset
-            0x1EC00000,         // Address Length
-            ,, PW32, AddressRangeMemory, TypeStatic)
-    })
-
-    Name(CR64, ResourceTemplate() {
-        QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
-            0x00000000,          // Address Space Granularity
-            0x8000000000,        // Address Range Minimum
-            0xFFFFFFFFFF,        // Address Range Maximum
-            0x00000000,          // Address Translation Offset
-            0x8000000000,        // Address Length
-            ,, PW64, AddressRangeMemory, TypeStatic)
-    })
-
-    Method(_CRS, 0) {
-        /* Fields provided by dynamically created ssdt */
-        External(P0S, IntObj)
-        External(P0E, IntObj)
-        External(P1V, IntObj)
-        External(P1S, BuffObj)
-        External(P1E, BuffObj)
-        External(P1L, BuffObj)
-
-        /* fixup 32bit pci io window */
-        CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32)
-        CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32)
-        CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32)
-        Store(P0S, PS32)
-        Store(P0E, PE32)
-        Store(Add(Subtract(P0E, P0S), 1), PL32)
-
-        If (LEqual(P1V, Zero)) {
-            Return (CRES)
-        }
-
-        /* fixup 64bit pci io window */
-        CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64)
-        CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64)
-        CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64)
-        Store(P1S, PS64)
-        Store(P1E, PE64)
-        Store(P1L, PL64)
-        /* add window and return result */
-        ConcatenateResTemplate(CRES, CR64, Local0)
-        Return (Local0)
-    }
-}
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index a611e07ec8..a2d84ecf8f 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -31,50 +31,6 @@ DefinitionBlock (
 
 #include "acpi-dsdt-dbug.dsl"
 
-
-/****************************************************************
- * PCI Bus definition
- ****************************************************************/
-#define BOARD_SPECIFIC_PCI_RESOURSES \
-     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
-         0x0000, \
-         0x0000, \
-         0x0CF7, \
-         0x0000, \
-         0x0CF8, \
-         ,, , TypeStatic) \
-     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
-         0x0000, \
-         0x0D00, \
-         0xADFF, \
-         0x0000, \
-         0xA100, \
-         ,, , TypeStatic) \
-     /* 0xae00-0xae0e hole for PCI hotplug, hw/acpi/piix4.c:PCI_HOTPLUG_ADDR */ \
-     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
-         0x0000, \
-         0xAE0F, \
-         0xAEFF, \
-         0x0000, \
-         0x00F1, \
-         ,, , TypeStatic) \
-     /* 0xaf00-0xaf1f hole for CPU hotplug, hw/acpi/piix4.c:PIIX4_PROC_BASE */ \
-     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
-         0x0000, \
-         0xAF20, \
-         0xAFDF, \
-         0x0000, \
-         0x00C0, \
-         ,, , TypeStatic) \
-     /* 0xafe0-0xafe3 hole for ACPI.GPE0, hw/acpi/piix4.c:GPE_BASE */ \
-     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
-         0x0000, \
-         0xAFE4, \
-         0xFFFF, \
-         0x0000, \
-         0x501C, \
-         ,, , TypeStatic)
-
     Scope(\_SB) {
         Device(PCI0) {
             Name(_HID, EisaId("PNP0A03"))
@@ -85,7 +41,6 @@ DefinitionBlock (
         }
     }
 
-#include "acpi-dsdt-pci-crs.dsl"
 #include "acpi-dsdt-hpet.dsl"
 
 
@@ -130,7 +85,6 @@ DefinitionBlock (
         }
     }
 
-#define DSDT_APPLESMC_STA piix_dsdt_applesmc_sta
 #include "acpi-dsdt-isa.dsl"
 
 
diff --git a/hw/i386/acpi-dsdt.hex.generated b/hw/i386/acpi-dsdt.hex.generated
index 498b194a0c..ecaa4a5480 100644
--- a/hw/i386/acpi-dsdt.hex.generated
+++ b/hw/i386/acpi-dsdt.hex.generated
@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x53,
 0x44,
 0x54,
-0x25,
-0xe,
+0x9a,
+0xb,
 0x0,
 0x0,
 0x1,
-0x6c,
+0xf8,
 0x42,
 0x58,
 0x50,
@@ -145,405 +145,6 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x44,
 0x1,
 0x10,
-0x4e,
-0x18,
-0x2e,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x8,
-0x43,
-0x52,
-0x45,
-0x53,
-0x11,
-0x42,
-0xa,
-0xa,
-0x9e,
-0x88,
-0xd,
-0x0,
-0x2,
-0xc,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xff,
-0x0,
-0x0,
-0x0,
-0x0,
-0x1,
-0x47,
-0x1,
-0xf8,
-0xc,
-0xf8,
-0xc,
-0x1,
-0x8,
-0x88,
-0xd,
-0x0,
-0x1,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0x0,
-0xf7,
-0xc,
-0x0,
-0x0,
-0xf8,
-0xc,
-0x88,
-0xd,
-0x0,
-0x1,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0xd,
-0xff,
-0xad,
-0x0,
-0x0,
-0x0,
-0xa1,
-0x88,
-0xd,
-0x0,
-0x1,
-0xc,
-0x3,
-0x0,
-0x0,
-0xf,
-0xae,
-0xff,
-0xae,
-0x0,
-0x0,
-0xf1,
-0x0,
-0x88,
-0xd,
-0x0,
-0x1,
-0xc,
-0x3,
-0x0,
-0x0,
-0x20,
-0xaf,
-0xdf,
-0xaf,
-0x0,
-0x0,
-0xc0,
-0x0,
-0x88,
-0xd,
-0x0,
-0x1,
-0xc,
-0x3,
-0x0,
-0x0,
-0xe4,
-0xaf,
-0xff,
-0xff,
-0x0,
-0x0,
-0x1c,
-0x50,
-0x87,
-0x17,
-0x0,
-0x0,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xa,
-0x0,
-0xff,
-0xff,
-0xb,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x2,
-0x0,
-0x87,
-0x17,
-0x0,
-0x0,
-0xc,
-0x1,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xe0,
-0xff,
-0xff,
-0xbf,
-0xfe,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xc0,
-0x1e,
-0x79,
-0x0,
-0x8,
-0x43,
-0x52,
-0x36,
-0x34,
-0x11,
-0x33,
-0xa,
-0x30,
-0x8a,
-0x2b,
-0x0,
-0x0,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x80,
-0x0,
-0x0,
-0x0,
-0xff,
-0xff,
-0xff,
-0xff,
-0xff,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x80,
-0x0,
-0x0,
-0x0,
-0x79,
-0x0,
-0x14,
-0x41,
-0xa,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x0,
-0x8a,
-0x43,
-0x52,
-0x45,
-0x53,
-0xa,
-0x8c,
-0x50,
-0x53,
-0x33,
-0x32,
-0x8a,
-0x43,
-0x52,
-0x45,
-0x53,
-0xa,
-0x90,
-0x50,
-0x45,
-0x33,
-0x32,
-0x8a,
-0x43,
-0x52,
-0x45,
-0x53,
-0xa,
-0x98,
-0x50,
-0x4c,
-0x33,
-0x32,
-0x70,
-0x50,
-0x30,
-0x53,
-0x5f,
-0x50,
-0x53,
-0x33,
-0x32,
-0x70,
-0x50,
-0x30,
-0x45,
-0x5f,
-0x50,
-0x45,
-0x33,
-0x32,
-0x70,
-0x72,
-0x74,
-0x50,
-0x30,
-0x45,
-0x5f,
-0x50,
-0x30,
-0x53,
-0x5f,
-0x0,
-0x1,
-0x0,
-0x50,
-0x4c,
-0x33,
-0x32,
-0xa0,
-0xc,
-0x93,
-0x50,
-0x31,
-0x56,
-0x5f,
-0x0,
-0xa4,
-0x43,
-0x52,
-0x45,
-0x53,
-0x8f,
-0x43,
-0x52,
-0x36,
-0x34,
-0xa,
-0xe,
-0x50,
-0x53,
-0x36,
-0x34,
-0x8f,
-0x43,
-0x52,
-0x36,
-0x34,
-0xa,
-0x16,
-0x50,
-0x45,
-0x36,
-0x34,
-0x8f,
-0x43,
-0x52,
-0x36,
-0x34,
-0xa,
-0x26,
-0x50,
-0x4c,
-0x36,
-0x34,
-0x70,
-0x50,
-0x31,
-0x53,
-0x5f,
-0x50,
-0x53,
-0x36,
-0x34,
-0x70,
-0x50,
-0x31,
-0x45,
-0x5f,
-0x50,
-0x45,
-0x36,
-0x34,
-0x70,
-0x50,
-0x31,
-0x4c,
-0x5f,
-0x50,
-0x4c,
-0x36,
-0x34,
-0x84,
-0x43,
-0x52,
-0x45,
-0x53,
-0x43,
-0x52,
-0x36,
-0x34,
-0x60,
-0xa4,
-0x60,
-0x10,
 0x4d,
 0x8,
 0x5f,
@@ -811,8 +412,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x4e,
 0x1,
 0x10,
-0x4a,
-0x1e,
+0x4c,
+0x1b,
 0x2f,
 0x3,
 0x5f,
@@ -829,52 +430,6 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x5f,
 0x5b,
 0x82,
-0x2c,
-0x53,
-0x4d,
-0x43,
-0x5f,
-0x8,
-0x5f,
-0x48,
-0x49,
-0x44,
-0xc,
-0x6,
-0x10,
-0x0,
-0x1,
-0x8,
-0x5f,
-0x53,
-0x54,
-0x41,
-0xa,
-0xf0,
-0x8,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x11,
-0x10,
-0xa,
-0xd,
-0x47,
-0x1,
-0x0,
-0x3,
-0x0,
-0x3,
-0x1,
-0x20,
-0x22,
-0x40,
-0x0,
-0x79,
-0x0,
-0x5b,
-0x82,
 0x2d,
 0x52,
 0x54,
@@ -2318,8 +1873,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x53,
 0x1,
 0x10,
-0x4f,
-0x12,
+0x4d,
+0xc,
 0x5f,
 0x53,
 0x42,
@@ -2416,32 +1971,6 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x22,
 0xa,
 0xc8,
-0x5b,
-0x80,
-0x50,
-0x52,
-0x53,
-0x54,
-0x1,
-0xb,
-0x0,
-0xaf,
-0xa,
-0x20,
-0x5b,
-0x81,
-0xc,
-0x50,
-0x52,
-0x53,
-0x54,
-0x1,
-0x50,
-0x52,
-0x53,
-0x5f,
-0x40,
-0x10,
 0x14,
 0x4a,
 0x6,
@@ -2549,81 +2078,9 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x3,
 0x75,
 0x60,
-0x5b,
-0x82,
-0x46,
-0x4,
-0x50,
-0x52,
-0x45,
-0x53,
-0x8,
-0x5f,
-0x48,
-0x49,
-0x44,
-0xc,
-0x41,
-0xd0,
-0xa,
-0x6,
-0x8,
-0x5f,
-0x55,
-0x49,
-0x44,
-0xd,
-0x43,
-0x50,
-0x55,
-0x20,
-0x68,
-0x6f,
-0x74,
-0x70,
-0x6c,
-0x75,
-0x67,
-0x20,
-0x72,
-0x65,
-0x73,
-0x6f,
-0x75,
-0x72,
-0x63,
-0x65,
-0x73,
-0x0,
-0x8,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x11,
-0xd,
-0xa,
-0xa,
-0x47,
-0x1,
-0x0,
-0xaf,
-0x0,
-0xaf,
-0x0,
-0x20,
-0x79,
-0x0,
-0x8,
-0x5f,
-0x53,
-0x54,
-0x41,
-0xa,
-0xb,
 0x10,
-0x40,
-0x31,
+0x44,
+0x2a,
 0x2e,
 0x5f,
 0x53,
@@ -2635,8 +2092,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x30,
 0x5b,
 0x82,
-0x43,
-0x30,
+0x47,
+0x29,
 0x4d,
 0x48,
 0x50,
@@ -2686,37 +2143,6 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x65,
 0x73,
 0x0,
-0x5b,
-0x80,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x1,
-0xb,
-0x0,
-0xa,
-0xa,
-0x18,
-0x8,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x11,
-0xd,
-0xa,
-0xa,
-0x47,
-0x1,
-0x0,
-0xa,
-0x0,
-0xa,
-0x0,
-0x18,
-0x79,
-0x0,
 0x14,
 0x13,
 0x5f,
@@ -2738,89 +2164,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0xa,
 0xb,
 0x5b,
-0x81,
-0x1f,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x3,
-0x4d,
-0x52,
-0x42,
-0x4c,
-0x20,
-0x4d,
-0x52,
-0x42,
-0x48,
-0x20,
-0x4d,
-0x52,
-0x4c,
-0x4c,
-0x20,
-0x4d,
-0x52,
-0x4c,
-0x48,
-0x20,
-0x4d,
-0x50,
-0x58,
-0x5f,
-0x20,
-0x5b,
-0x81,
-0x13,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x1,
-0x0,
-0x40,
-0xa,
-0x4d,
-0x45,
-0x53,
-0x5f,
-0x1,
-0x4d,
-0x49,
-0x4e,
-0x53,
-0x1,
-0x5b,
 0x1,
 0x4d,
 0x4c,
 0x43,
 0x4b,
 0x0,
-0x5b,
-0x81,
-0x15,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x3,
-0x4d,
-0x53,
-0x45,
-0x4c,
-0x20,
-0x4d,
-0x4f,
-0x45,
-0x56,
-0x20,
-0x4d,
-0x4f,
-0x53,
-0x43,
-0x20,
 0x14,
 0x4a,
 0x4,
@@ -3621,6 +2970,3 @@ static unsigned char AcpiDsdtAmlCode[] = {
 0x46,
 0x0
 };
-static unsigned short piix_dsdt_applesmc_sta[] = {
-0x353
-};
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index bd92c69916..9db7c77605 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -1738,7 +1738,7 @@ static void reset_assigned_device(DeviceState *dev)
     assigned_dev_pci_write_config(pci_dev, PCI_COMMAND, 0, 1);
 }
 
-static int assigned_initfn(struct PCIDevice *pci_dev)
+static void assigned_realize(struct PCIDevice *pci_dev, Error **errp)
 {
     AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
     uint8_t e_intx;
@@ -1821,7 +1821,7 @@ static int assigned_initfn(struct PCIDevice *pci_dev)
 
     assigned_dev_load_option_rom(dev);
 
-    return 0;
+    return;
 
 assigned_out:
     deassign_device(dev);
@@ -1831,9 +1831,7 @@ out:
 
 exit_with_error:
     assert(local_err);
-    qerror_report_err(local_err);
-    error_free(local_err);
-    return -1;
+    error_propagate(errp, local_err);
 }
 
 static void assigned_exitfn(struct PCIDevice *pci_dev)
@@ -1869,7 +1867,7 @@ static void assign_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init         = assigned_initfn;
+    k->realize      = assigned_realize;
     k->exit         = assigned_exitfn;
     k->config_read  = assigned_dev_pci_read_config;
     k->config_write = assigned_dev_pci_write_config;
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index b229856a26..79eaad5fec 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1241,6 +1241,13 @@ FWCfgState *pc_memory_init(MachineState *machine,
             exit(EXIT_FAILURE);
         }
 
+        if (QEMU_ALIGN_UP(machine->maxram_size,
+                          TARGET_PAGE_SIZE) != machine->maxram_size) {
+            error_report("maximum memory size must by aligned to multiple of "
+                         "%d bytes", TARGET_PAGE_SIZE);
+            exit(EXIT_FAILURE);
+        }
+
         pcms->hotplug_memory_base =
             ROUND_UP(0x100000000ULL + above_4g_mem_size, 1ULL << 30);
 
@@ -1666,6 +1673,20 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
     }
 }
 
+static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+                                                DeviceState *dev, Error **errp)
+{
+    error_setg(errp, "acpi: device unplug request for not supported device"
+               " type: %s", object_get_typename(OBJECT(dev)));
+}
+
+static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
+                                        DeviceState *dev, Error **errp)
+{
+    error_setg(errp, "acpi: device unplug for not supported device"
+               " type: %s", object_get_typename(OBJECT(dev)));
+}
+
 static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,
                                              DeviceState *dev)
 {
@@ -1795,6 +1816,8 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     pcmc->get_hotplug_handler = mc->get_hotplug_handler;
     mc->get_hotplug_handler = pc_get_hotpug_handler;
     hc->plug = pc_machine_device_plug_cb;
+    hc->unplug_request = pc_machine_device_unplug_request_cb;
+    hc->unplug = pc_machine_device_unplug_cb;
 }
 
 static const TypeInfo pc_machine_info = {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index de75cf0e87..8eab4ba94d 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -60,6 +60,7 @@ static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 
 static bool has_acpi_build = true;
+static bool rsdp_in_ram = true;
 static int legacy_acpi_table_size;
 static bool smbios_defaults = true;
 static bool smbios_legacy_mode;
@@ -168,6 +169,7 @@ static void pc_init1(MachineState *machine,
 
     guest_info->isapc_ram_fw = !pci_enabled;
     guest_info->has_reserved_memory = has_reserved_memory;
+    guest_info->rsdp_in_ram = rsdp_in_ram;
 
     if (smbios_defaults) {
         MachineClass *mc = MACHINE_GET_CLASS(machine);
@@ -310,6 +312,7 @@ static void pc_init_pci(MachineState *machine)
 
 static void pc_compat_2_2(MachineState *machine)
 {
+    rsdp_in_ram = false;
     x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
     x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
     x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 63027ee76b..c0f21fe725 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -50,6 +50,7 @@
 #define MAX_SATA_PORTS     6
 
 static bool has_acpi_build = true;
+static bool rsdp_in_ram = true;
 static bool smbios_defaults = true;
 static bool smbios_legacy_mode;
 static bool smbios_uuid_encoded = true;
@@ -154,6 +155,7 @@ static void pc_q35_init(MachineState *machine)
     guest_info->isapc_ram_fw = false;
     guest_info->has_acpi_build = has_acpi_build;
     guest_info->has_reserved_memory = has_reserved_memory;
+    guest_info->rsdp_in_ram = rsdp_in_ram;
 
     /* Migration was not supported in 2.0 for Q35, so do not bother
      * with this hack (see hw/i386/acpi-build.c).
@@ -289,6 +291,7 @@ static void pc_q35_init(MachineState *machine)
 
 static void pc_compat_2_2(MachineState *machine)
 {
+    rsdp_in_ram = false;
     x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
     x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
     x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index e1cee5d89a..16eaca3fae 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -48,23 +48,6 @@ DefinitionBlock (
 /****************************************************************
  * PCI Bus definition
  ****************************************************************/
-#define BOARD_SPECIFIC_PCI_RESOURSES \
-     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
-         0x0000, \
-         0x0000, \
-         0x0CD7, \
-         0x0000, \
-         0x0CD8, \
-         ,, , TypeStatic) \
-     /* 0xcd8-0xcf7 hole for CPU hotplug, hw/acpi/ich9.c:ICH9_PROC_BASE */ \
-     WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \
-         0x0000, \
-         0x0D00, \
-         0xFFFF, \
-         0x0000, \
-         0xF300, \
-         ,, , TypeStatic)
-
     Scope(\_SB) {
         Device(PCI0) {
             Name(_HID, EisaId("PNP0A08"))
@@ -131,7 +114,6 @@ DefinitionBlock (
         }
     }
 
-#include "acpi-dsdt-pci-crs.dsl"
 #include "acpi-dsdt-hpet.dsl"
 
 
@@ -168,7 +150,6 @@ DefinitionBlock (
         }
     }
 
-#define DSDT_APPLESMC_STA q35_dsdt_applesmc_sta
 #include "acpi-dsdt-isa.dsl"
 
 
diff --git a/hw/i386/q35-acpi-dsdt.hex.generated b/hw/i386/q35-acpi-dsdt.hex.generated
index 0d5b133150..ed9a2cc8e0 100644
--- a/hw/i386/q35-acpi-dsdt.hex.generated
+++ b/hw/i386/q35-acpi-dsdt.hex.generated
@@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x53,
 0x44,
 0x54,
-0x13,
-0x20,
+0xb8,
+0x1d,
 0x0,
 0x0,
 0x1,
-0x0,
+0x35,
 0x42,
 0x58,
 0x50,
@@ -360,357 +360,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0xa4,
 0x6b,
 0x10,
-0x4e,
-0x15,
-0x2e,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x8,
-0x43,
-0x52,
-0x45,
-0x53,
-0x11,
-0x42,
-0x7,
-0xa,
-0x6e,
-0x88,
-0xd,
-0x0,
-0x2,
-0xc,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xff,
-0x0,
-0x0,
-0x0,
-0x0,
-0x1,
-0x47,
-0x1,
-0xf8,
-0xc,
-0xf8,
-0xc,
-0x1,
-0x8,
-0x88,
-0xd,
-0x0,
-0x1,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0x0,
-0xd7,
-0xc,
-0x0,
-0x0,
-0xd8,
-0xc,
-0x88,
-0xd,
-0x0,
-0x1,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0xd,
-0xff,
-0xff,
-0x0,
-0x0,
-0x0,
-0xf3,
-0x87,
-0x17,
-0x0,
-0x0,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xa,
-0x0,
-0xff,
-0xff,
-0xb,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x2,
-0x0,
-0x87,
-0x17,
-0x0,
-0x0,
-0xc,
-0x1,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xe0,
-0xff,
-0xff,
-0xbf,
-0xfe,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xc0,
-0x1e,
-0x79,
-0x0,
-0x8,
-0x43,
-0x52,
-0x36,
-0x34,
-0x11,
-0x33,
-0xa,
-0x30,
-0x8a,
-0x2b,
-0x0,
-0x0,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x80,
-0x0,
-0x0,
-0x0,
-0xff,
-0xff,
-0xff,
-0xff,
-0xff,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x80,
-0x0,
-0x0,
-0x0,
-0x79,
-0x0,
-0x14,
-0x41,
-0xa,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x0,
-0x8a,
-0x43,
-0x52,
-0x45,
-0x53,
-0xa,
-0x5c,
-0x50,
-0x53,
-0x33,
-0x32,
-0x8a,
-0x43,
-0x52,
-0x45,
-0x53,
-0xa,
-0x60,
-0x50,
-0x45,
-0x33,
-0x32,
-0x8a,
-0x43,
-0x52,
-0x45,
-0x53,
-0xa,
-0x68,
-0x50,
-0x4c,
-0x33,
-0x32,
-0x70,
-0x50,
-0x30,
-0x53,
-0x5f,
-0x50,
-0x53,
-0x33,
-0x32,
-0x70,
-0x50,
-0x30,
-0x45,
-0x5f,
-0x50,
-0x45,
-0x33,
-0x32,
-0x70,
-0x72,
-0x74,
-0x50,
-0x30,
-0x45,
-0x5f,
-0x50,
-0x30,
-0x53,
-0x5f,
-0x0,
-0x1,
-0x0,
-0x50,
-0x4c,
-0x33,
-0x32,
-0xa0,
-0xc,
-0x93,
-0x50,
-0x31,
-0x56,
-0x5f,
-0x0,
-0xa4,
-0x43,
-0x52,
-0x45,
-0x53,
-0x8f,
-0x43,
-0x52,
-0x36,
-0x34,
-0xa,
-0xe,
-0x50,
-0x53,
-0x36,
-0x34,
-0x8f,
-0x43,
-0x52,
-0x36,
-0x34,
-0xa,
-0x16,
-0x50,
-0x45,
-0x36,
-0x34,
-0x8f,
-0x43,
-0x52,
-0x36,
-0x34,
-0xa,
-0x26,
-0x50,
-0x4c,
-0x36,
-0x34,
-0x70,
-0x50,
-0x31,
-0x53,
-0x5f,
-0x50,
-0x53,
-0x36,
-0x34,
-0x70,
-0x50,
-0x31,
-0x45,
-0x5f,
-0x50,
-0x45,
-0x36,
-0x34,
-0x70,
-0x50,
-0x31,
-0x4c,
-0x5f,
-0x50,
-0x4c,
-0x36,
-0x34,
-0x84,
-0x43,
-0x52,
-0x45,
-0x53,
-0x43,
-0x52,
-0x36,
-0x34,
-0x60,
-0xa4,
-0x60,
-0x10,
 0x4d,
 0x8,
 0x5f,
@@ -978,8 +627,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x4e,
 0x1,
 0x10,
-0x4a,
-0x1e,
+0x4c,
+0x1b,
 0x2f,
 0x3,
 0x5f,
@@ -996,52 +645,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x5f,
 0x5b,
 0x82,
-0x2c,
-0x53,
-0x4d,
-0x43,
-0x5f,
-0x8,
-0x5f,
-0x48,
-0x49,
-0x44,
-0xc,
-0x6,
-0x10,
-0x0,
-0x1,
-0x8,
-0x5f,
-0x53,
-0x54,
-0x41,
-0xa,
-0xf0,
-0x8,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x11,
-0x10,
-0xa,
-0xd,
-0x47,
-0x1,
-0x0,
-0x3,
-0x0,
-0x3,
-0x1,
-0x20,
-0x22,
-0x40,
-0x0,
-0x79,
-0x0,
-0x5b,
-0x82,
 0x2d,
 0x52,
 0x54,
@@ -6959,8 +6562,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x53,
 0x1,
 0x10,
-0x4f,
-0x12,
+0x4d,
+0xc,
 0x5f,
 0x53,
 0x42,
@@ -7057,32 +6660,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x22,
 0xa,
 0xc8,
-0x5b,
-0x80,
-0x50,
-0x52,
-0x53,
-0x54,
-0x1,
-0xb,
-0xd8,
-0xc,
-0xa,
-0x20,
-0x5b,
-0x81,
-0xc,
-0x50,
-0x52,
-0x53,
-0x54,
-0x1,
-0x50,
-0x52,
-0x53,
-0x5f,
-0x40,
-0x10,
 0x14,
 0x4a,
 0x6,
@@ -7190,81 +6767,9 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x3,
 0x75,
 0x60,
-0x5b,
-0x82,
-0x46,
-0x4,
-0x50,
-0x52,
-0x45,
-0x53,
-0x8,
-0x5f,
-0x48,
-0x49,
-0x44,
-0xc,
-0x41,
-0xd0,
-0xa,
-0x6,
-0x8,
-0x5f,
-0x55,
-0x49,
-0x44,
-0xd,
-0x43,
-0x50,
-0x55,
-0x20,
-0x68,
-0x6f,
-0x74,
-0x70,
-0x6c,
-0x75,
-0x67,
-0x20,
-0x72,
-0x65,
-0x73,
-0x6f,
-0x75,
-0x72,
-0x63,
-0x65,
-0x73,
-0x0,
-0x8,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x11,
-0xd,
-0xa,
-0xa,
-0x47,
-0x1,
-0xd8,
-0xc,
-0xd8,
-0xc,
-0x0,
-0x20,
-0x79,
-0x0,
-0x8,
-0x5f,
-0x53,
-0x54,
-0x41,
-0xa,
-0xb,
 0x10,
-0x40,
-0x31,
+0x44,
+0x2a,
 0x2e,
 0x5f,
 0x53,
@@ -7276,8 +6781,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x30,
 0x5b,
 0x82,
-0x43,
-0x30,
+0x47,
+0x29,
 0x4d,
 0x48,
 0x50,
@@ -7327,37 +6832,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x65,
 0x73,
 0x0,
-0x5b,
-0x80,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x1,
-0xb,
-0x0,
-0xa,
-0xa,
-0x18,
-0x8,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x11,
-0xd,
-0xa,
-0xa,
-0x47,
-0x1,
-0x0,
-0xa,
-0x0,
-0xa,
-0x0,
-0x18,
-0x79,
-0x0,
 0x14,
 0x13,
 0x5f,
@@ -7379,89 +6853,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0xa,
 0xb,
 0x5b,
-0x81,
-0x1f,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x3,
-0x4d,
-0x52,
-0x42,
-0x4c,
-0x20,
-0x4d,
-0x52,
-0x42,
-0x48,
-0x20,
-0x4d,
-0x52,
-0x4c,
-0x4c,
-0x20,
-0x4d,
-0x52,
-0x4c,
-0x48,
-0x20,
-0x4d,
-0x50,
-0x58,
-0x5f,
-0x20,
-0x5b,
-0x81,
-0x13,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x1,
-0x0,
-0x40,
-0xa,
-0x4d,
-0x45,
-0x53,
-0x5f,
-0x1,
-0x4d,
-0x49,
-0x4e,
-0x53,
-0x1,
-0x5b,
 0x1,
 0x4d,
 0x4c,
 0x43,
 0x4b,
 0x0,
-0x5b,
-0x81,
-0x15,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x3,
-0x4d,
-0x53,
-0x45,
-0x4c,
-0x20,
-0x4d,
-0x4f,
-0x45,
-0x56,
-0x20,
-0x4d,
-0x4f,
-0x53,
-0x43,
-0x20,
 0x14,
 0x4a,
 0x4,
@@ -8211,6 +7608,3 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
 0x46,
 0x0
 };
-static unsigned short q35_dsdt_applesmc_sta[] = {
-0x3fa
-};
diff --git a/hw/i386/ssdt-mem.dsl b/hw/i386/ssdt-mem.dsl
deleted file mode 100644
index 22ff5ddfc3..0000000000
--- a/hw/i386/ssdt-mem.dsl
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Memory hotplug ACPI DSDT static objects definitions
- *
- * Copyright ProfitBricks GmbH 2012
- * Copyright (C) 2013-2014 Red Hat Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>
- */
-
-/* This file is the basis for the ssdt_mem[] variable in src/acpi.c.
- * It defines the contents of the memory device object.  At
- * runtime, a dynamically generated SSDT will contain one copy of this
- * AML snippet for every possible memory device in the system.  The
- * objects will be placed in the \_SB_ namespace.
- *
- * In addition to the aml code generated from this file, the
- * src/acpi.c file creates a MTFY method with an entry for each memdevice:
- *     Method(MTFY, 2) {
- *         If (LEqual(Arg0, 0x00)) { Notify(MP00, Arg1) }
- *         If (LEqual(Arg0, 0x01)) { Notify(MP01, Arg1) }
- *         ...
- *     }
- */
-#include "hw/acpi/pc-hotplug.h"
-
-ACPI_EXTRACT_ALL_CODE ssdm_mem_aml
-
-DefinitionBlock ("ssdt-mem.aml", "SSDT", 0x02, "BXPC", "CSSDT", 0x1)
-{
-
-    External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_CRS_METHOD, MethodObj)
-    External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_STATUS_METHOD, MethodObj)
-    External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_OST_METHOD, MethodObj)
-    External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_PROXIMITY_METHOD, MethodObj)
-
-    Scope(\_SB) {
-/*  v------------------ DO NOT EDIT ------------------v */
-        ACPI_EXTRACT_DEVICE_START ssdt_mem_start
-        ACPI_EXTRACT_DEVICE_END ssdt_mem_end
-        ACPI_EXTRACT_DEVICE_STRING ssdt_mem_name
-        Device(MPAA) {
-            ACPI_EXTRACT_NAME_STRING ssdt_mem_id
-            Name(_UID, "0xAA")
-/*  ^------------------ DO NOT EDIT ------------------^
- * Don't change the above without also updating the C code.
- */
-            Name(_HID, EISAID("PNP0C80"))
-
-            Method(_CRS, 0) {
-                Return(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_CRS_METHOD(_UID))
-            }
-
-            Method(_STA, 0) {
-                Return(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_STATUS_METHOD(_UID))
-            }
-
-            Method(_PXM, 0) {
-                Return(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_PROXIMITY_METHOD(_UID))
-            }
-
-            Method(_OST, 3) {
-                \_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_OST_METHOD(_UID, Arg0, Arg1, Arg2)
-            }
-        }
-    }
-}
diff --git a/hw/i386/ssdt-mem.hex.generated b/hw/i386/ssdt-mem.hex.generated
deleted file mode 100644
index b3bfbbda09..0000000000
--- a/hw/i386/ssdt-mem.hex.generated
+++ /dev/null
@@ -1,213 +0,0 @@
-static unsigned char ssdt_mem_id[] = {
-0x35
-};
-static unsigned char ssdm_mem_aml[] = {
-0x53,
-0x53,
-0x44,
-0x54,
-0xc7,
-0x0,
-0x0,
-0x0,
-0x2,
-0x66,
-0x42,
-0x58,
-0x50,
-0x43,
-0x0,
-0x0,
-0x43,
-0x53,
-0x53,
-0x44,
-0x54,
-0x0,
-0x0,
-0x0,
-0x1,
-0x0,
-0x0,
-0x0,
-0x49,
-0x4e,
-0x54,
-0x4c,
-0x28,
-0x8,
-0x14,
-0x20,
-0x10,
-0x42,
-0xa,
-0x5c,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x5b,
-0x82,
-0x49,
-0x9,
-0x4d,
-0x50,
-0x41,
-0x41,
-0x8,
-0x5f,
-0x55,
-0x49,
-0x44,
-0xd,
-0x30,
-0x78,
-0x41,
-0x41,
-0x0,
-0x8,
-0x5f,
-0x48,
-0x49,
-0x44,
-0xc,
-0x41,
-0xd0,
-0xc,
-0x80,
-0x14,
-0x1e,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x0,
-0xa4,
-0x5c,
-0x2f,
-0x4,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x4d,
-0x48,
-0x50,
-0x44,
-0x4d,
-0x43,
-0x52,
-0x53,
-0x5f,
-0x55,
-0x49,
-0x44,
-0x14,
-0x1e,
-0x5f,
-0x53,
-0x54,
-0x41,
-0x0,
-0xa4,
-0x5c,
-0x2f,
-0x4,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x4d,
-0x48,
-0x50,
-0x44,
-0x4d,
-0x52,
-0x53,
-0x54,
-0x5f,
-0x55,
-0x49,
-0x44,
-0x14,
-0x1e,
-0x5f,
-0x50,
-0x58,
-0x4d,
-0x0,
-0xa4,
-0x5c,
-0x2f,
-0x4,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x4d,
-0x48,
-0x50,
-0x44,
-0x4d,
-0x50,
-0x58,
-0x4d,
-0x5f,
-0x55,
-0x49,
-0x44,
-0x14,
-0x20,
-0x5f,
-0x4f,
-0x53,
-0x54,
-0x3,
-0x5c,
-0x2f,
-0x4,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x4d,
-0x48,
-0x50,
-0x44,
-0x4d,
-0x4f,
-0x53,
-0x54,
-0x5f,
-0x55,
-0x49,
-0x44,
-0x68,
-0x69,
-0x6a
-};
-static unsigned char ssdt_mem_start[] = {
-0x2c
-};
-static unsigned char ssdt_mem_end[] = {
-0xc7
-};
-static unsigned char ssdt_mem_name[] = {
-0x30
-};
diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
deleted file mode 100644
index 1e3baaed3d..0000000000
--- a/hw/i386/ssdt-misc.dsl
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "hw/acpi/pc-hotplug.h"
-
-ACPI_EXTRACT_ALL_CODE ssdp_misc_aml
-
-DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
-{
-
-/****************************************************************
- * PCI memory ranges
- ****************************************************************/
-
-    Scope(\) {
-       ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start
-       Name(P0S, 0x12345678)
-       ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end
-       Name(P0E, 0x12345678)
-       ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid
-       Name(P1V, 0x12)
-       ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start
-       Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
-       ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end
-       Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
-       ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length
-       Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
-       ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mctrl_nr_slots
-       Name(MEMORY_SLOTS_NUMBER, 0x12345678)
-    }
-
-
-/****************************************************************
- * Suspend
- ****************************************************************/
-
-    Scope(\) {
-    /*
-     * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
-     * must match piix4 emulation.
-     */
-
-        ACPI_EXTRACT_NAME_STRING acpi_s3_name
-        Name(_S3, Package(0x04) {
-            One,  /* PM1a_CNT.SLP_TYP */
-            One,  /* PM1b_CNT.SLP_TYP */
-            Zero,  /* reserved */
-            Zero   /* reserved */
-        })
-        ACPI_EXTRACT_NAME_STRING acpi_s4_name
-        ACPI_EXTRACT_PKG_START acpi_s4_pkg
-        Name(_S4, Package(0x04) {
-            0x2,  /* PM1a_CNT.SLP_TYP */
-            0x2,  /* PM1b_CNT.SLP_TYP */
-            Zero,  /* reserved */
-            Zero   /* reserved */
-        })
-        Name(_S5, Package(0x04) {
-            Zero,  /* PM1a_CNT.SLP_TYP */
-            Zero,  /* PM1b_CNT.SLP_TYP */
-            Zero,  /* reserved */
-            Zero   /* reserved */
-        })
-    }
-
-    External(\_SB.PCI0, DeviceObj)
-    External(\_SB.PCI0.ISA, DeviceObj)
-
-    Scope(\_SB.PCI0.ISA) {
-        Device(PEVT) {
-            Name(_HID, "QEMU0001")
-            /* PEST will be patched to be Zero if no such device */
-            ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest
-            Name(PEST, 0xFFFF)
-            OperationRegion(PEOR, SystemIO, PEST, 0x01)
-            Field(PEOR, ByteAcc, NoLock, Preserve) {
-                PEPT,   8,
-            }
-
-            Method(_STA, 0, NotSerialized) {
-                Store(PEST, Local0)
-                If (LEqual(Local0, Zero)) {
-                    Return (0x00)
-                } Else {
-                    Return (0x0F)
-                }
-            }
-
-            Method(RDPT, 0, NotSerialized) {
-                Store(PEPT, Local0)
-                Return (Local0)
-            }
-
-            Method(WRPT, 1, NotSerialized) {
-                Store(Arg0, PEPT)
-            }
-
-            Name(_CRS, ResourceTemplate() {
-                IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO)
-            })
-
-            CreateWordField(_CRS, IO._MIN, IOMN)
-            CreateWordField(_CRS, IO._MAX, IOMX)
-
-            Method(_INI, 0, NotSerialized) {
-                Store(PEST, IOMN)
-                Store(PEST, IOMX)
-            }
-        }
-    }
-}
diff --git a/hw/i386/ssdt-misc.hex.generated b/hw/i386/ssdt-misc.hex.generated
deleted file mode 100644
index cbcf61dcce..0000000000
--- a/hw/i386/ssdt-misc.hex.generated
+++ /dev/null
@@ -1,399 +0,0 @@
-static unsigned char acpi_pci64_length[] = {
-0x6f
-};
-static unsigned char acpi_s4_pkg[] = {
-0x99
-};
-static unsigned char ssdt_mctrl_nr_slots[] = {
-0x7d
-};
-static unsigned char acpi_s3_name[] = {
-0x86
-};
-static unsigned char acpi_pci32_start[] = {
-0x2f
-};
-static unsigned char acpi_pci64_valid[] = {
-0x43
-};
-static unsigned char ssdp_misc_aml[] = {
-0x53,
-0x53,
-0x44,
-0x54,
-0x6c,
-0x1,
-0x0,
-0x0,
-0x1,
-0x3,
-0x42,
-0x58,
-0x50,
-0x43,
-0x0,
-0x0,
-0x42,
-0x58,
-0x53,
-0x53,
-0x44,
-0x54,
-0x53,
-0x55,
-0x1,
-0x0,
-0x0,
-0x0,
-0x49,
-0x4e,
-0x54,
-0x4c,
-0x28,
-0x8,
-0x14,
-0x20,
-0x10,
-0x4c,
-0x5,
-0x5c,
-0x0,
-0x8,
-0x50,
-0x30,
-0x53,
-0x5f,
-0xc,
-0x78,
-0x56,
-0x34,
-0x12,
-0x8,
-0x50,
-0x30,
-0x45,
-0x5f,
-0xc,
-0x78,
-0x56,
-0x34,
-0x12,
-0x8,
-0x50,
-0x31,
-0x56,
-0x5f,
-0xa,
-0x12,
-0x8,
-0x50,
-0x31,
-0x53,
-0x5f,
-0x11,
-0xb,
-0xa,
-0x8,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x8,
-0x50,
-0x31,
-0x45,
-0x5f,
-0x11,
-0xb,
-0xa,
-0x8,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x8,
-0x50,
-0x31,
-0x4c,
-0x5f,
-0x11,
-0xb,
-0xa,
-0x8,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x8,
-0x4d,
-0x44,
-0x4e,
-0x52,
-0xc,
-0x78,
-0x56,
-0x34,
-0x12,
-0x10,
-0x29,
-0x5c,
-0x0,
-0x8,
-0x5f,
-0x53,
-0x33,
-0x5f,
-0x12,
-0x6,
-0x4,
-0x1,
-0x1,
-0x0,
-0x0,
-0x8,
-0x5f,
-0x53,
-0x34,
-0x5f,
-0x12,
-0x8,
-0x4,
-0xa,
-0x2,
-0xa,
-0x2,
-0x0,
-0x0,
-0x8,
-0x5f,
-0x53,
-0x35,
-0x5f,
-0x12,
-0x6,
-0x4,
-0x0,
-0x0,
-0x0,
-0x0,
-0x10,
-0x40,
-0xc,
-0x5c,
-0x2f,
-0x3,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x49,
-0x53,
-0x41,
-0x5f,
-0x5b,
-0x82,
-0x4d,
-0xa,
-0x50,
-0x45,
-0x56,
-0x54,
-0x8,
-0x5f,
-0x48,
-0x49,
-0x44,
-0xd,
-0x51,
-0x45,
-0x4d,
-0x55,
-0x30,
-0x30,
-0x30,
-0x31,
-0x0,
-0x8,
-0x50,
-0x45,
-0x53,
-0x54,
-0xb,
-0xff,
-0xff,
-0x5b,
-0x80,
-0x50,
-0x45,
-0x4f,
-0x52,
-0x1,
-0x50,
-0x45,
-0x53,
-0x54,
-0x1,
-0x5b,
-0x81,
-0xb,
-0x50,
-0x45,
-0x4f,
-0x52,
-0x1,
-0x50,
-0x45,
-0x50,
-0x54,
-0x8,
-0x14,
-0x18,
-0x5f,
-0x53,
-0x54,
-0x41,
-0x0,
-0x70,
-0x50,
-0x45,
-0x53,
-0x54,
-0x60,
-0xa0,
-0x6,
-0x93,
-0x60,
-0x0,
-0xa4,
-0x0,
-0xa1,
-0x4,
-0xa4,
-0xa,
-0xf,
-0x14,
-0xe,
-0x52,
-0x44,
-0x50,
-0x54,
-0x0,
-0x70,
-0x50,
-0x45,
-0x50,
-0x54,
-0x60,
-0xa4,
-0x60,
-0x14,
-0xc,
-0x57,
-0x52,
-0x50,
-0x54,
-0x1,
-0x70,
-0x68,
-0x50,
-0x45,
-0x50,
-0x54,
-0x8,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x11,
-0xd,
-0xa,
-0xa,
-0x47,
-0x1,
-0x0,
-0x0,
-0x0,
-0x0,
-0x1,
-0x1,
-0x79,
-0x0,
-0x8b,
-0x5f,
-0x43,
-0x52,
-0x53,
-0xa,
-0x2,
-0x49,
-0x4f,
-0x4d,
-0x4e,
-0x8b,
-0x5f,
-0x43,
-0x52,
-0x53,
-0xa,
-0x4,
-0x49,
-0x4f,
-0x4d,
-0x58,
-0x14,
-0x18,
-0x5f,
-0x49,
-0x4e,
-0x49,
-0x0,
-0x70,
-0x50,
-0x45,
-0x53,
-0x54,
-0x49,
-0x4f,
-0x4d,
-0x4e,
-0x70,
-0x50,
-0x45,
-0x53,
-0x54,
-0x49,
-0x4f,
-0x4d,
-0x58
-};
-static unsigned char ssdt_isa_pest[] = {
-0xda
-};
-static unsigned char acpi_s4_name[] = {
-0x92
-};
-static unsigned char acpi_pci64_start[] = {
-0x4d
-};
-static unsigned char acpi_pci64_end[] = {
-0x5e
-};
-static unsigned char acpi_pci32_end[] = {
-0x39
-};
diff --git a/hw/i386/ssdt-pcihp.dsl b/hw/i386/ssdt-pcihp.dsl
deleted file mode 100644
index ac91c05836..0000000000
--- a/hw/i386/ssdt-pcihp.dsl
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml
-
-DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
-{
-
-/****************************************************************
- * PCI hotplug
- ****************************************************************/
-
-    /* Objects supplied by DSDT */
-    External(\_SB.PCI0, DeviceObj)
-    External(\_SB.PCI0.PCEJ, MethodObj)
-    External(BSEL, IntObj)
-
-    Scope(\_SB.PCI0) {
-
-        /* Bulk generated PCI hotplug devices */
-        ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start
-        ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
-        ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
-
-        // Extract the offsets of the device name, address dword and the slot
-        // name byte - we fill them in for each device.
-        Device(SAA) {
-            ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
-            Name(_SUN, 0xAA)
-            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
-            Name(_ADR, 0xAA0000)
-            Method(_EJ0, 1) {
-                PCEJ(BSEL, _SUN)
-            }
-        }
-
-        ACPI_EXTRACT_DEVICE_START ssdt_pcinohp_start
-        ACPI_EXTRACT_DEVICE_END ssdt_pcinohp_end
-        ACPI_EXTRACT_DEVICE_STRING ssdt_pcinohp_name
-
-        // Extract the offsets of the device name, address dword and the slot
-        // name byte - we fill them in for each device.
-        Device(SBB) {
-            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcinohp_adr
-            Name(_ADR, 0xAA0000)
-        }
-
-        ACPI_EXTRACT_DEVICE_START ssdt_pcivga_start
-        ACPI_EXTRACT_DEVICE_END ssdt_pcivga_end
-        ACPI_EXTRACT_DEVICE_STRING ssdt_pcivga_name
-
-        // Extract the offsets of the device name, address dword and the slot
-        // name byte - we fill them in for each device.
-        Device(SCC) {
-            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcivga_adr
-            Name(_ADR, 0xAA0000)
-            Method(_S1D, 0, NotSerialized) {
-                Return (0x00)
-            }
-            Method(_S2D, 0, NotSerialized) {
-                Return (0x00)
-            }
-            Method(_S3D, 0, NotSerialized) {
-                Return (0x00)
-            }
-        }
-
-        ACPI_EXTRACT_DEVICE_START ssdt_pciqxl_start
-        ACPI_EXTRACT_DEVICE_END ssdt_pciqxl_end
-        ACPI_EXTRACT_DEVICE_STRING ssdt_pciqxl_name
-
-        // Extract the offsets of the device name, address dword and the slot
-        // name byte - we fill them in for each device.
-        Device(SDD) {
-            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pciqxl_adr
-            Name(_ADR, 0xAA0000)
-            Method(_S1D, 0, NotSerialized) {
-                Return (0x00)
-            }
-            Method(_S2D, 0, NotSerialized) {
-                Return (0x00)
-            }
-            Method(_S3D, 0, NotSerialized) {
-                Return (0x03)           // QXL
-            }
-        }
-    }
-}
diff --git a/hw/i386/ssdt-pcihp.hex.generated b/hw/i386/ssdt-pcihp.hex.generated
deleted file mode 100644
index 72ffa84800..0000000000
--- a/hw/i386/ssdt-pcihp.hex.generated
+++ /dev/null
@@ -1,251 +0,0 @@
-static unsigned char ssdt_pcihp_name[] = {
-0x34
-};
-static unsigned char ssdt_pcivga_end[] = {
-0x99
-};
-static unsigned char ssdt_pcivga_name[] = {
-0x70
-};
-static unsigned char ssdt_pcihp_adr[] = {
-0x45
-};
-static unsigned char ssdt_pcinohp_end[] = {
-0x6d
-};
-static unsigned char ssdt_pcihp_end[] = {
-0x5c
-};
-static unsigned char ssdt_pciqxl_start[] = {
-0x99
-};
-static unsigned char ssdt_pcinohp_name[] = {
-0x5f
-};
-static unsigned char ssdp_pcihp_aml[] = {
-0x53,
-0x53,
-0x44,
-0x54,
-0xc6,
-0x0,
-0x0,
-0x0,
-0x1,
-0x70,
-0x42,
-0x58,
-0x50,
-0x43,
-0x0,
-0x0,
-0x42,
-0x58,
-0x53,
-0x53,
-0x44,
-0x54,
-0x50,
-0x43,
-0x1,
-0x0,
-0x0,
-0x0,
-0x49,
-0x4e,
-0x54,
-0x4c,
-0x15,
-0x11,
-0x13,
-0x20,
-0x10,
-0x41,
-0xa,
-0x5c,
-0x2e,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x5b,
-0x82,
-0x29,
-0x53,
-0x41,
-0x41,
-0x5f,
-0x8,
-0x5f,
-0x53,
-0x55,
-0x4e,
-0xa,
-0xaa,
-0x8,
-0x5f,
-0x41,
-0x44,
-0x52,
-0xc,
-0x0,
-0x0,
-0xaa,
-0x0,
-0x14,
-0x12,
-0x5f,
-0x45,
-0x4a,
-0x30,
-0x1,
-0x50,
-0x43,
-0x45,
-0x4a,
-0x42,
-0x53,
-0x45,
-0x4c,
-0x5f,
-0x53,
-0x55,
-0x4e,
-0x5b,
-0x82,
-0xf,
-0x53,
-0x42,
-0x42,
-0x5f,
-0x8,
-0x5f,
-0x41,
-0x44,
-0x52,
-0xc,
-0x0,
-0x0,
-0xaa,
-0x0,
-0x5b,
-0x82,
-0x2a,
-0x53,
-0x43,
-0x43,
-0x5f,
-0x8,
-0x5f,
-0x41,
-0x44,
-0x52,
-0xc,
-0x0,
-0x0,
-0xaa,
-0x0,
-0x14,
-0x8,
-0x5f,
-0x53,
-0x31,
-0x44,
-0x0,
-0xa4,
-0x0,
-0x14,
-0x8,
-0x5f,
-0x53,
-0x32,
-0x44,
-0x0,
-0xa4,
-0x0,
-0x14,
-0x8,
-0x5f,
-0x53,
-0x33,
-0x44,
-0x0,
-0xa4,
-0x0,
-0x5b,
-0x82,
-0x2b,
-0x53,
-0x44,
-0x44,
-0x5f,
-0x8,
-0x5f,
-0x41,
-0x44,
-0x52,
-0xc,
-0x0,
-0x0,
-0xaa,
-0x0,
-0x14,
-0x8,
-0x5f,
-0x53,
-0x31,
-0x44,
-0x0,
-0xa4,
-0x0,
-0x14,
-0x8,
-0x5f,
-0x53,
-0x32,
-0x44,
-0x0,
-0xa4,
-0x0,
-0x14,
-0x9,
-0x5f,
-0x53,
-0x33,
-0x44,
-0x0,
-0xa4,
-0xa,
-0x3
-};
-static unsigned char ssdt_pciqxl_adr[] = {
-0xa6
-};
-static unsigned char ssdt_pcinohp_adr[] = {
-0x69
-};
-static unsigned char ssdt_pcivga_adr[] = {
-0x7a
-};
-static unsigned char ssdt_pciqxl_name[] = {
-0x9c
-};
-static unsigned char ssdt_pcivga_start[] = {
-0x6d
-};
-static unsigned char ssdt_pciqxl_end[] = {
-0xc6
-};
-static unsigned char ssdt_pcihp_start[] = {
-0x31
-};
-static unsigned char ssdt_pcihp_id[] = {
-0x3e
-};
-static unsigned char ssdt_pcinohp_start[] = {
-0x5c
-};
diff --git a/hw/i386/ssdt-proc.dsl b/hw/i386/ssdt-proc.dsl
deleted file mode 100644
index 8229bfd702..0000000000
--- a/hw/i386/ssdt-proc.dsl
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* This file is the basis for the ssdt table generated in src/acpi.c.
- * It defines the contents of the per-cpu Processor() object.  At
- * runtime, a dynamically generated SSDT will contain one copy of this
- * AML snippet for every possible cpu in the system.  The objects will
- * be placed in the \_SB_ namespace.
- *
- * In addition to the aml code generated from this file, the
- * src/acpi.c file creates a NTFY method with an entry for each cpu:
- *     Method(NTFY, 2) {
- *         If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) }
- *         If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) }
- *         ...
- *     }
- * and a CPON array with the list of active and inactive cpus:
- *     Name(CPON, Package() { One, One, ..., Zero, Zero, ... })
- */
-
-ACPI_EXTRACT_ALL_CODE ssdp_proc_aml
-
-DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1)
-{
-    ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start
-    ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end
-    ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name
-    Processor(CPAA, 0xAA, 0x00000000, 0x0) {
-        ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id
-        Name(ID, 0xAA)
-/*
- * The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update
- * CPAA and 0xAA with the appropriate CPU id (see
- * SD_OFFSET_CPUHEX/CPUID1/CPUID2).  Don't change the above without
- * also updating the C code.
- */
-        Name(_HID, "ACPI0007")
-        External(CPMA, MethodObj)
-        External(CPST, MethodObj)
-        External(CPEJ, MethodObj)
-        Method(_MAT, 0) {
-            Return (CPMA(ID))
-        }
-        Method(_STA, 0) {
-            Return (CPST(ID))
-        }
-        Method(_EJ0, 1, NotSerialized) {
-            CPEJ(ID, Arg0)
-        }
-    }
-}
diff --git a/hw/i386/ssdt-proc.hex.generated b/hw/i386/ssdt-proc.hex.generated
deleted file mode 100644
index 4df0734c79..0000000000
--- a/hw/i386/ssdt-proc.hex.generated
+++ /dev/null
@@ -1,134 +0,0 @@
-static unsigned char ssdt_proc_name[] = {
-0x28
-};
-static unsigned char ssdp_proc_aml[] = {
-0x53,
-0x53,
-0x44,
-0x54,
-0x78,
-0x0,
-0x0,
-0x0,
-0x1,
-0x7d,
-0x42,
-0x58,
-0x50,
-0x43,
-0x0,
-0x0,
-0x42,
-0x58,
-0x53,
-0x53,
-0x44,
-0x54,
-0x0,
-0x0,
-0x1,
-0x0,
-0x0,
-0x0,
-0x49,
-0x4e,
-0x54,
-0x4c,
-0x15,
-0x11,
-0x13,
-0x20,
-0x5b,
-0x83,
-0x42,
-0x5,
-0x43,
-0x50,
-0x41,
-0x41,
-0xaa,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x8,
-0x49,
-0x44,
-0x5f,
-0x5f,
-0xa,
-0xaa,
-0x8,
-0x5f,
-0x48,
-0x49,
-0x44,
-0xd,
-0x41,
-0x43,
-0x50,
-0x49,
-0x30,
-0x30,
-0x30,
-0x37,
-0x0,
-0x14,
-0xf,
-0x5f,
-0x4d,
-0x41,
-0x54,
-0x0,
-0xa4,
-0x43,
-0x50,
-0x4d,
-0x41,
-0x49,
-0x44,
-0x5f,
-0x5f,
-0x14,
-0xf,
-0x5f,
-0x53,
-0x54,
-0x41,
-0x0,
-0xa4,
-0x43,
-0x50,
-0x53,
-0x54,
-0x49,
-0x44,
-0x5f,
-0x5f,
-0x14,
-0xf,
-0x5f,
-0x45,
-0x4a,
-0x30,
-0x1,
-0x43,
-0x50,
-0x45,
-0x4a,
-0x49,
-0x44,
-0x5f,
-0x5f,
-0x68
-};
-static unsigned char ssdt_proc_id[] = {
-0x38
-};
-static unsigned char ssdt_proc_end[] = {
-0x78
-};
-static unsigned char ssdt_proc_start[] = {
-0x24
-};
diff --git a/hw/i386/ssdt-tpm.hex.generated b/hw/i386/ssdt-tpm.hex.generated
index 4a916a8398..e84dc6cfc0 100644
--- a/hw/i386/ssdt-tpm.hex.generated
+++ b/hw/i386/ssdt-tpm.hex.generated
@@ -8,7 +8,7 @@ static unsigned char ssdt_tpm_aml[] = {
 0x0,
 0x0,
 0x1,
-0xf,
+0x1c,
 0x42,
 0x58,
 0x50,
@@ -31,9 +31,9 @@ static unsigned char ssdt_tpm_aml[] = {
 0x4e,
 0x54,
 0x4c,
-0x15,
+0x7,
 0x11,
-0x13,
+0x14,
 0x20,
 0x10,
 0x38,
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index c8b0322155..dafa9ec7c7 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -326,7 +326,7 @@ static void cmd646_pci_config_write(PCIDevice *d, uint32_t addr, uint32_t val,
 }
 
 /* CMD646 PCI IDE controller */
-static int pci_cmd646_ide_initfn(PCIDevice *dev)
+static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp)
 {
     PCIIDEState *d = PCI_IDE(dev);
     uint8_t *pci_conf = dev->config;
@@ -374,7 +374,6 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
 
     vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
     qemu_register_reset(cmd646_reset, d);
-    return 0;
 }
 
 static void pci_cmd646_ide_exitfn(PCIDevice *dev)
@@ -410,7 +409,7 @@ static void cmd646_ide_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_cmd646_ide_initfn;
+    k->realize = pci_cmd646_ide_realize;
     k->exit = pci_cmd646_ide_exitfn;
     k->vendor_id = PCI_VENDOR_ID_CMD;
     k->device_id = PCI_DEVICE_ID_CMD_646;
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index fb1d095503..b1d8874671 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -98,7 +98,7 @@ static void pci_ich9_reset(DeviceState *dev)
     ahci_reset(&d->ahci);
 }
 
-static int pci_ich9_ahci_init(PCIDevice *dev)
+static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
 {
     struct AHCIPCIState *d;
     int sata_cap_offset;
@@ -123,10 +123,11 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
     pci_register_bar(dev, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY,
                      &d->ahci.mem);
 
-    sata_cap_offset = pci_add_capability(dev, PCI_CAP_ID_SATA,
-                                         ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE);
+    sata_cap_offset = pci_add_capability2(dev, PCI_CAP_ID_SATA,
+                                          ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE,
+                                          errp);
     if (sata_cap_offset < 0) {
-        return sata_cap_offset;
+        return;
     }
 
     sata_cap = dev->config + sata_cap_offset;
@@ -139,8 +140,6 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
      * should be PMCAP, the Intel ICH9 data sheet specifies that the ICH9
      * AHCI device puts the MSI capability first, pointing to 0x80. */
     msi_init(dev, ICH9_MSI_CAP_OFFSET, 1, true, false);
-
-    return 0;
 }
 
 static void pci_ich9_uninit(PCIDevice *dev)
@@ -158,7 +157,7 @@ static void ich_ahci_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_ich9_ahci_init;
+    k->realize = pci_ich9_ahci_realize;
     k->exit = pci_ich9_uninit;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_82801IR;
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index b0172fbf59..ab930843e8 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -148,7 +148,7 @@ static void pci_piix_init_ports(PCIIDEState *d) {
     }
 }
 
-static int pci_piix_ide_initfn(PCIDevice *dev)
+static void pci_piix_ide_realize(PCIDevice *dev, Error **errp)
 {
     PCIIDEState *d = PCI_IDE(dev);
     uint8_t *pci_conf = dev->config;
@@ -163,8 +163,6 @@ static int pci_piix_ide_initfn(PCIDevice *dev)
     vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
 
     pci_piix_init_ports(d);
-
-    return 0;
 }
 
 int pci_piix3_xen_ide_unplug(DeviceState *dev)
@@ -238,7 +236,7 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_piix_ide_initfn;
+    k->realize = pci_piix_ide_realize;
     k->exit = pci_piix_ide_exitfn;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
@@ -258,7 +256,7 @@ static void piix3_ide_xen_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_piix_ide_initfn;
+    k->realize = pci_piix_ide_realize;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
     k->class_id = PCI_CLASS_STORAGE_IDE;
@@ -276,7 +274,7 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_piix_ide_initfn;
+    k->realize = pci_piix_ide_realize;
     k->exit = pci_piix_ide_exitfn;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_82371AB;
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 4d8089de75..7a5151c5c1 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -172,7 +172,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) {
 }
 
 /* via ide func */
-static int vt82c686b_ide_initfn(PCIDevice *dev)
+static void vt82c686b_ide_realize(PCIDevice *dev, Error **errp)
 {
     PCIIDEState *d = PCI_IDE(dev);
     uint8_t *pci_conf = dev->config;
@@ -187,8 +187,6 @@ static int vt82c686b_ide_initfn(PCIDevice *dev)
     vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
 
     vt82c686b_init_ports(d);
-
-    return 0;
 }
 
 static void vt82c686b_ide_exitfn(PCIDevice *dev)
@@ -215,7 +213,7 @@ static void via_ide_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = vt82c686b_ide_initfn;
+    k->realize = vt82c686b_ide_realize;
     k->exit = vt82c686b_ide_exitfn;
     k->vendor_id = PCI_VENDOR_ID_VIA;
     k->device_id = PCI_DEVICE_ID_VIA_IDE;
diff --git a/hw/ipack/tpci200.c b/hw/ipack/tpci200.c
index b7031a0b13..1df02ee859 100644
--- a/hw/ipack/tpci200.c
+++ b/hw/ipack/tpci200.c
@@ -573,7 +573,7 @@ static const MemoryRegionOps tpci200_las3_ops = {
     }
 };
 
-static int tpci200_initfn(PCIDevice *pci_dev)
+static void tpci200_realize(PCIDevice *pci_dev, Error **errp)
 {
     TPCI200State *s = TPCI200(pci_dev);
     uint8_t *c = s->dev.config;
@@ -609,8 +609,6 @@ static int tpci200_initfn(PCIDevice *pci_dev)
 
     ipack_bus_new_inplace(&s->bus, sizeof(s->bus), DEVICE(pci_dev), NULL,
                           N_MODULES, tpci200_set_irq);
-
-    return 0;
 }
 
 static const VMStateDescription vmstate_tpci200 = {
@@ -632,7 +630,7 @@ static void tpci200_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = tpci200_initfn;
+    k->realize = tpci200_realize;
     k->vendor_id = PCI_VENDOR_ID_TEWS;
     k->device_id = PCI_DEVICE_ID_TEWS_TPCI200;
     k->class_id = PCI_CLASS_BRIDGE_OTHER;
diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c
index 0dc440df5c..9da9dfc4da 100644
--- a/hw/isa/i82378.c
+++ b/hw/isa/i82378.c
@@ -58,7 +58,7 @@ static void i82378_request_pic_irq(void *opaque, int irq, int level)
     qemu_set_irq(s->i8259[irq], level);
 }
 
-static int i82378_initfn(PCIDevice *pci)
+static void i82378_realize(PCIDevice *pci, Error **errp)
 {
     DeviceState *dev = DEVICE(pci);
     I82378State *s = I82378(dev);
@@ -107,8 +107,6 @@ static int i82378_initfn(PCIDevice *pci)
 
     /* timer */
     isa_create_simple(isabus, "mc146818rtc");
-
-    return 0;
 }
 
 static void i82378_init(Object *obj)
@@ -125,7 +123,7 @@ static void i82378_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = i82378_initfn;
+    k->realize = i82378_realize;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_82378;
     k->revision = 0x03;
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 231de74414..dba758595f 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -610,8 +610,17 @@ static void ich9_device_plug_cb(HotplugHandler *hotplug_dev,
 static void ich9_device_unplug_request_cb(HotplugHandler *hotplug_dev,
                                           DeviceState *dev, Error **errp)
 {
-    error_setg(errp, "acpi: device unplug request for not supported device"
-               " type: %s", object_get_typename(OBJECT(dev)));
+    ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
+
+    ich9_pm_device_unplug_request_cb(&lpc->pm, dev, errp);
+}
+
+static void ich9_device_unplug_cb(HotplugHandler *hotplug_dev,
+                                  DeviceState *dev, Error **errp)
+{
+    ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
+
+    ich9_pm_device_unplug_cb(&lpc->pm, dev, errp);
 }
 
 static bool ich9_rst_cnt_needed(void *opaque)
@@ -677,6 +686,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)
     dc->cannot_instantiate_with_device_add_yet = true;
     hc->plug = ich9_device_plug_cb;
     hc->unplug_request = ich9_device_unplug_request_cb;
+    hc->unplug = ich9_device_unplug_cb;
     adevc->ospm_status = ich9_pm_ospm_status;
 }
 
diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
index a9916df20a..d9522b1f45 100644
--- a/hw/isa/piix4.c
+++ b/hw/isa/piix4.c
@@ -82,7 +82,7 @@ static const VMStateDescription vmstate_piix4 = {
     }
 };
 
-static int piix4_initfn(PCIDevice *dev)
+static void piix4_realize(PCIDevice *dev, Error **errp)
 {
     PIIX4State *d = DO_UPCAST(PIIX4State, dev, dev);
 
@@ -90,7 +90,6 @@ static int piix4_initfn(PCIDevice *dev)
                 pci_address_space_io(dev));
     piix4_dev = &d->dev;
     qemu_register_reset(piix4_reset, d);
-    return 0;
 }
 
 int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn)
@@ -107,7 +106,7 @@ static void piix4_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = piix4_initfn;
+    k->realize = piix4_realize;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0;
     k->class_id = PCI_CLASS_BRIDGE_ISA;
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index b223526bde..b8197b115d 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -245,7 +245,7 @@ static const VMStateDescription vmstate_acpi = {
  * just register a PCI device now, functionalities will be implemented later.
  */
 
-static int vt82c686b_ac97_initfn(PCIDevice *dev)
+static void vt82c686b_ac97_realize(PCIDevice *dev, Error **errp)
 {
     VT686AC97State *s = DO_UPCAST(VT686AC97State, dev, dev);
     uint8_t *pci_conf = s->dev.config;
@@ -255,8 +255,6 @@ static int vt82c686b_ac97_initfn(PCIDevice *dev)
     pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST |
                  PCI_STATUS_DEVSEL_MEDIUM);
     pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03);
-
-    return 0;
 }
 
 void vt82c686b_ac97_init(PCIBus *bus, int devfn)
@@ -272,7 +270,7 @@ static void via_ac97_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = vt82c686b_ac97_initfn;
+    k->realize = vt82c686b_ac97_realize;
     k->vendor_id = PCI_VENDOR_ID_VIA;
     k->device_id = PCI_DEVICE_ID_VIA_AC97;
     k->revision = 0x50;
@@ -288,7 +286,7 @@ static const TypeInfo via_ac97_info = {
     .class_init    = via_ac97_class_init,
 };
 
-static int vt82c686b_mc97_initfn(PCIDevice *dev)
+static void vt82c686b_mc97_realize(PCIDevice *dev, Error **errp)
 {
     VT686MC97State *s = DO_UPCAST(VT686MC97State, dev, dev);
     uint8_t *pci_conf = s->dev.config;
@@ -297,8 +295,6 @@ static int vt82c686b_mc97_initfn(PCIDevice *dev)
                  PCI_COMMAND_VGA_PALETTE);
     pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM);
     pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03);
-
-    return 0;
 }
 
 void vt82c686b_mc97_init(PCIBus *bus, int devfn)
@@ -314,7 +310,7 @@ static void via_mc97_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = vt82c686b_mc97_initfn;
+    k->realize = vt82c686b_mc97_realize;
     k->vendor_id = PCI_VENDOR_ID_VIA;
     k->device_id = PCI_DEVICE_ID_VIA_MC97;
     k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
@@ -331,7 +327,7 @@ static const TypeInfo via_mc97_info = {
 };
 
 /* vt82c686 pm init */
-static int vt82c686b_pm_initfn(PCIDevice *dev)
+static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp)
 {
     VT686PMState *s = DO_UPCAST(VT686PMState, dev, dev);
     uint8_t *pci_conf;
@@ -361,8 +357,6 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_cnt_init(&s->ar, &s->io, 2);
-
-    return 0;
 }
 
 I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
@@ -391,7 +385,7 @@ static void via_pm_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = vt82c686b_pm_initfn;
+    k->realize = vt82c686b_pm_realize;
     k->config_write = pm_write_config;
     k->vendor_id = PCI_VENDOR_ID_VIA;
     k->device_id = PCI_DEVICE_ID_VIA_ACPI;
@@ -421,7 +415,7 @@ static const VMStateDescription vmstate_via = {
 };
 
 /* init the PCI-to-ISA bridge */
-static int vt82c686b_initfn(PCIDevice *d)
+static void vt82c686b_realize(PCIDevice *d, Error **errp)
 {
     VT82C686BState *vt82c = DO_UPCAST(VT82C686BState, dev, d);
     uint8_t *pci_conf;
@@ -451,8 +445,6 @@ static int vt82c686b_initfn(PCIDevice *d)
                                 &vt82c->superio);
 
     qemu_register_reset(vt82c686b_reset, d);
-
-    return 0;
 }
 
 ISABus *vt82c686b_init(PCIBus *bus, int devfn)
@@ -469,7 +461,7 @@ static void via_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = vt82c686b_initfn;
+    k->realize = vt82c686b_realize;
     k->config_write = vt82c686b_write_config;
     k->vendor_id = PCI_VENDOR_ID_VIA;
     k->device_id = PCI_DEVICE_ID_VIA_ISA_BRIDGE;
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index 6a56b07c6b..6bd61e7828 100644
--- a/hw/misc/applesmc.c
+++ b/hw/misc/applesmc.c
@@ -43,7 +43,6 @@
 /* command/status port used by Apple SMC */
 #define APPLESMC_CMD_PORT              0x4
 #define APPLESMC_NR_PORTS              32
-#define APPLESMC_MAX_DATA_LENGTH       32
 
 #define APPLESMC_READ_CMD              0x10
 #define APPLESMC_WRITE_CMD             0x11
@@ -249,8 +248,8 @@ static void applesmc_isa_realize(DeviceState *dev, Error **errp)
 }
 
 static Property applesmc_isa_properties[] = {
-    DEFINE_PROP_UINT32("iobase", AppleSMCState, iobase,
-                      APPLESMC_DEFAULT_IOBASE),
+    DEFINE_PROP_UINT32(APPLESMC_PROP_IO_BASE, AppleSMCState, iobase,
+                       APPLESMC_DEFAULT_IOBASE),
     DEFINE_PROP_STRING("osk", AppleSMCState, osk),
     DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c
index c78a63e3a7..26b9b86178 100644
--- a/hw/misc/pci-testdev.c
+++ b/hw/misc/pci-testdev.c
@@ -233,7 +233,7 @@ static const MemoryRegionOps pci_testdev_pio_ops = {
     },
 };
 
-static int pci_testdev_init(PCIDevice *pci_dev)
+static void pci_testdev_realize(PCIDevice *pci_dev, Error **errp)
 {
     PCITestDevState *d = PCI_TEST_DEV(pci_dev);
     uint8_t *pci_conf;
@@ -275,8 +275,6 @@ static int pci_testdev_init(PCIDevice *pci_dev)
         assert(r >= 0);
         test->hasnotifier = true;
     }
-
-    return 0;
 }
 
 static void
@@ -306,7 +304,7 @@ static void pci_testdev_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_testdev_init;
+    k->realize = pci_testdev_realize;
     k->exit = pci_testdev_uninit;
     k->vendor_id = PCI_VENDOR_ID_REDHAT;
     k->device_id = PCI_DEVICE_ID_REDHAT_TEST;
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index a207e21bcf..3405cb9ea0 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -1537,7 +1537,7 @@ static void e1000_write_config(PCIDevice *pci_dev, uint32_t address,
 }
 
 
-static int pci_e1000_init(PCIDevice *pci_dev)
+static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp)
 {
     DeviceState *dev = DEVICE(pci_dev);
     E1000State *d = E1000(pci_dev);
@@ -1581,8 +1581,6 @@ static int pci_e1000_init(PCIDevice *pci_dev)
 
     d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
     d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d);
-
-    return 0;
 }
 
 static void qdev_e1000_reset(DeviceState *dev)
@@ -1614,7 +1612,7 @@ static void e1000_class_init(ObjectClass *klass, void *data)
     E1000BaseClass *e = E1000_DEVICE_CLASS(klass);
     const E1000Info *info = data;
 
-    k->init = pci_e1000_init;
+    k->realize = pci_e1000_realize;
     k->exit = pci_e1000_uninit;
     k->romfile = "efi-e1000.rom";
     k->vendor_id = PCI_VENDOR_ID_INTEL;
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index 7a4f9f8a08..c374c1a251 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -1848,7 +1848,7 @@ static NetClientInfo net_eepro100_info = {
     .receive = nic_receive,
 };
 
-static int e100_nic_init(PCIDevice *pci_dev)
+static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
     E100PCIDeviceInfo *info = eepro100_get_class(s);
@@ -1892,8 +1892,6 @@ static int e100_nic_init(PCIDevice *pci_dev)
     memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100));
     s->vmstate->name = qemu_get_queue(s->nic)->model;
     vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
-
-    return 0;
 }
 
 static void eepro100_instance_init(Object *obj)
@@ -2083,7 +2081,7 @@ static void eepro100_class_init(ObjectClass *klass, void *data)
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->class_id = PCI_CLASS_NETWORK_ETHERNET;
     k->romfile = "pxe-eepro100.rom";
-    k->init = e100_nic_init;
+    k->realize = e100_nic_realize;
     k->exit = pci_nic_uninit;
     k->device_id = info->device_id;
     k->revision = info->revision;
diff --git a/hw/net/lance.c b/hw/net/lance.c
index ff7e789563..4baa0169e6 100644
--- a/hw/net/lance.c
+++ b/hw/net/lance.c
@@ -126,7 +126,8 @@ static int lance_init(SysBusDevice *sbd)
 
     s->phys_mem_read = ledma_memory_read;
     s->phys_mem_write = ledma_memory_write;
-    return pcnet_common_init(dev, s, &net_lance_info);
+    pcnet_common_init(dev, s, &net_lance_info);
+    return 0;
 }
 
 static void lance_reset(DeviceState *dev)
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
index 4dea70178d..3492db3663 100644
--- a/hw/net/ne2000.c
+++ b/hw/net/ne2000.c
@@ -709,7 +709,7 @@ static NetClientInfo net_ne2000_info = {
     .receive = ne2000_receive,
 };
 
-static int pci_ne2000_init(PCIDevice *pci_dev)
+static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp)
 {
     PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
     NE2000State *s;
@@ -729,8 +729,6 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
     s->nic = qemu_new_nic(&net_ne2000_info, &s->c,
                           object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s);
     qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
-
-    return 0;
 }
 
 static void pci_ne2000_exit(PCIDevice *pci_dev)
@@ -763,7 +761,7 @@ static void ne2000_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_ne2000_init;
+    k->realize = pci_ne2000_realize;
     k->exit = pci_ne2000_exit;
     k->romfile = "efi-ne2k_pci.rom",
     k->vendor_id = PCI_VENDOR_ID_REALTEK;
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
index 5df79f0a1f..8305d1bdf2 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -278,7 +278,7 @@ static NetClientInfo net_pci_pcnet_info = {
     .link_status_changed = pcnet_set_link_status,
 };
 
-static int pci_pcnet_init(PCIDevice *pci_dev)
+static void pci_pcnet_realize(PCIDevice *pci_dev, Error **errp)
 {
     PCIPCNetState *d = PCI_PCNET(pci_dev);
     PCNetState *s = &d->state;
@@ -316,7 +316,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
     s->phys_mem_write = pci_physical_memory_write;
     s->dma_opaque = pci_dev;
 
-    return pcnet_common_init(DEVICE(pci_dev), s, &net_pci_pcnet_info);
+    pcnet_common_init(DEVICE(pci_dev), s, &net_pci_pcnet_info);
 }
 
 static void pci_reset(DeviceState *dev)
@@ -346,7 +346,7 @@ static void pcnet_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_pcnet_init;
+    k->realize = pci_pcnet_realize;
     k->exit = pci_pcnet_uninit;
     k->romfile = "efi-pcnet.rom",
     k->vendor_id = PCI_VENDOR_ID_AMD;
diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
index 7778b9ad47..bdfd38f4ca 100644
--- a/hw/net/pcnet.c
+++ b/hw/net/pcnet.c
@@ -1712,7 +1712,7 @@ const VMStateDescription vmstate_pcnet = {
     }
 };
 
-int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
+void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
 {
     int i;
     uint16_t checksum;
@@ -1751,6 +1751,4 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
     *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
 
     s->lnkst = 0x40; /* initial link state: up */
-
-    return 0;
 }
diff --git a/hw/net/pcnet.h b/hw/net/pcnet.h
index 3f12fe3c13..79c4c84f07 100644
--- a/hw/net/pcnet.h
+++ b/hw/net/pcnet.h
@@ -63,6 +63,6 @@ uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
 int pcnet_can_receive(NetClientState *nc);
 ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_);
 void pcnet_set_link_status(NetClientState *nc);
-int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info);
+void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info);
 extern const VMStateDescription vmstate_pcnet;
 #endif
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 2d1be06f41..f868108dfe 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -3455,7 +3455,7 @@ static NetClientInfo net_rtl8139_info = {
     .link_status_changed = rtl8139_set_link_status,
 };
 
-static int pci_rtl8139_init(PCIDevice *dev)
+static void pci_rtl8139_realize(PCIDevice *dev, Error **errp)
 {
     RTL8139State *s = RTL8139(dev);
     DeviceState *d = DEVICE(dev);
@@ -3496,8 +3496,6 @@ static int pci_rtl8139_init(PCIDevice *dev)
     s->cplus_txbuffer_offset = 0;
 
     s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rtl8139_timer, s);
-
-    return 0;
 }
 
 static void rtl8139_instance_init(Object *obj)
@@ -3519,7 +3517,7 @@ static void rtl8139_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_rtl8139_init;
+    k->realize = pci_rtl8139_realize;
     k->exit = pci_rtl8139_uninit;
     k->romfile = "efi-rtl8139.rom";
     k->vendor_id = PCI_VENDOR_ID_REALTEK;
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 4e3a061622..2ea1ef1dd0 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -35,7 +35,7 @@
 
 #include <stdio.h>
 
-#include "hw/virtio/virtio_ring.h"
+#include "standard-headers/linux/virtio_ring.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/virtio-bus.h"
 
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 45da34ad61..1187ab813b 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -86,7 +86,7 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
 
     memcpy(&netcfg, config, n->config_size);
 
-    if (!(vdev->guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) &&
+    if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) &&
         memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
         memcpy(n->mac, netcfg.mac, ETH_ALEN);
         qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
@@ -305,7 +305,7 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
     info->multicast_table = str_list;
     info->vlan_table = get_vlan_table(n);
 
-    if (!((1 << VIRTIO_NET_F_CTRL_VLAN) & vdev->guest_features)) {
+    if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) {
         info->vlan = RX_STATE_ALL;
     } else if (!info->vlan_table) {
         info->vlan = RX_STATE_NONE;
@@ -446,23 +446,23 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
     VirtIONet *n = VIRTIO_NET(vdev);
     NetClientState *nc = qemu_get_queue(n->nic);
 
-    features |= (1 << VIRTIO_NET_F_MAC);
+    virtio_add_feature(&features, VIRTIO_NET_F_MAC);
 
     if (!peer_has_vnet_hdr(n)) {
-        features &= ~(0x1 << VIRTIO_NET_F_CSUM);
-        features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4);
-        features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6);
-        features &= ~(0x1 << VIRTIO_NET_F_HOST_ECN);
+        virtio_clear_feature(&features, VIRTIO_NET_F_CSUM);
+        virtio_clear_feature(&features, VIRTIO_NET_F_HOST_TSO4);
+        virtio_clear_feature(&features, VIRTIO_NET_F_HOST_TSO6);
+        virtio_clear_feature(&features, VIRTIO_NET_F_HOST_ECN);
 
-        features &= ~(0x1 << VIRTIO_NET_F_GUEST_CSUM);
-        features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO4);
-        features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO6);
-        features &= ~(0x1 << VIRTIO_NET_F_GUEST_ECN);
+        virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_CSUM);
+        virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO4);
+        virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO6);
+        virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_ECN);
     }
 
     if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
-        features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO);
-        features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
+        virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_UFO);
+        virtio_clear_feature(&features, VIRTIO_NET_F_HOST_UFO);
     }
 
     if (!get_vhost_net(nc->peer)) {
@@ -477,11 +477,11 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
 
     /* Linux kernel 2.6.25.  It understood MAC (as everyone must),
      * but also these: */
-    features |= (1 << VIRTIO_NET_F_MAC);
-    features |= (1 << VIRTIO_NET_F_CSUM);
-    features |= (1 << VIRTIO_NET_F_HOST_TSO4);
-    features |= (1 << VIRTIO_NET_F_HOST_TSO6);
-    features |= (1 << VIRTIO_NET_F_HOST_ECN);
+    virtio_add_feature(&features, VIRTIO_NET_F_MAC);
+    virtio_add_feature(&features, VIRTIO_NET_F_CSUM);
+    virtio_add_feature(&features, VIRTIO_NET_F_HOST_TSO4);
+    virtio_add_feature(&features, VIRTIO_NET_F_HOST_TSO6);
+    virtio_add_feature(&features, VIRTIO_NET_F_HOST_ECN);
 
     return features;
 }
@@ -519,9 +519,12 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
     VirtIONet *n = VIRTIO_NET(vdev);
     int i;
 
-    virtio_net_set_multiqueue(n, !!(features & (1 << VIRTIO_NET_F_MQ)));
+    virtio_net_set_multiqueue(n,
+                              __virtio_has_feature(features, VIRTIO_NET_F_MQ));
 
-    virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)));
+    virtio_net_set_mrg_rx_bufs(n,
+                               __virtio_has_feature(features,
+                                                    VIRTIO_NET_F_MRG_RXBUF));
 
     if (n->has_vnet_hdr) {
         n->curr_guest_offloads =
@@ -538,7 +541,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
         vhost_net_ack_features(get_vhost_net(nc->peer), features);
     }
 
-    if ((1 << VIRTIO_NET_F_CTRL_VLAN) & features) {
+    if (__virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) {
         memset(n->vlans, 0, MAX_VLAN >> 3);
     } else {
         memset(n->vlans, 0xff, MAX_VLAN >> 3);
@@ -585,7 +588,7 @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
     uint64_t offloads;
     size_t s;
 
-    if (!((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features)) {
+    if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
         return VIRTIO_NET_ERR;
     }
 
@@ -1378,7 +1381,7 @@ static void virtio_net_save_device(VirtIODevice *vdev, QEMUFile *f)
         }
     }
 
-    if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) {
+    if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
         qemu_put_be64(f, n->curr_guest_offloads);
     }
 }
@@ -1486,7 +1489,7 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
         }
     }
 
-    if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) {
+    if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
         n->curr_guest_offloads = qemu_get_be64(f);
     } else {
         n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
@@ -1513,8 +1516,8 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
         qemu_get_subqueue(n->nic, i)->link_down = link_down;
     }
 
-    if (vdev->guest_features & (0x1 << VIRTIO_NET_F_GUEST_ANNOUNCE) &&
-        vdev->guest_features & (0x1 << VIRTIO_NET_F_CTRL_VQ)) {
+    if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
+        virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
         n->announce_counter = SELF_ANNOUNCE_ROUNDS;
         timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
     }
@@ -1552,7 +1555,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
 void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
 {
     int i, config_size = 0;
-    host_features |= (1 << VIRTIO_NET_F_MAC);
+    virtio_add_feature(&host_features, VIRTIO_NET_F_MAC);
     for (i = 0; feature_sizes[i].flags != 0; i++) {
         if (host_features & feature_sizes[i].flags) {
             config_size = MAX(feature_sizes[i].end, config_size);
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index a83d2a11ff..dfb328debd 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2125,7 +2125,7 @@ static const MemoryRegionOps b1_ops = {
     },
 };
 
-static int vmxnet3_pci_init(PCIDevice *pci_dev)
+static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
 {
     DeviceState *dev = DEVICE(pci_dev);
     VMXNET3State *s = VMXNET3(pci_dev);
@@ -2164,8 +2164,6 @@ static int vmxnet3_pci_init(PCIDevice *pci_dev)
 
     register_savevm(dev, "vmxnet3-msix", -1, 1,
                     vmxnet3_msix_save, vmxnet3_msix_load, s);
-
-    return 0;
 }
 
 static void vmxnet3_instance_init(Object *obj)
@@ -2501,7 +2499,7 @@ static void vmxnet3_class_init(ObjectClass *class, void *data)
     DeviceClass *dc = DEVICE_CLASS(class);
     PCIDeviceClass *c = PCI_DEVICE_CLASS(class);
 
-    c->init = vmxnet3_pci_init;
+    c->realize = vmxnet3_pci_realize;
     c->exit = vmxnet3_pci_uninit;
     c->vendor_id = PCI_VENDOR_ID_VMWARE;
     c->device_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c
index a6ca940d55..28d0ff9c84 100644
--- a/hw/pci-bridge/dec.c
+++ b/hw/pci-bridge/dec.c
@@ -107,10 +107,9 @@ static int pci_dec_21154_device_init(SysBusDevice *dev)
     return 0;
 }
 
-static int dec_21154_pci_host_init(PCIDevice *d)
+static void dec_21154_pci_host_realize(PCIDevice *d, Error **errp)
 {
     /* PCI2PCI bridge same values as PearPC - check this */
-    return 0;
 }
 
 static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
@@ -118,7 +117,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = dec_21154_pci_host_init;
+    k->realize = dec_21154_pci_host_realize;
     k->vendor_id = PCI_VENDOR_ID_DEC;
     k->device_id = PCI_DEVICE_ID_DEC_21154;
     k->revision = 0x02;
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 832b6c7248..312fa703c6 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -792,14 +792,13 @@ static int pci_pbm_init_device(SysBusDevice *dev)
     return 0;
 }
 
-static int pbm_pci_host_init(PCIDevice *d)
+static void pbm_pci_host_realize(PCIDevice *d, Error **errp)
 {
     pci_set_word(d->config + PCI_COMMAND,
                  PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
     pci_set_word(d->config + PCI_STATUS,
                  PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
                  PCI_STATUS_DEVSEL_MEDIUM);
-    return 0;
 }
 
 static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
@@ -807,7 +806,7 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = pbm_pci_host_init;
+    k->realize = pbm_pci_host_realize;
     k->vendor_id = PCI_VENDOR_ID_SUN;
     k->device_id = PCI_DEVICE_ID_SUN_SABRE;
     k->class_id = PCI_CLASS_BRIDGE_HOST;
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 56292adb03..8bdd56922a 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -705,7 +705,7 @@ static int bonito_pcihost_initfn(SysBusDevice *dev)
     return 0;
 }
 
-static int bonito_initfn(PCIDevice *dev)
+static void bonito_realize(PCIDevice *dev, Error **errp)
 {
     PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev);
     SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost);
@@ -766,8 +766,6 @@ static int bonito_initfn(PCIDevice *dev)
     pci_set_byte(dev->config + PCI_MAX_LAT, 0x00);
 
     qemu_register_reset(bonito_reset, s);
-
-    return 0;
 }
 
 PCIBus *bonito_init(qemu_irq *pic)
@@ -799,7 +797,7 @@ static void bonito_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = bonito_initfn;
+    k->realize = bonito_realize;
     k->vendor_id = 0xdf53;
     k->device_id = 0x00d5;
     k->revision = 0x01;
diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c
index 6c7cfdbeb2..bfe707a1a1 100644
--- a/hw/pci-host/grackle.c
+++ b/hw/pci-host/grackle.c
@@ -114,10 +114,9 @@ static int pci_grackle_init_device(SysBusDevice *dev)
     return 0;
 }
 
-static int grackle_pci_host_init(PCIDevice *d)
+static void grackle_pci_host_realize(PCIDevice *d, Error **errp)
 {
     d->config[0x09] = 0x01;
-    return 0;
 }
 
 static void grackle_pci_class_init(ObjectClass *klass, void *data)
@@ -125,7 +124,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init      = grackle_pci_host_init;
+    k->realize   = grackle_pci_host_realize;
     k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
     k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106;
     k->revision  = 0x00;
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 8ea718e18e..723836fb0e 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -295,14 +295,13 @@ static void i440fx_pcihost_realize(DeviceState *dev, Error **errp)
     sysbus_init_ioports(sbd, 0xcfc, 4);
 }
 
-static int i440fx_initfn(PCIDevice *dev)
+static void i440fx_realize(PCIDevice *dev, Error **errp)
 {
     PCII440FXState *d = I440FX_PCI_DEVICE(dev);
 
     dev->config[I440FX_SMRAM] = 0x02;
 
     cpu_smm_register(&i440fx_set_smm, d);
-    return 0;
 }
 
 PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
@@ -631,7 +630,7 @@ static const MemoryRegionOps rcr_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN
 };
 
-static int piix3_initfn(PCIDevice *dev)
+static void piix3_realize(PCIDevice *dev, Error **errp)
 {
     PIIX3State *d = DO_UPCAST(PIIX3State, dev, dev);
 
@@ -644,7 +643,6 @@ static int piix3_initfn(PCIDevice *dev)
                                         &d->rcr_mem, 1);
 
     qemu_register_reset(piix3_reset, d);
-    return 0;
 }
 
 static void piix3_class_init(ObjectClass *klass, void *data)
@@ -655,7 +653,7 @@ static void piix3_class_init(ObjectClass *klass, void *data)
     dc->desc        = "ISA bridge";
     dc->vmsd        = &vmstate_piix3;
     dc->hotpluggable   = false;
-    k->init         = piix3_initfn;
+    k->realize      = piix3_realize;
     k->config_write = piix3_write_config;
     k->vendor_id    = PCI_VENDOR_ID_INTEL;
     /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
@@ -683,7 +681,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data)
     dc->desc        = "ISA bridge";
     dc->vmsd        = &vmstate_piix3;
     dc->hotpluggable   = false;
-    k->init         = piix3_initfn;
+    k->realize      = piix3_realize;
     k->config_write = piix3_write_config_xen;
     k->vendor_id    = PCI_VENDOR_ID_INTEL;
     /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
@@ -708,7 +706,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = i440fx_initfn;
+    k->realize = i440fx_realize;
     k->config_write = i440fx_write_config;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_82441;
diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
index 574f8b2efb..613ba73c64 100644
--- a/hw/pci-host/ppce500.c
+++ b/hw/pci-host/ppce500.c
@@ -416,7 +416,7 @@ static const VMStateDescription vmstate_ppce500_pci = {
 
 #include "exec/address-spaces.h"
 
-static int e500_pcihost_bridge_initfn(PCIDevice *d)
+static void e500_pcihost_bridge_realize(PCIDevice *d, Error **errp)
 {
     PPCE500PCIBridgeState *b = PPC_E500_PCI_BRIDGE(d);
     PPCE500CCSRState *ccsr = CCSR(container_get(qdev_get_machine(),
@@ -430,8 +430,6 @@ static int e500_pcihost_bridge_initfn(PCIDevice *d)
     memory_region_init_alias(&b->bar0, OBJECT(ccsr), "e500-pci-bar0", &ccsr->ccsr_space,
                              0, int128_get64(ccsr->ccsr_space.size));
     pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0);
-
-    return 0;
 }
 
 static AddressSpace *e500_pcihost_set_iommu(PCIBus *bus, void *opaque,
@@ -500,7 +498,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = e500_pcihost_bridge_initfn;
+    k->realize = e500_pcihost_bridge_realize;
     k->vendor_id = PCI_VENDOR_ID_FREESCALE;
     k->device_id = PCI_DEVICE_ID_MPC8533E;
     k->class_id = PCI_CLASS_PROCESSOR_POWERPC;
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 1de3681db9..6cea6ffebb 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -289,7 +289,7 @@ static void raven_pcihost_initfn(Object *obj)
     qdev_prop_set_bit(pci_dev, "multifunction", false);
 }
 
-static int raven_init(PCIDevice *d)
+static void raven_realize(PCIDevice *d, Error **errp)
 {
     RavenPCIState *s = RAVEN_PCI_DEVICE(d);
     char *filename;
@@ -330,8 +330,6 @@ static int raven_init(PCIDevice *d)
             g_free(filename);
         }
     }
-
-    return 0;
 }
 
 static const VMStateDescription vmstate_raven = {
@@ -349,7 +347,7 @@ static void raven_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = raven_init;
+    k->realize = raven_realize;
     k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
     k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN;
     k->revision = 0x00;
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index b20bad8373..df60e61d4f 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -390,7 +390,7 @@ static void mch_init_dmar(MCHPCIState *mch)
     pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu);
 }
 
-static int mch_init(PCIDevice *d)
+static void mch_realize(PCIDevice *d, Error **errp)
 {
     int i;
     MCHPCIState *mch = MCH_PCI_DEVICE(d);
@@ -418,7 +418,6 @@ static int mch_init(PCIDevice *d)
     if (qemu_opt_get_bool(qemu_get_machine_opts(), "iommu", false)) {
         mch_init_dmar(mch);
     }
-    return 0;
 }
 
 uint64_t mch_mcfg_base(void)
@@ -436,7 +435,7 @@ static void mch_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = mch_init;
+    k->realize = mch_realize;
     k->config_write = mch_write_config;
     dc->reset = mch_reset;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c
index 21f805f314..53f2b59ae8 100644
--- a/hw/pci-host/uninorth.c
+++ b/hw/pci-host/uninorth.c
@@ -315,37 +315,33 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
     return h->bus;
 }
 
-static int unin_main_pci_host_init(PCIDevice *d)
+static void unin_main_pci_host_realize(PCIDevice *d, Error **errp)
 {
     d->config[0x0C] = 0x08; // cache_line_size
     d->config[0x0D] = 0x10; // latency_timer
     d->config[0x34] = 0x00; // capabilities_pointer
-    return 0;
 }
 
-static int unin_agp_pci_host_init(PCIDevice *d)
+static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp)
 {
     d->config[0x0C] = 0x08; // cache_line_size
     d->config[0x0D] = 0x10; // latency_timer
     //    d->config[0x34] = 0x80; // capabilities_pointer
-    return 0;
 }
 
-static int u3_agp_pci_host_init(PCIDevice *d)
+static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp)
 {
     /* cache line size */
     d->config[0x0C] = 0x08;
     /* latency timer */
     d->config[0x0D] = 0x10;
-    return 0;
 }
 
-static int unin_internal_pci_host_init(PCIDevice *d)
+static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp)
 {
     d->config[0x0C] = 0x08; // cache_line_size
     d->config[0x0D] = 0x10; // latency_timer
     d->config[0x34] = 0x00; // capabilities_pointer
-    return 0;
 }
 
 static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
@@ -353,7 +349,7 @@ static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init      = unin_main_pci_host_init;
+    k->realize   = unin_main_pci_host_realize;
     k->vendor_id = PCI_VENDOR_ID_APPLE;
     k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI;
     k->revision  = 0x00;
@@ -377,7 +373,7 @@ static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init      = u3_agp_pci_host_init;
+    k->realize   = u3_agp_pci_host_realize;
     k->vendor_id = PCI_VENDOR_ID_APPLE;
     k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP;
     k->revision  = 0x00;
@@ -401,7 +397,7 @@ static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init      = unin_agp_pci_host_init;
+    k->realize   = unin_agp_pci_host_realize;
     k->vendor_id = PCI_VENDOR_ID_APPLE;
     k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP;
     k->revision  = 0x00;
@@ -425,7 +421,7 @@ static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init      = unin_internal_pci_host_init;
+    k->realize   = unin_internal_pci_host_realize;
     k->vendor_id = PCI_VENDOR_ID_APPLE;
     k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI;
     k->revision  = 0x00;
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index 71ff0de303..6d23553094 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -456,12 +456,11 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp)
     object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
 }
 
-static int versatile_pci_host_init(PCIDevice *d)
+static void versatile_pci_host_realize(PCIDevice *d, Error **errp)
 {
     pci_set_word(d->config + PCI_STATUS,
                  PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM);
     pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10);
-    return 0;
 }
 
 static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
@@ -469,7 +468,7 @@ static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = versatile_pci_host_init;
+    k->realize = versatile_pci_host_realize;
     k->vendor_id = PCI_VENDOR_ID_XILINX;
     k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30;
     k->class_id = PCI_CLASS_PROCESSOR_CO;
diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs
index 80f8aa69ac..9f905e6344 100644
--- a/hw/pci/Makefile.objs
+++ b/hw/pci/Makefile.objs
@@ -7,5 +7,3 @@ common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
 
 common-obj-$(call lnot,$(CONFIG_PCI)) += pci-stub.o
 common-obj-$(CONFIG_ALL) += pci-stub.o
-
-common-obj-$(CONFIG_PCI_HOTPLUG_OLD) += pci-hotplug-old.o
diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c
deleted file mode 100644
index 501a918b89..0000000000
--- a/hw/pci/pci-hotplug-old.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Deprecated PCI hotplug interface support
- * This covers the old pci_add / pci_del command, whereas the more general
- * device_add / device_del commands are now preferred.
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw/hw.h"
-#include "hw/boards.h"
-#include "hw/pci/pci.h"
-#include "net/net.h"
-#include "hw/i386/pc.h"
-#include "monitor/monitor.h"
-#include "hw/scsi/scsi.h"
-#include "hw/virtio/virtio-blk.h"
-#include "qemu/config-file.h"
-#include "sysemu/block-backend.h"
-#include "qapi/error.h"
-
-static int pci_read_devaddr(Monitor *mon, const char *addr,
-                            int *busp, unsigned *slotp)
-{
-    int dom;
-
-    /* strip legacy tag */
-    if (!strncmp(addr, "pci_addr=", 9)) {
-        addr += 9;
-    }
-    if (pci_parse_devaddr(addr, &dom, busp, slotp, NULL)) {
-        monitor_printf(mon, "Invalid pci address\n");
-        return -1;
-    }
-    if (dom != 0) {
-        monitor_printf(mon, "Multiple PCI domains not supported, use device_add\n");
-        return -1;
-    }
-    return 0;
-}
-
-static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
-                                       const char *devaddr,
-                                       const char *opts_str)
-{
-    Error *local_err = NULL;
-    QemuOpts *opts;
-    PCIBus *root = pci_find_primary_bus();
-    PCIBus *bus;
-    int ret, devfn;
-
-    if (!root) {
-        monitor_printf(mon, "no primary PCI bus (if there are multiple"
-                       " PCI roots, you must use device_add instead)");
-        return NULL;
-    }
-
-    bus = pci_get_bus_devfn(&devfn, root, devaddr);
-    if (!bus) {
-        monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
-        return NULL;
-    }
-    if (!qbus_is_hotpluggable(BUS(bus))) {
-        monitor_printf(mon, "PCI bus doesn't support hotplug\n");
-        return NULL;
-    }
-
-    opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0);
-    if (!opts) {
-        return NULL;
-    }
-
-    qemu_opt_set(opts, "type", "nic", &error_abort);
-
-    ret = net_client_init(opts, 0, &local_err);
-    if (local_err) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return NULL;
-    }
-    if (nd_table[ret].devaddr) {
-        monitor_printf(mon, "Parameter addr not supported\n");
-        return NULL;
-    }
-    return pci_nic_init(&nd_table[ret], root, "rtl8139", devaddr);
-}
-
-static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
-                        DriveInfo *dinfo, int printinfo)
-{
-    SCSIBus *scsibus;
-    SCSIDevice *scsidev;
-    Error *local_err = NULL;
-
-    scsibus = (SCSIBus *)
-        object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)),
-                            TYPE_SCSI_BUS);
-    if (!scsibus) {
-	error_report("Device is not a SCSI adapter");
-	return -1;
-    }
-
-    /*
-     * drive_init() tries to find a default for dinfo->unit.  Doesn't
-     * work at all for hotplug though as we assign the device to a
-     * specific bus instead of the first bus with spare scsi ids.
-     *
-     * Ditch the calculated value and reload from option string (if
-     * specified).
-     */
-    dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
-    dinfo->bus = scsibus->busnr;
-    scsidev = scsi_bus_legacy_add_drive(scsibus,
-                                        blk_by_legacy_dinfo(dinfo),
-                                        dinfo->unit, false, -1, NULL,
-                                        &local_err);
-    if (!scsidev) {
-        error_report_err(local_err);
-        return -1;
-    }
-    dinfo->unit = scsidev->id;
-
-    if (printinfo)
-        monitor_printf(mon, "OK bus %d, unit %d\n",
-                       scsibus->busnr, scsidev->id);
-    return 0;
-}
-
-int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
-{
-    int pci_bus;
-    unsigned slot;
-    PCIBus *root = pci_find_primary_bus();
-    PCIDevice *dev;
-    const char *pci_addr = qdict_get_str(qdict, "pci_addr");
-
-    switch (dinfo->type) {
-    case IF_SCSI:
-        if (!root) {
-            monitor_printf(mon, "no primary PCI bus (if there are multiple"
-                           " PCI roots, you must use device_add instead)");
-            goto err;
-        }
-        if (pci_read_devaddr(mon, pci_addr, &pci_bus, &slot)) {
-            goto err;
-        }
-        dev = pci_find_device(root, pci_bus, PCI_DEVFN(slot, 0));
-        if (!dev) {
-            monitor_printf(mon, "no pci device with address %s\n", pci_addr);
-            goto err;
-        }
-        if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) {
-            goto err;
-        }
-        break;
-    default:
-        monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
-        goto err;
-    }
-
-    return 0;
-err:
-    return -1;
-}
-
-static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
-                                           const char *devaddr,
-                                           const char *opts)
-{
-    PCIDevice *dev;
-    DriveInfo *dinfo = NULL;
-    int type = -1;
-    char buf[128];
-    PCIBus *root = pci_find_primary_bus();
-    PCIBus *bus;
-    int devfn;
-
-    if (get_param_value(buf, sizeof(buf), "if", opts)) {
-        if (!strcmp(buf, "scsi"))
-            type = IF_SCSI;
-        else if (!strcmp(buf, "virtio")) {
-            type = IF_VIRTIO;
-        } else {
-            monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", buf);
-            return NULL;
-        }
-    } else {
-        monitor_printf(mon, "no if= specified\n");
-        return NULL;
-    }
-
-    if (get_param_value(buf, sizeof(buf), "file", opts)) {
-        dinfo = add_init_drive(opts);
-        if (!dinfo)
-            return NULL;
-        if (dinfo->devaddr) {
-            monitor_printf(mon, "Parameter addr not supported\n");
-            return NULL;
-        }
-    } else {
-        dinfo = NULL;
-    }
-
-    if (!root) {
-        monitor_printf(mon, "no primary PCI bus (if there are multiple"
-                       " PCI roots, you must use device_add instead)");
-        return NULL;
-    }
-    bus = pci_get_bus_devfn(&devfn, root, devaddr);
-    if (!bus) {
-        monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
-        return NULL;
-    }
-    if (!qbus_is_hotpluggable(BUS(bus))) {
-        monitor_printf(mon, "PCI bus doesn't support hotplug\n");
-        return NULL;
-    }
-
-    switch (type) {
-    case IF_SCSI:
-        dev = pci_create(bus, devfn, "lsi53c895a");
-        if (qdev_init(&dev->qdev) < 0)
-            dev = NULL;
-        if (dev && dinfo) {
-            if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) {
-                qdev_unplug(&dev->qdev, NULL);
-                dev = NULL;
-            }
-        }
-        break;
-    case IF_VIRTIO:
-        if (!dinfo) {
-            monitor_printf(mon, "virtio requires a backing file/device.\n");
-            return NULL;
-        }
-        dev = pci_create(bus, devfn, "virtio-blk-pci");
-        if (qdev_prop_set_drive(&dev->qdev, "drive",
-                                blk_by_legacy_dinfo(dinfo)) < 0) {
-            object_unparent(OBJECT(dev));
-            dev = NULL;
-            break;
-        }
-        if (qdev_init(&dev->qdev) < 0)
-            dev = NULL;
-        break;
-    default:
-        dev = NULL;
-    }
-    return dev;
-}
-
-void hmp_pci_add(Monitor *mon, const QDict *qdict)
-{
-    PCIDevice *dev = NULL;
-    const char *pci_addr = qdict_get_str(qdict, "pci_addr");
-    const char *type = qdict_get_str(qdict, "type");
-    const char *opts = qdict_get_try_str(qdict, "opts");
-
-    /* strip legacy tag */
-    if (!strncmp(pci_addr, "pci_addr=", 9)) {
-        pci_addr += 9;
-    }
-
-    if (!opts) {
-        opts = "";
-    }
-
-    if (!strcmp(pci_addr, "auto"))
-        pci_addr = NULL;
-
-    if (strcmp(type, "nic") == 0) {
-        dev = qemu_pci_hot_add_nic(mon, pci_addr, opts);
-    } else if (strcmp(type, "storage") == 0) {
-        dev = qemu_pci_hot_add_storage(mon, pci_addr, opts);
-    } else {
-        monitor_printf(mon, "invalid type: %s\n", type);
-    }
-
-    if (dev) {
-        monitor_printf(mon, "OK root bus %s, bus %d, slot %d, function %d\n",
-                       pci_root_bus_path(dev),
-                       pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
-                       PCI_FUNC(dev->devfn));
-    } else
-        monitor_printf(mon, "failed to add %s\n", opts);
-}
-
-static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
-{
-    PCIBus *root = pci_find_primary_bus();
-    PCIDevice *d;
-    int bus;
-    unsigned slot;
-    Error *local_err = NULL;
-
-    if (!root) {
-        monitor_printf(mon, "no primary PCI bus (if there are multiple"
-                       " PCI roots, you must use device_del instead)");
-        return -1;
-    }
-
-    if (pci_read_devaddr(mon, pci_addr, &bus, &slot)) {
-        return -1;
-    }
-
-    d = pci_find_device(root, bus, PCI_DEVFN(slot, 0));
-    if (!d) {
-        monitor_printf(mon, "slot %d empty\n", slot);
-        return -1;
-    }
-
-    qdev_unplug(&d->qdev, &local_err);
-    if (local_err) {
-        monitor_printf(mon, "%s\n", error_get_pretty(local_err));
-        error_free(local_err);
-        return -1;
-    }
-
-    return 0;
-}
-
-void hmp_pci_del(Monitor *mon, const QDict *qdict)
-{
-    pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr"));
-}
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 31b222d8c0..cc5d946b8f 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -115,7 +115,7 @@ static const TypeInfo pcie_bus_info = {
 static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
 static void pci_update_mappings(PCIDevice *d);
 static void pci_irq_handler(void *opaque, int irq_num, int level);
-static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
+static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, Error **);
 static void pci_del_option_rom(PCIDevice *pdev);
 
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
@@ -539,8 +539,8 @@ static void pci_set_default_subsystem_id(PCIDevice *pci_dev)
  * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL
  *       [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
  */
-int pci_parse_devaddr(const char *addr, int *domp, int *busp,
-                      unsigned int *slotp, unsigned int *funcp)
+static int pci_parse_devaddr(const char *addr, int *domp, int *busp,
+                             unsigned int *slotp, unsigned int *funcp)
 {
     const char *p;
     char *e;
@@ -598,7 +598,8 @@ int pci_parse_devaddr(const char *addr, int *domp, int *busp,
     return 0;
 }
 
-PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr)
+static PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root,
+                                 const char *devaddr)
 {
     int dom, bus;
     unsigned slot;
@@ -726,7 +727,7 @@ static void pci_init_mask_bridge(PCIDevice *d)
                                PCI_PREF_RANGE_TYPE_MASK);
 }
 
-static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
+static void pci_init_multifunction(PCIBus *bus, PCIDevice *dev, Error **errp)
 {
     uint8_t slot = PCI_SLOT(dev->devfn);
     uint8_t func;
@@ -752,26 +753,25 @@ static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
         PCIDevice *f0 = bus->devices[PCI_DEVFN(slot, 0)];
         if (f0 && !(f0->cap_present & QEMU_PCI_CAP_MULTIFUNCTION)) {
             /* function 0 should set multifunction bit */
-            error_report("PCI: single function device can't be populated "
-                         "in function %x.%x", slot, PCI_FUNC(dev->devfn));
-            return -1;
+            error_setg(errp, "PCI: single function device can't be populated "
+                       "in function %x.%x", slot, PCI_FUNC(dev->devfn));
+            return;
         }
-        return 0;
+        return;
     }
 
     if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
-        return 0;
+        return;
     }
     /* function 0 indicates single function, so function > 0 must be NULL */
     for (func = 1; func < PCI_FUNC_MAX; ++func) {
         if (bus->devices[PCI_DEVFN(slot, func)]) {
-            error_report("PCI: %x.0 indicates single function, "
-                         "but %x.%x is already populated.",
-                         slot, slot, func);
-            return -1;
+            error_setg(errp, "PCI: %x.0 indicates single function, "
+                       "but %x.%x is already populated.",
+                       slot, slot, func);
+            return;
         }
     }
-    return 0;
 }
 
 static void pci_config_alloc(PCIDevice *pci_dev)
@@ -804,11 +804,13 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
 
 /* -1 for devfn means auto assign */
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
-                                         const char *name, int devfn)
+                                         const char *name, int devfn,
+                                         Error **errp)
 {
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
     PCIConfigReadFunc *config_read = pc->config_read;
     PCIConfigWriteFunc *config_write = pc->config_write;
+    Error *local_err = NULL;
     AddressSpace *dma_as;
 
     if (devfn < 0) {
@@ -817,12 +819,15 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
             if (!bus->devices[devfn])
                 goto found;
         }
-        error_report("PCI: no slot/function available for %s, all in use", name);
+        error_setg(errp, "PCI: no slot/function available for %s, all in use",
+                   name);
         return NULL;
     found: ;
     } else if (bus->devices[devfn]) {
-        error_report("PCI: slot %d function %d not available for %s, in use by %s",
-                     PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);
+        error_setg(errp, "PCI: slot %d function %d not available for %s,"
+                   " in use by %s",
+                   PCI_SLOT(devfn), PCI_FUNC(devfn), name,
+                   bus->devices[devfn]->name);
         return NULL;
     }
 
@@ -866,7 +871,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     if (pc->is_bridge) {
         pci_init_mask_bridge(pci_dev);
     }
-    if (pci_init_multifunction(bus, pci_dev)) {
+    pci_init_multifunction(bus, pci_dev, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
         do_pci_unregister_device(pci_dev);
         return NULL;
     }
@@ -897,7 +904,7 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
     pci_unregister_vga(pci_dev);
 }
 
-static int pci_unregister_device(DeviceState *dev)
+static void pci_qdev_unrealize(DeviceState *dev, Error **errp)
 {
     PCIDevice *pci_dev = PCI_DEVICE(dev);
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
@@ -910,7 +917,6 @@ static int pci_unregister_device(DeviceState *dev)
     }
 
     do_pci_unregister_device(pci_dev);
-    return 0;
 }
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
@@ -1605,10 +1611,9 @@ static const char * const pci_nic_names[] = {
 };
 
 /* Initialize a PCI NIC.  */
-/* FIXME callers should check for failure, but don't */
-PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus,
-                        const char *default_model,
-                        const char *default_devaddr)
+static PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus,
+                               const char *default_model,
+                               const char *default_devaddr)
 {
     const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
     PCIBus *bus;
@@ -1751,12 +1756,12 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
     return bus->devices[devfn];
 }
 
-static int pci_qdev_init(DeviceState *qdev)
+static void pci_qdev_realize(DeviceState *qdev, Error **errp)
 {
     PCIDevice *pci_dev = (PCIDevice *)qdev;
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
+    Error *local_err = NULL;
     PCIBus *bus;
-    int rc;
     bool is_default_rom;
 
     /* initialize cap_present for pci_is_express() and pci_config_size() */
@@ -1767,15 +1772,16 @@ static int pci_qdev_init(DeviceState *qdev)
     bus = PCI_BUS(qdev_get_parent_bus(qdev));
     pci_dev = do_pci_register_device(pci_dev, bus,
                                      object_get_typename(OBJECT(qdev)),
-                                     pci_dev->devfn);
+                                     pci_dev->devfn, errp);
     if (pci_dev == NULL)
-        return -1;
+        return;
 
-    if (pc->init) {
-        rc = pc->init(pci_dev);
-        if (rc != 0) {
+    if (pc->realize) {
+        pc->realize(pci_dev, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
             do_pci_unregister_device(pci_dev);
-            return rc;
+            return;
         }
     }
 
@@ -1786,13 +1792,24 @@ static int pci_qdev_init(DeviceState *qdev)
         is_default_rom = true;
     }
 
-    rc = pci_add_option_rom(pci_dev, is_default_rom);
-    if (rc != 0) {
-        pci_unregister_device(DEVICE(pci_dev));
-        return rc;
+    pci_add_option_rom(pci_dev, is_default_rom, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        pci_qdev_unrealize(DEVICE(pci_dev), NULL);
+        return;
     }
+}
 
-    return 0;
+static void pci_default_realize(PCIDevice *dev, Error **errp)
+{
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+
+    if (pc->init) {
+        if (pc->init(dev) < 0) {
+            error_setg(errp, "Device initialization failed");
+            return;
+        }
+    }
 }
 
 PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
@@ -1932,7 +1949,8 @@ static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size)
 }
 
 /* Add an option rom for the device */
-static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
+static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom,
+                               Error **errp)
 {
     int size;
     char *path;
@@ -1941,9 +1959,9 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
     const VMStateDescription *vmsd;
 
     if (!pdev->romfile)
-        return 0;
+        return;
     if (strlen(pdev->romfile) == 0)
-        return 0;
+        return;
 
     if (!pdev->rom_bar) {
         /*
@@ -1957,7 +1975,9 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
          * if the rom bar is disabled.
          */
         if (DEVICE(pdev)->hotplugged) {
-            return -1;
+            error_setg(errp, "Hot-plugged device without ROM bar"
+                       " can't have an option ROM");
+            return;
         }
 
         if (class == 0x0300) {
@@ -1965,7 +1985,7 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
         } else {
             rom_add_option(pdev->romfile, -1);
         }
-        return 0;
+        return;
     }
 
     path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile);
@@ -1975,15 +1995,13 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
 
     size = get_image_size(path);
     if (size < 0) {
-        error_report("%s: failed to find romfile \"%s\"",
-                     __func__, pdev->romfile);
+        error_setg(errp, "failed to find romfile \"%s\"", pdev->romfile);
         g_free(path);
-        return -1;
+        return;
     } else if (size == 0) {
-        error_report("%s: ignoring empty romfile \"%s\"",
-                     __func__, pdev->romfile);
+        error_setg(errp, "romfile \"%s\" is empty", pdev->romfile);
         g_free(path);
-        return -1;
+        return;
     }
     if (size & (size - 1)) {
         size = 1 << qemu_fls(size);
@@ -2009,8 +2027,6 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
     }
 
     pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom);
-
-    return 0;
 }
 
 static void pci_del_option_rom(PCIDevice *pdev)
@@ -2291,10 +2307,13 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev)
 static void pci_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
-    k->init = pci_qdev_init;
-    k->exit = pci_unregister_device;
+    PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
+
+    k->realize = pci_qdev_realize;
+    k->unrealize = pci_qdev_unrealize;
     k->bus_type = TYPE_PCI_BUS;
     k->props = pci_props;
+    pc->realize = pci_default_realize;
 }
 
 AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h
index ffd0df708b..92aa9d0499 100644
--- a/hw/s390x/s390-virtio-bus.h
+++ b/hw/s390x/s390-virtio-bus.h
@@ -19,6 +19,10 @@
 #ifndef HW_S390_VIRTIO_BUS_H
 #define HW_S390_VIRTIO_BUS_H 1
 
+#include <stddef.h>
+
+#include "standard-headers/asm-s390/kvm_virtio.h"
+#include "standard-headers/linux/virtio_ring.h"
 #include "hw/virtio/virtio-blk.h"
 #include "hw/virtio/virtio-net.h"
 #include "hw/virtio/virtio-rng.h"
@@ -29,28 +33,26 @@
 #include "hw/virtio/vhost-scsi.h"
 #endif
 
-#define VIRTIO_DEV_OFFS_TYPE		0	/* 8 bits */
-#define VIRTIO_DEV_OFFS_NUM_VQ		1	/* 8 bits */
-#define VIRTIO_DEV_OFFS_FEATURE_LEN	2	/* 8 bits */
-#define VIRTIO_DEV_OFFS_CONFIG_LEN	3	/* 8 bits */
-#define VIRTIO_DEV_OFFS_STATUS		4	/* 8 bits */
-#define VIRTIO_DEV_OFFS_CONFIG		5	/* dynamic */
+typedef struct kvm_device_desc KvmDeviceDesc;
+
+#define VIRTIO_DEV_OFFS_TYPE        offsetof(KvmDeviceDesc, type)
+#define VIRTIO_DEV_OFFS_NUM_VQ      offsetof(KvmDeviceDesc, num_vq)
+#define VIRTIO_DEV_OFFS_FEATURE_LEN offsetof(KvmDeviceDesc, feature_len)
+#define VIRTIO_DEV_OFFS_CONFIG_LEN  offsetof(KvmDeviceDesc, config_len)
+#define VIRTIO_DEV_OFFS_STATUS      offsetof(KvmDeviceDesc, status)
+#define VIRTIO_DEV_OFFS_CONFIG      offsetof(KvmDeviceDesc, config)
 
-#define VIRTIO_VQCONFIG_OFFS_TOKEN	0	/* 64 bits */
-#define VIRTIO_VQCONFIG_OFFS_ADDRESS	8	/* 64 bits */
-#define VIRTIO_VQCONFIG_OFFS_NUM	16	/* 16 bits */
-#define VIRTIO_VQCONFIG_LEN		24
+typedef struct kvm_vqconfig KvmVqConfig;
+#define VIRTIO_VQCONFIG_OFFS_TOKEN   offsetof(KvmVqConfig,token)    /* 64 bit */
+#define VIRTIO_VQCONFIG_OFFS_ADDRESS offsetof(KvmVqConfig, address) /* 64 bit */
+#define VIRTIO_VQCONFIG_OFFS_NUM     offsetof(KvmVqConfig, num)     /* 16 bit */
+#define VIRTIO_VQCONFIG_LEN          sizeof(KvmVqConfig)
 
 #define VIRTIO_RING_LEN			(TARGET_PAGE_SIZE * 3)
-#define VIRTIO_VRING_AVAIL_IDX_OFFS 2
-#define VIRTIO_VRING_USED_IDX_OFFS 2
+#define VIRTIO_VRING_AVAIL_IDX_OFFS offsetof(struct vring_avail, idx)
+#define VIRTIO_VRING_USED_IDX_OFFS  offsetof(struct vring_used, idx)
 #define S390_DEVICE_PAGES		512
 
-#define VIRTIO_PARAM_MASK               0xff
-#define VIRTIO_PARAM_VRING_INTERRUPT    0x0
-#define VIRTIO_PARAM_CONFIG_CHANGED     0x1
-#define VIRTIO_PARAM_DEV_ADD            0x2
-
 #define TYPE_VIRTIO_S390_DEVICE "virtio-s390-device"
 #define VIRTIO_S390_DEVICE(obj) \
      OBJECT_CHECK(VirtIOS390Device, (obj), TYPE_VIRTIO_S390_DEVICE)
diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h
index 75b67eda20..c847853957 100644
--- a/hw/s390x/s390-virtio.h
+++ b/hw/s390x/s390-virtio.h
@@ -13,11 +13,8 @@
 #define HW_S390_VIRTIO_H 1
 
 #include "hw/nmi.h"
-
-#define KVM_S390_VIRTIO_NOTIFY          0
-#define KVM_S390_VIRTIO_RESET           1
-#define KVM_S390_VIRTIO_SET_STATUS      2
-#define KVM_S390_VIRTIO_CCW_NOTIFY      3
+#include "standard-headers/asm-s390/kvm_virtio.h"
+#include "standard-headers/asm-s390/virtio-ccw.h"
 
 typedef int (*s390_virtio_fn)(const uint64_t *args);
 void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index ea236c9b01..ffbb9c2c89 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -400,8 +400,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                                        ccw.cda + sizeof(features.features));
             features.features = ldl_le_phys(&address_space_memory, ccw.cda);
             if (features.index < ARRAY_SIZE(dev->host_features)) {
-                virtio_bus_set_vdev_features(&dev->bus, features.features);
-                vdev->guest_features = features.features;
+                virtio_set_features(vdev, features.features);
             } else {
                 /*
                  * If the guest supports more feature bits, assert that it
@@ -744,8 +743,8 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
     dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus,
                                                          dev->host_features[0]);
 
-    dev->host_features[0] |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
-    dev->host_features[0] |= 0x1 << VIRTIO_F_BAD_FEATURE;
+    virtio_add_feature(&dev->host_features[0], VIRTIO_F_NOTIFY_ON_EMPTY);
+    virtio_add_feature(&dev->host_features[0], VIRTIO_F_BAD_FEATURE);
 
     css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
                           parent->hotplugged, 1);
@@ -899,9 +898,8 @@ static void balloon_ccw_stats_set_poll_interval(Object *obj, struct Visitor *v,
 static void virtio_ccw_balloon_instance_init(Object *obj)
 {
     VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj);
-    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON);
-    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
-    object_unref(OBJECT(&dev->vdev));
+    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
+                                TYPE_VIRTIO_BALLOON);
     object_property_add(obj, "guest-stats", "guest statistics",
                         balloon_ccw_stats_get_all, NULL, NULL, dev, NULL);
 
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 4db3b23ea3..cfb52e8fd9 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -13,6 +13,7 @@
  *
  */
 
+#include "standard-headers/linux/virtio_ids.h"
 #include "hw/virtio/virtio-scsi.h"
 #include "qemu/error-report.h"
 #include "qemu/iov.h"
@@ -144,7 +145,7 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
      *
      * TODO: always disable this workaround for virtio 1.0 devices.
      */
-    if ((vdev->guest_features & (1 << VIRTIO_F_ANY_LAYOUT)) == 0) {
+    if (!virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) {
         req_size = req->elem.out_sg[0].iov_len;
         resp_size = req->elem.in_sg[0].iov_len;
     }
@@ -744,7 +745,7 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
     VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
     VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-    if (((vdev->guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) &&
+    if (virtio_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) &&
         dev->type != TYPE_ROM) {
         virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
                                sense.asc | (sense.ascq << 8));
@@ -768,7 +769,7 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
         aio_context_release(s->ctx);
     }
 
-    if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
+    if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
         virtio_scsi_push_event(s, sd,
                                VIRTIO_SCSI_T_TRANSPORT_RESET,
                                VIRTIO_SCSI_EVT_RESET_RESCAN);
@@ -782,7 +783,7 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
     VirtIOSCSI *s = VIRTIO_SCSI(vdev);
     SCSIDevice *sd = SCSI_DEVICE(dev);
 
-    if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
+    if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
         virtio_scsi_push_event(s, sd,
                                VIRTIO_SCSI_T_TRANSPORT_RESET,
                                VIRTIO_SCSI_EVT_RESET_REMOVED);
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 10e5355de7..27b914aa94 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1220,7 +1220,7 @@ static Property sdhci_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static int sdhci_pci_init(PCIDevice *dev)
+static void sdhci_pci_realize(PCIDevice *dev, Error **errp)
 {
     SDHCIState *s = PCI_SDHCI(dev);
     dev->config[PCI_CLASS_PROG] = 0x01; /* Standard Host supported DMA */
@@ -1232,7 +1232,6 @@ static int sdhci_pci_init(PCIDevice *dev)
     memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
             SDHC_REGISTERS_MAP_SIZE);
     pci_register_bar(dev, 0, 0, &s->iomem);
-    return 0;
 }
 
 static void sdhci_pci_exit(PCIDevice *dev)
@@ -1246,7 +1245,7 @@ static void sdhci_pci_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = sdhci_pci_init;
+    k->realize = sdhci_pci_realize;
     k->exit = sdhci_pci_exit;
     k->vendor_id = PCI_VENDOR_ID_REDHAT;
     k->device_id = PCI_DEVICE_ID_REDHAT_SDHCI;
diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h
index 2f582caaee..2b35fe21ec 100644
--- a/hw/tpm/tpm_int.h
+++ b/hw/tpm/tpm_int.h
@@ -62,6 +62,7 @@ struct tpm_resp_hdr {
 
 #define TPM_FAIL                  9
 
+#define TPM_ORD_ContinueSelfTest  0x53
 #define TPM_ORD_GetTicks          0xf1
 
 #endif /* TPM_TPM_INT_H */
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index 2bf3c6fd61..a94c7c5a24 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -112,14 +112,31 @@ static void tpm_write_fatal_error_response(uint8_t *out, uint32_t out_len)
     }
 }
 
+static bool tpm_passthrough_is_selftest(const uint8_t *in, uint32_t in_len)
+{
+    struct tpm_req_hdr *hdr = (struct tpm_req_hdr *)in;
+
+    if (in_len >= sizeof(*hdr)) {
+        return (be32_to_cpu(hdr->ordinal) == TPM_ORD_ContinueSelfTest);
+    }
+
+    return false;
+}
+
 static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
                                         const uint8_t *in, uint32_t in_len,
-                                        uint8_t *out, uint32_t out_len)
+                                        uint8_t *out, uint32_t out_len,
+                                        bool *selftest_done)
 {
     int ret;
+    bool is_selftest;
+    const struct tpm_resp_hdr *hdr;
 
     tpm_pt->tpm_op_canceled = false;
     tpm_pt->tpm_executing = true;
+    *selftest_done = false;
+
+    is_selftest = tpm_passthrough_is_selftest(in, in_len);
 
     ret = tpm_passthrough_unix_write(tpm_pt->tpm_fd, in, in_len);
     if (ret != in_len) {
@@ -149,6 +166,11 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
                      "packet from TPM\n");
     }
 
+    if (is_selftest && (ret >= sizeof(struct tpm_resp_hdr))) {
+        hdr = (struct tpm_resp_hdr *)out;
+        *selftest_done = (be32_to_cpu(hdr->errcode) == 0);
+    }
+
 err_exit:
     if (ret < 0) {
         tpm_write_fatal_error_response(out, out_len);
@@ -160,13 +182,15 @@ err_exit:
 }
 
 static int tpm_passthrough_unix_transfer(TPMPassthruState *tpm_pt,
-                                         const TPMLocality *locty_data)
+                                         const TPMLocality *locty_data,
+                                         bool *selftest_done)
 {
     return tpm_passthrough_unix_tx_bufs(tpm_pt,
                                         locty_data->w_buffer.buffer,
                                         locty_data->w_offset,
                                         locty_data->r_buffer.buffer,
-                                        locty_data->r_buffer.size);
+                                        locty_data->r_buffer.size,
+                                        selftest_done);
 }
 
 static void tpm_passthrough_worker_thread(gpointer data,
@@ -175,16 +199,19 @@ static void tpm_passthrough_worker_thread(gpointer data,
     TPMPassthruThreadParams *thr_parms = user_data;
     TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(thr_parms->tb);
     TPMBackendCmd cmd = (TPMBackendCmd)data;
+    bool selftest_done = false;
 
     DPRINTF("tpm_passthrough: processing command type %d\n", cmd);
 
     switch (cmd) {
     case TPM_BACKEND_CMD_PROCESS_CMD:
         tpm_passthrough_unix_transfer(tpm_pt,
-                                      thr_parms->tpm_state->locty_data);
+                                      thr_parms->tpm_state->locty_data,
+                                      &selftest_done);
 
         thr_parms->recv_data_callback(thr_parms->tpm_state,
-                                      thr_parms->tpm_state->locty_number);
+                                      thr_parms->tpm_state->locty_number,
+                                      selftest_done);
         break;
     case TPM_BACKEND_CMD_INIT:
     case TPM_BACKEND_CMD_END:
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index c0e7cd738a..d0bb97f7d9 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -14,7 +14,7 @@
  *
  * Implementation of the TIS interface according to specs found at
  * http://www.trustedcomputinggroup.org. This implementation currently
- * supports version 1.21, revision 1.0.
+ * supports version 1.3, 21 March 2013
  * In the developers menu choose the PC Client section then find the TIS
  * specification.
  */
@@ -51,6 +51,8 @@
 #define TPM_TIS_REG_INTF_CAPABILITY       0x14
 #define TPM_TIS_REG_STS                   0x18
 #define TPM_TIS_REG_DATA_FIFO             0x24
+#define TPM_TIS_REG_DATA_XFIFO            0x80
+#define TPM_TIS_REG_DATA_XFIFO_END        0xbc
 #define TPM_TIS_REG_DID_VID               0xf00
 #define TPM_TIS_REG_RID                   0xf04
 
@@ -62,6 +64,7 @@
 #define TPM_TIS_STS_TPM_GO                (1 << 5)
 #define TPM_TIS_STS_DATA_AVAILABLE        (1 << 4)
 #define TPM_TIS_STS_EXPECT                (1 << 3)
+#define TPM_TIS_STS_SELFTEST_DONE         (1 << 2)
 #define TPM_TIS_STS_RESPONSE_RETRY        (1 << 1)
 
 #define TPM_TIS_BURST_COUNT_SHIFT         8
@@ -100,8 +103,15 @@
 
 #endif
 
+#define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28)
+#define TPM_TIS_CAP_DATA_TRANSFER_64B    (3 << 9)
+#define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9)
+#define TPM_TIS_CAP_BURST_COUNT_DYNAMIC  (0 << 8)
 #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL  (1 << 4) /* support is mandatory */
 #define TPM_TIS_CAPABILITIES_SUPPORTED   (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
+                                          TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
+                                          TPM_TIS_CAP_DATA_TRANSFER_64B | \
+                                          TPM_TIS_CAP_INTERFACE_VERSION1_3 | \
                                           TPM_TIS_INTERRUPTS_SUPPORTED)
 
 #define TPM_TIS_TPM_DID       0x0001
@@ -145,6 +155,24 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
 }
 
 /*
+ * Set the given flags in the STS register by clearing the register but
+ * preserving the SELFTEST_DONE flag and then setting the new flags.
+ *
+ * The SELFTEST_DONE flag is acquired from the backend that determines it by
+ * peeking into TPM commands.
+ *
+ * A VM suspend/resume will preserve the flag by storing it into the VM
+ * device state, but the backend will not remember it when QEMU is started
+ * again. Therefore, we cache the flag here. Once set, it will not be unset
+ * except by a reset.
+ */
+static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
+{
+    l->sts &= TPM_TIS_STS_SELFTEST_DONE;
+    l->sts |= flags;
+}
+
+/*
  * Send a request to the TPM.
  */
 static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
@@ -255,7 +283,8 @@ static void tpm_tis_abort(TPMState *s, uint8_t locty)
      */
     if (tis->aborting_locty == tis->next_locty) {
         tis->loc[tis->aborting_locty].state = TPM_TIS_STATE_READY;
-        tis->loc[tis->aborting_locty].sts = TPM_TIS_STS_COMMAND_READY;
+        tpm_tis_sts_set(&tis->loc[tis->aborting_locty],
+                        TPM_TIS_STS_COMMAND_READY);
         tpm_tis_raise_irq(s, tis->aborting_locty, TPM_TIS_INT_COMMAND_READY);
     }
 
@@ -300,7 +329,8 @@ static void tpm_tis_receive_bh(void *opaque)
     TPMTISEmuState *tis = &s->s.tis;
     uint8_t locty = s->locty_number;
 
-    tis->loc[locty].sts = TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE;
+    tpm_tis_sts_set(&tis->loc[locty],
+                    TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE);
     tis->loc[locty].state = TPM_TIS_STATE_COMPLETION;
     tis->loc[locty].r_offset = 0;
     tis->loc[locty].w_offset = 0;
@@ -320,12 +350,20 @@ static void tpm_tis_receive_bh(void *opaque)
 /*
  * Callback from the TPM to indicate that the response was received.
  */
-static void tpm_tis_receive_cb(TPMState *s, uint8_t locty)
+static void tpm_tis_receive_cb(TPMState *s, uint8_t locty,
+                               bool is_selftest_done)
 {
     TPMTISEmuState *tis = &s->s.tis;
+    uint8_t l;
 
     assert(s->locty_number == locty);
 
+    if (is_selftest_done) {
+        for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
+            tis->loc[locty].sts |= TPM_TIS_STS_SELFTEST_DONE;
+        }
+    }
+
     qemu_bh_schedule(tis->bh);
 }
 
@@ -344,7 +382,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)
         ret = tis->loc[locty].r_buffer.buffer[tis->loc[locty].r_offset++];
         if (tis->loc[locty].r_offset >= len) {
             /* got last byte */
-            tis->loc[locty].sts = TPM_TIS_STS_VALID;
+            tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_VALID);
 #ifdef RAISE_STS_IRQ
             tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
 #endif
@@ -427,6 +465,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
     uint32_t val = 0xffffffff;
     uint8_t locty = tpm_tis_locality_from_addr(addr);
     uint32_t avail;
+    uint8_t v;
 
     if (tpm_backend_had_startup_error(s->be_driver)) {
         return val;
@@ -475,15 +514,28 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
         }
         break;
     case TPM_TIS_REG_DATA_FIFO:
+    case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END:
         if (tis->active_locty == locty) {
-            switch (tis->loc[locty].state) {
-            case TPM_TIS_STATE_COMPLETION:
-                val = tpm_tis_data_read(s, locty);
-                break;
-            default:
-                val = TPM_TIS_NO_DATA_BYTE;
-                break;
+            if (size > 4 - (addr & 0x3)) {
+                /* prevent access beyond FIFO */
+                size = 4 - (addr & 0x3);
             }
+            val = 0;
+            shift = 0;
+            while (size > 0) {
+                switch (tis->loc[locty].state) {
+                case TPM_TIS_STATE_COMPLETION:
+                    v = tpm_tis_data_read(s, locty);
+                    break;
+                default:
+                    v = TPM_TIS_NO_DATA_BYTE;
+                    break;
+                }
+                val |= (v << shift);
+                shift += 8;
+                size--;
+            }
+            shift = 0; /* no more adjustments */
         }
         break;
     case TPM_TIS_REG_DID_VID:
@@ -518,11 +570,13 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
 {
     TPMState *s = opaque;
     TPMTISEmuState *tis = &s->s.tis;
-    uint16_t off = addr & 0xfff;
+    uint16_t off = addr & 0xffc;
+    uint8_t shift = (addr & 0x3) * 8;
     uint8_t locty = tpm_tis_locality_from_addr(addr);
     uint8_t active_locty, l;
     int c, set_new_locty = 1;
     uint16_t len;
+    uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0);
 
     DPRINTF("tpm_tis: write.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val);
 
@@ -535,6 +589,15 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
         return;
     }
 
+    val &= mask;
+
+    if (shift) {
+        val <<= shift;
+        mask <<= shift;
+    }
+
+    mask ^= 0xffffffff;
+
     switch (off) {
     case TPM_TIS_REG_ACCESS:
 
@@ -646,9 +709,10 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
             break;
         }
 
-        tis->loc[locty].inte = (val & (TPM_TIS_INT_ENABLED |
-                                       TPM_TIS_INT_POLARITY_MASK |
-                                       TPM_TIS_INTERRUPTS_SUPPORTED));
+        tis->loc[locty].inte &= mask;
+        tis->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED |
+                                        TPM_TIS_INT_POLARITY_MASK |
+                                        TPM_TIS_INTERRUPTS_SUPPORTED));
         break;
     case TPM_TIS_REG_INT_VECTOR:
         /* hard wired -- ignore */
@@ -686,7 +750,7 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
             break;
 
             case TPM_TIS_STATE_IDLE:
-                tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY;
+                tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_COMMAND_READY);
                 tis->loc[locty].state = TPM_TIS_STATE_READY;
                 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
             break;
@@ -705,7 +769,8 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
                 /* shortcut to ready state with C/R set */
                 tis->loc[locty].state = TPM_TIS_STATE_READY;
                 if (!(tis->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) {
-                    tis->loc[locty].sts   = TPM_TIS_STS_COMMAND_READY;
+                    tpm_tis_sts_set(&tis->loc[locty],
+                                    TPM_TIS_STS_COMMAND_READY);
                     tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
                 }
                 tis->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE);
@@ -727,8 +792,9 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
             switch (tis->loc[locty].state) {
             case TPM_TIS_STATE_COMPLETION:
                 tis->loc[locty].r_offset = 0;
-                tis->loc[locty].sts = TPM_TIS_STS_VALID |
-                                      TPM_TIS_STS_DATA_AVAILABLE;
+                tpm_tis_sts_set(&tis->loc[locty],
+                                TPM_TIS_STS_VALID|
+                                TPM_TIS_STS_DATA_AVAILABLE);
                 break;
             default:
                 /* ignore */
@@ -737,6 +803,7 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
         }
         break;
     case TPM_TIS_REG_DATA_FIFO:
+    case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END:
         /* data fifo */
         if (tis->active_locty != locty) {
             break;
@@ -747,18 +814,28 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
             tis->loc[locty].state == TPM_TIS_STATE_COMPLETION) {
             /* drop the byte */
         } else {
-            DPRINTF("tpm_tis: Byte to send to TPM: %02x\n", (uint8_t)val);
+            DPRINTF("tpm_tis: Data to send to TPM: %08x (size=%d)\n",
+                    val, size);
             if (tis->loc[locty].state == TPM_TIS_STATE_READY) {
                 tis->loc[locty].state = TPM_TIS_STATE_RECEPTION;
-                tis->loc[locty].sts = TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID;
+                tpm_tis_sts_set(&tis->loc[locty],
+                                TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
+            }
+
+            val >>= shift;
+            if (size > 4 - (addr & 0x3)) {
+                /* prevent access beyond FIFO */
+                size = 4 - (addr & 0x3);
             }
 
-            if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) {
+            while ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) {
                 if (tis->loc[locty].w_offset < tis->loc[locty].w_buffer.size) {
                     tis->loc[locty].w_buffer.
                         buffer[tis->loc[locty].w_offset++] = (uint8_t)val;
+                    val >>= 8;
+                    size--;
                 } else {
-                    tis->loc[locty].sts = TPM_TIS_STS_VALID;
+                    tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_VALID);
                 }
             }
 
@@ -771,11 +848,11 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
 #endif
                 len = tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer);
                 if (len > tis->loc[locty].w_offset) {
-                    tis->loc[locty].sts = TPM_TIS_STS_EXPECT |
-                                          TPM_TIS_STS_VALID;
+                    tpm_tis_sts_set(&tis->loc[locty],
+                                    TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
                 } else {
                     /* packet complete */
-                    tis->loc[locty].sts = TPM_TIS_STS_VALID;
+                    tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_VALID);
                 }
 #ifdef RAISE_STS_IRQ
                 if (needIrq) {
diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h
index 1a0db23367..db78d51e4f 100644
--- a/hw/tpm/tpm_tis.h
+++ b/hw/tpm/tpm_tis.h
@@ -41,7 +41,7 @@ typedef enum {
 typedef struct TPMLocality {
     TPMTISState state;
     uint8_t access;
-    uint8_t sts;
+    uint32_t sts;
     uint32_t inte;
     uint32_t ints;
 
diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index 490f2b6af9..4c80707f85 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -26,7 +26,7 @@ typedef struct EHCIPCIInfo {
     bool companion;
 } EHCIPCIInfo;
 
-static int usb_ehci_pci_initfn(PCIDevice *dev)
+static void usb_ehci_pci_realize(PCIDevice *dev, Error **errp)
 {
     EHCIPCIState *i = PCI_EHCI(dev);
     EHCIState *s = &i->ehci;
@@ -66,8 +66,6 @@ static int usb_ehci_pci_initfn(PCIDevice *dev)
 
     usb_ehci_realize(s, DEVICE(dev), NULL);
     pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
-
-    return 0;
 }
 
 static void usb_ehci_pci_init(Object *obj)
@@ -139,7 +137,7 @@ static void ehci_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = usb_ehci_pci_initfn;
+    k->realize = usb_ehci_pci_realize;
     k->exit = usb_ehci_pci_exit;
     k->class_id = PCI_CLASS_SERIAL_USB;
     k->config_write = usb_ehci_pci_write_config;
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 828c2a7d78..ba15ae0019 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3576,7 +3576,7 @@ static void usb_xhci_init(XHCIState *xhci)
     }
 }
 
-static int usb_xhci_initfn(struct PCIDevice *dev)
+static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
 {
     int i, ret;
 
@@ -3655,8 +3655,6 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
                   &xhci->mem, 0, OFF_MSIX_PBA,
                   0x90);
     }
-
-    return 0;
 }
 
 static void usb_xhci_exit(PCIDevice *dev)
@@ -3896,7 +3894,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
     dc->props   = xhci_properties;
     dc->reset   = xhci_reset;
     set_bit(DEVICE_CATEGORY_USB, dc->categories);
-    k->init         = usb_xhci_initfn;
+    k->realize      = usb_xhci_realize;
     k->exit         = usb_xhci_exit;
     k->vendor_id    = PCI_VENDOR_ID_NEC;
     k->device_id    = PCI_DEVICE_ID_NEC_UPD720200;
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 0936f659e5..5c7b8c20fa 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -105,7 +105,7 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
 /* Disable guest->host notifies */
 void vring_disable_notification(VirtIODevice *vdev, Vring *vring)
 {
-    if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
+    if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
         vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
     }
 }
@@ -116,7 +116,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring)
  */
 bool vring_enable_notification(VirtIODevice *vdev, Vring *vring)
 {
-    if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
+    if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
         vring_avail_event(&vring->vr) = vring->vr.avail->idx;
     } else {
         vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
@@ -135,12 +135,12 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring)
      * interrupts. */
     smp_mb();
 
-    if ((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) &&
+    if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
         unlikely(!vring_more_avail(vdev, vring))) {
         return true;
     }
 
-    if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
+    if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
         return !(vring_get_avail_flags(vdev, vring) &
                  VRING_AVAIL_F_NO_INTERRUPT);
     }
@@ -401,7 +401,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
 
     /* On success, increment avail index. */
     vring->last_avail_idx++;
-    if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
+    if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
         vring_avail_event(&vring->vr) = vring->last_avail_idx;
     }
 
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 8a48d2a178..95b0643448 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -70,7 +70,7 @@ static inline void reset_stats(VirtIOBalloon *dev)
 static bool balloon_stats_supported(const VirtIOBalloon *s)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(s);
-    return vdev->guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ);
+    return virtio_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ);
 }
 
 static bool balloon_stats_enabled(const VirtIOBalloon *s)
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index dfd2d8c772..be886e75af 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -109,20 +109,6 @@ uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
     return k->get_features(vdev, requested_features);
 }
 
-/* Set the features of the plugged device. */
-void virtio_bus_set_vdev_features(VirtioBusState *bus,
-                                      uint32_t requested_features)
-{
-    VirtIODevice *vdev = virtio_bus_get_device(bus);
-    VirtioDeviceClass *k;
-
-    assert(vdev != NULL);
-    k = VIRTIO_DEVICE_GET_CLASS(vdev);
-    if (k->set_features != NULL) {
-        k->set_features(vdev, requested_features);
-    }
-}
-
 /* Get bad features of the plugged device. */
 uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
 {
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 2450c13747..10123f34b2 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -349,7 +349,7 @@ static void virtio_mmio_device_plugged(DeviceState *opaque)
 {
     VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 
-    proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+    virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);
     proxy->host_features = virtio_bus_get_vdev_features(&proxy->bus,
                                                         proxy->host_features);
 }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 604cb5b749..e7baf7b5e8 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -17,6 +17,7 @@
 
 #include <inttypes.h>
 
+#include "standard-headers/linux/virtio_pci.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-blk.h"
 #include "hw/virtio/virtio-net.h"
@@ -35,56 +36,11 @@
 #include "hw/virtio/virtio-bus.h"
 #include "qapi/visitor.h"
 
-/* from Linux's linux/virtio_pci.h */
-
-/* A 32-bit r/o bitmask of the features supported by the host */
-#define VIRTIO_PCI_HOST_FEATURES        0
-
-/* A 32-bit r/w bitmask of features activated by the guest */
-#define VIRTIO_PCI_GUEST_FEATURES       4
-
-/* A 32-bit r/w PFN for the currently selected queue */
-#define VIRTIO_PCI_QUEUE_PFN            8
-
-/* A 16-bit r/o queue size for the currently selected queue */
-#define VIRTIO_PCI_QUEUE_NUM            12
-
-/* A 16-bit r/w queue selector */
-#define VIRTIO_PCI_QUEUE_SEL            14
-
-/* A 16-bit r/w queue notifier */
-#define VIRTIO_PCI_QUEUE_NOTIFY         16
-
-/* An 8-bit device status register.  */
-#define VIRTIO_PCI_STATUS               18
-
-/* An 8-bit r/o interrupt status register.  Reading the value will return the
- * current contents of the ISR and will also clear it.  This is effectively
- * a read-and-acknowledge. */
-#define VIRTIO_PCI_ISR                  19
-
-/* MSI-X registers: only enabled if MSI-X is enabled. */
-/* A 16-bit vector for configuration changes. */
-#define VIRTIO_MSI_CONFIG_VECTOR        20
-/* A 16-bit vector for selected queue notifications. */
-#define VIRTIO_MSI_QUEUE_VECTOR         22
-
-/* Config space size */
-#define VIRTIO_PCI_CONFIG_NOMSI         20
-#define VIRTIO_PCI_CONFIG_MSI           24
-#define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
-                                         VIRTIO_PCI_CONFIG_MSI : \
-                                         VIRTIO_PCI_CONFIG_NOMSI)
+#define VIRTIO_PCI_REGION_SIZE(dev)     VIRTIO_PCI_CONFIG_OFF(msix_present(dev))
 
 /* The remaining space is defined by each driver as the per-driver
  * configuration space */
-#define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
-                                         VIRTIO_PCI_CONFIG_MSI : \
-                                         VIRTIO_PCI_CONFIG_NOMSI)
-
-/* How many bits to shift physical queue address written to QUEUE_PFN.
- * 12 is historical, and due to x86 page size. */
-#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
+#define VIRTIO_PCI_CONFIG_SIZE(dev)     VIRTIO_PCI_CONFIG_OFF(msix_enabled(dev))
 
 static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
                                VirtIOPCIProxy *dev);
@@ -392,7 +348,7 @@ static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr,
 {
     VirtIOPCIProxy *proxy = opaque;
     VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
-    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
+    uint32_t config = VIRTIO_PCI_CONFIG_SIZE(&proxy->pci_dev);
     uint64_t val = 0;
     if (addr < config) {
         return virtio_ioport_read(proxy, addr);
@@ -423,7 +379,7 @@ static void virtio_pci_config_write(void *opaque, hwaddr addr,
                                     uint64_t val, unsigned size)
 {
     VirtIOPCIProxy *proxy = opaque;
-    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
+    uint32_t config = VIRTIO_PCI_CONFIG_SIZE(&proxy->pci_dev);
     VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
     if (addr < config) {
         virtio_ioport_write(proxy, addr, val);
@@ -996,8 +952,8 @@ static void virtio_pci_device_plugged(DeviceState *d)
         proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
     }
 
-    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
-    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
+    virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);
+    virtio_add_feature(&proxy->host_features, VIRTIO_F_BAD_FEATURE);
     proxy->host_features = virtio_bus_get_vdev_features(bus,
                                                       proxy->host_features);
 }
@@ -1318,9 +1274,8 @@ static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data)
 static void virtio_balloon_pci_instance_init(Object *obj)
 {
     VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
-    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON);
-    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
-    object_unref(OBJECT(&dev->vdev));
+    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
+                                TYPE_VIRTIO_BALLOON);
     object_property_add(obj, "guest-stats", "guest statistics",
                         balloon_pci_stats_get_all, NULL, NULL, dev,
                         NULL);
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index d735343ca8..3c6e430048 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -155,7 +155,7 @@ static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
     return virtio_lduw_phys(vq->vdev, pa);
 }
 
-static inline uint16_t vring_used_event(VirtQueue *vq)
+static inline uint16_t vring_get_used_event(VirtQueue *vq)
 {
     return vring_avail_ring(vq, vq->vring.num);
 }
@@ -204,7 +204,7 @@ static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask)
     virtio_stw_phys(vdev, pa, virtio_lduw_phys(vdev, pa) & ~mask);
 }
 
-static inline void vring_avail_event(VirtQueue *vq, uint16_t val)
+static inline void vring_set_avail_event(VirtQueue *vq, uint16_t val)
 {
     hwaddr pa;
     if (!vq->notification) {
@@ -217,8 +217,8 @@ static inline void vring_avail_event(VirtQueue *vq, uint16_t val)
 void virtio_queue_set_notification(VirtQueue *vq, int enable)
 {
     vq->notification = enable;
-    if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
-        vring_avail_event(vq, vring_avail_idx(vq));
+    if (virtio_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
+        vring_set_avail_event(vq, vring_avail_idx(vq));
     } else if (enable) {
         vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
     } else {
@@ -468,8 +468,8 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
     max = vq->vring.num;
 
     i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
-    if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
-        vring_avail_event(vq, vq->last_avail_idx);
+    if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
+        vring_set_avail_event(vq, vq->last_avail_idx);
     }
 
     if (vring_desc_flags(vdev, desc_pa, i) & VRING_DESC_F_INDIRECT) {
@@ -819,19 +819,6 @@ void virtio_irq(VirtQueue *vq)
     virtio_notify_vector(vq->vdev, vq->vector);
 }
 
-/* Assuming a given event_idx value from the other size, if
- * we have just incremented index from old to new_idx,
- * should we trigger an event? */
-static inline int vring_need_event(uint16_t event, uint16_t new, uint16_t old)
-{
-	/* Note: Xen has similar logic for notification hold-off
-	 * in include/xen/interface/io/ring.h with req_event and req_prod
-	 * corresponding to event_idx + 1 and new respectively.
-	 * Note also that req_event and req_prod in Xen start at 1,
-	 * event indexes in virtio start at 0. */
-	return (uint16_t)(new - event - 1) < (uint16_t)(new - old);
-}
-
 static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
 {
     uint16_t old, new;
@@ -839,12 +826,12 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
     /* We need to expose used array entries before checking used event. */
     smp_mb();
     /* Always notify when queue is empty (when feature acknowledge) */
-    if (((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) &&
-         !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx)) {
+    if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
+        !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx) {
         return true;
     }
 
-    if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
+    if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
         return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT);
     }
 
@@ -852,7 +839,7 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
     vq->signalled_used_valid = true;
     old = vq->signalled_used;
     new = vq->signalled_used = vring_used_idx(vq);
-    return !v || vring_need_event(vring_used_event(vq), new, old);
+    return !v || vring_need_event(vring_get_used_event(vq), new, old);
 }
 
 void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
index 33dd6d43c0..b2d158f7ba 100644
--- a/hw/watchdog/wdt_i6300esb.c
+++ b/hw/watchdog/wdt_i6300esb.c
@@ -408,7 +408,7 @@ static const VMStateDescription vmstate_i6300esb = {
     }
 };
 
-static int i6300esb_init(PCIDevice *dev)
+static void i6300esb_realize(PCIDevice *dev, Error **errp)
 {
     I6300State *d = DO_UPCAST(I6300State, dev, dev);
 
@@ -421,8 +421,6 @@ static int i6300esb_init(PCIDevice *dev)
                           "i6300esb", 0x10);
     pci_register_bar(&d->dev, 0, 0, &d->io_mem);
     /* qemu_register_coalesced_mmio (addr, 0x10); ? */
-
-    return 0;
 }
 
 static WatchdogTimerModel model = {
@@ -437,7 +435,7 @@ static void i6300esb_class_init(ObjectClass *klass, void *data)
 
     k->config_read = i6300esb_config_read;
     k->config_write = i6300esb_config_write;
-    k->init = i6300esb_init;
+    k->realize = i6300esb_realize;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = PCI_DEVICE_ID_INTEL_ESB_9;
     k->class_id = PCI_CLASS_SYSTEM_OTHER;
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
new file mode 100644
index 0000000000..17d3beb5a3
--- /dev/null
+++ b/include/hw/acpi/aml-build.h
@@ -0,0 +1,191 @@
+#ifndef HW_ACPI_GEN_UTILS_H
+#define HW_ACPI_GEN_UTILS_H
+
+#include <stdint.h>
+#include <glib.h>
+#include "qemu/compiler.h"
+
+typedef enum {
+    AML_NO_OPCODE = 0,/* has only data */
+    AML_OPCODE,       /* has opcode optionally followed by data */
+    AML_PACKAGE,      /* has opcode and uses PkgLength for its length */
+    AML_EXT_PACKAGE,  /* Same as AML_PACKAGE but also has 'ExOpPrefix' */
+    AML_BUFFER,       /* data encoded as 'DefBuffer' */
+    AML_RES_TEMPLATE, /* encoded as ResourceTemplate macro */
+} AmlBlockFlags;
+
+struct Aml {
+    GArray *buf;
+
+    /*< private >*/
+    uint8_t op;
+    AmlBlockFlags block_flags;
+};
+typedef struct Aml Aml;
+
+typedef enum {
+    aml_decode10 = 0,
+    aml_decode16 = 1,
+} AmlIODecode;
+
+typedef enum {
+    aml_any_acc = 0,
+    aml_byte_acc = 1,
+    aml_word_acc = 2,
+    aml_dword_acc = 3,
+    aml_qword_acc = 4,
+    aml_buffer_acc = 5,
+} AmlFieldFlags;
+
+typedef enum {
+    aml_system_memory = 0x00,
+    aml_system_io = 0x01,
+} AmlRegionSpace;
+
+typedef enum {
+    aml_memory_range = 0,
+    aml_io_range = 1,
+    aml_bus_number_range = 2,
+} AmlResourceType;
+
+typedef enum {
+    aml_sub_decode = 1 << 1,
+    aml_pos_decode = 0
+} AmlDecode;
+
+typedef enum {
+    aml_max_fixed = 1 << 3,
+    aml_max_not_fixed = 0,
+} AmlMaxFixed;
+
+typedef enum {
+    aml_min_fixed = 1 << 2,
+    aml_min_not_fixed = 0
+} AmlMinFixed;
+
+/*
+ * ACPI 1.0b: Table 6-26 I/O Resource Flag (Resource Type = 1) Definitions
+ * _RNG field definition
+ */
+typedef enum {
+    aml_isa_only = 1,
+    aml_non_isa_only = 2,
+    aml_entire_range = 3,
+} AmlISARanges;
+
+/*
+ * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions
+ * _MEM field definition
+ */
+typedef enum {
+    aml_non_cacheable = 0,
+    aml_cacheable = 1,
+    aml_write_combining = 2,
+    aml_prefetchable = 3,
+} AmlCacheble;
+
+/*
+ * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions
+ * _RW field definition
+ */
+typedef enum {
+    aml_ReadOnly = 0,
+    aml_ReadWrite = 1,
+} AmlReadAndWrite;
+
+/**
+ * init_aml_allocator:
+ *
+ * Called for initializing API allocator which allow to use
+ * AML API.
+ * Returns: toplevel container which accumulates all other
+ * AML elements for a table.
+ */
+Aml *init_aml_allocator(void);
+
+/**
+ * free_aml_allocator:
+ *
+ * Releases all elements used by AML API, frees associated memory
+ * and invalidates AML allocator. After this call @init_aml_allocator
+ * should be called again if AML API is to be used again.
+ */
+void free_aml_allocator(void);
+
+/**
+ * aml_append:
+ * @parent_ctx: context to which @child element is added
+ * @child: element that is copied into @parent_ctx context
+ *
+ * Joins Aml elements together and helps to construct AML tables
+ * Examle of usage:
+ *   Aml *table = aml_def_block("SSDT", ...);
+ *   Aml *sb = aml_scope("\_SB");
+ *   Aml *dev = aml_device("PCI0");
+ *
+ *   aml_append(dev, aml_name_decl("HID", aml_eisaid("PNP0A03")));
+ *   aml_append(sb, dev);
+ *   aml_append(table, sb);
+ */
+void aml_append(Aml *parent_ctx, Aml *child);
+
+/* non block AML object primitives */
+Aml *aml_name(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
+Aml *aml_name_decl(const char *name, Aml *val);
+Aml *aml_return(Aml *val);
+Aml *aml_int(const uint64_t val);
+Aml *aml_arg(int pos);
+Aml *aml_store(Aml *val, Aml *target);
+Aml *aml_and(Aml *arg1, Aml *arg2);
+Aml *aml_notify(Aml *arg1, Aml *arg2);
+Aml *aml_call1(const char *method, Aml *arg1);
+Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2);
+Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3);
+Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4);
+Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
+            uint8_t aln, uint8_t len);
+Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
+                          uint32_t offset, uint32_t len);
+Aml *aml_irq_no_flags(uint8_t irq);
+Aml *aml_named_field(const char *name, unsigned length);
+Aml *aml_reserved_field(unsigned length);
+Aml *aml_local(int num);
+Aml *aml_string(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
+Aml *aml_equal(Aml *arg1, Aml *arg2);
+Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len,
+                   const char *name_format, ...) GCC_FMT_ATTR(4, 5);
+Aml *aml_eisaid(const char *str);
+Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
+                         AmlDecode dec, uint16_t addr_gran,
+                         uint16_t addr_min, uint16_t addr_max,
+                         uint16_t addr_trans, uint16_t len);
+Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
+                 AmlDecode dec, AmlISARanges isa_ranges,
+                 uint16_t addr_gran, uint16_t addr_min,
+                 uint16_t addr_max, uint16_t addr_trans,
+                 uint16_t len);
+Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed,
+                      AmlMaxFixed max_fixed, AmlCacheble cacheable,
+                      AmlReadAndWrite read_and_write,
+                      uint32_t addr_gran, uint32_t addr_min,
+                      uint32_t addr_max, uint32_t addr_trans,
+                      uint32_t len);
+Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
+                      AmlMaxFixed max_fixed, AmlCacheble cacheable,
+                      AmlReadAndWrite read_and_write,
+                      uint64_t addr_gran, uint64_t addr_min,
+                      uint64_t addr_max, uint64_t addr_trans,
+                      uint64_t len);
+
+/* Block AML object primitives */
+Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
+Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
+Aml *aml_method(const char *name, int arg_count);
+Aml *aml_if(Aml *predicate);
+Aml *aml_package(uint8_t num_elements);
+Aml *aml_buffer(void);
+Aml *aml_resource_template(void);
+Aml *aml_field(const char *name, AmlFieldFlags flags);
+Aml *aml_varpackage(uint32_t num_elements);
+
+#endif
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 12d7a7af5f..c2d3dba0c7 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -63,6 +63,10 @@ extern const VMStateDescription vmstate_ich9_pm;
 void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp);
 
 void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp);
+void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
+                                      Error **errp);
+void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
+                              Error **errp);
 
 void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
 #endif /* HW_ACPI_ICH9_H */
diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h
index b9db29576c..efa6ed7b7b 100644
--- a/include/hw/acpi/pc-hotplug.h
+++ b/include/hw/acpi/pc-hotplug.h
@@ -28,6 +28,7 @@
 
 #define ICH9_CPU_HOTPLUG_IO_BASE 0x0CD8
 #define PIIX4_CPU_HOTPLUG_IO_BASE 0xaf00
+#define CPU_HOTPLUG_RESOURCE_DEVICE PRES
 
 #define ACPI_MEMORY_HOTPLUG_IO_LEN 24
 #define ACPI_MEMORY_HOTPLUG_BASE 0x0a00
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
index 9323838319..f3526d4aaf 100644
--- a/include/hw/acpi/pcihp.h
+++ b/include/hw/acpi/pcihp.h
@@ -32,6 +32,9 @@
 #include "hw/acpi/acpi.h"
 #include "migration/vmstate.h"
 
+#define ACPI_PCIHP_IO_BASE_PROP "acpi-pcihp-io-base"
+#define ACPI_PCIHP_IO_LEN_PROP "acpi-pcihp-io-len"
+
 typedef struct AcpiPciHpPciStatus {
     uint32_t up;
     uint32_t down;
@@ -48,9 +51,11 @@ typedef struct AcpiPciHpState {
     PCIBus *root;
     MemoryRegion io;
     bool legacy_piix;
+    uint16_t io_base;
+    uint16_t io_len;
 } AcpiPciHpState;
 
-void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root,
+void acpi_pcihp_init(Object *owner, AcpiPciHpState *, PCIBus *root,
                      MemoryRegion *address_space_io, bool bridges_enabled);
 
 void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 08ab67d7fd..1b35168e96 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -104,6 +104,7 @@ struct PcGuestInfo {
     int legacy_acpi_table_size;
     bool has_acpi_build;
     bool has_reserved_memory;
+    bool rsdp_in_ram;
 };
 
 /* parallel.c */
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index cf7bd343c7..f21ceaafc6 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -21,10 +21,17 @@
 #define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
 
 #define TYPE_APPLE_SMC "isa-applesmc"
+#define APPLESMC_MAX_DATA_LENGTH       32
+#define APPLESMC_PROP_IO_BASE "iobase"
 
-static inline bool applesmc_find(void)
+static inline uint16_t applesmc_port(void)
 {
-    return object_resolve_path_type("", TYPE_APPLE_SMC, NULL);
+    Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL);
+
+    if (obj) {
+        return object_property_get_int(obj, APPLESMC_PROP_IO_BASE, NULL);
+    }
+    return 0;
 }
 
 typedef struct ISADeviceClass {
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index bdee464e61..be2d9b8703 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -185,7 +185,8 @@ typedef struct PCIINTxRoute {
 typedef struct PCIDeviceClass {
     DeviceClass parent_class;
 
-    int (*init)(PCIDevice *dev);
+    void (*realize)(PCIDevice *dev, Error **errp);
+    int (*init)(PCIDevice *dev);/* TODO convert to realize() and remove */
     PCIUnregisterFunc *exit;
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
@@ -370,9 +371,6 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev,
                                           PCIINTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 
-PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus,
-                        const char *default_model,
-                        const char *default_devaddr);
 PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
                                const char *default_model,
                                const char *default_devaddr);
@@ -402,12 +400,8 @@ PCIBus *pci_device_root_bus(const PCIDevice *d);
 const char *pci_root_bus_path(PCIDevice *dev);
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
-PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr);
 void pci_bus_get_w64_range(PCIBus *bus, Range *range);
 
-int pci_parse_devaddr(const char *addr, int *domp, int *busp,
-                      unsigned int *slotp, unsigned int *funcp);
-
 void pci_device_deassert_intx(PCIDevice *dev);
 
 typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 070006c715..57ee363b89 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -180,9 +180,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
 void qdev_prop_register_global(GlobalProperty *prop);
 void qdev_prop_register_global_list(GlobalProperty *props);
 int qdev_prop_check_globals(void);
-void qdev_prop_set_globals(DeviceState *dev, Error **errp);
-void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
-                                    Error **errp);
+void qdev_prop_set_globals(DeviceState *dev);
 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
                                     Property *prop, const char *value);
 
diff --git a/include/hw/virtio/dataplane/vring-accessors.h b/include/hw/virtio/dataplane/vring-accessors.h
index b508b87900..815c19b6ef 100644
--- a/include/hw/virtio/dataplane/vring-accessors.h
+++ b/include/hw/virtio/dataplane/vring-accessors.h
@@ -1,7 +1,7 @@
 #ifndef VRING_ACCESSORS_H
 #define VRING_ACCESSORS_H
 
-#include "hw/virtio/virtio_ring.h"
+#include "standard-headers/linux/virtio_ring.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-access.h"
 
diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h
index e42c0fc9cc..8d97db9e2d 100644
--- a/include/hw/virtio/dataplane/vring.h
+++ b/include/hw/virtio/dataplane/vring.h
@@ -18,7 +18,7 @@
 #define VRING_H
 
 #include "qemu-common.h"
-#include "hw/virtio/virtio_ring.h"
+#include "standard-headers/linux/virtio_ring.h"
 #include "hw/virtio/virtio.h"
 
 typedef struct {
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index f863bfe27a..4ab8f541b0 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -15,6 +15,7 @@
 #ifndef _QEMU_VIRTIO_BALLOON_H
 #define _QEMU_VIRTIO_BALLOON_H
 
+#include "standard-headers/linux/virtio_balloon.h"
 #include "hw/virtio/virtio.h"
 #include "hw/pci/pci.h"
 
@@ -22,39 +23,7 @@
 #define VIRTIO_BALLOON(obj) \
         OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON)
 
-/* from Linux's linux/virtio_balloon.h */
-
-/* The ID for virtio_balloon */
-#define VIRTIO_ID_BALLOON 5
-
-/* The feature bitmap for virtio balloon */
-#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */
-#define VIRTIO_BALLOON_F_STATS_VQ 1       /* Memory stats virtqueue */
-
-/* Size of a PFN in the balloon interface. */
-#define VIRTIO_BALLOON_PFN_SHIFT 12
-
-struct virtio_balloon_config
-{
-    /* Number of pages host wants Guest to give up. */
-    uint32_t num_pages;
-    /* Number of pages we've actually got in balloon. */
-    uint32_t actual;
-};
-
-/* Memory Statistics */
-#define VIRTIO_BALLOON_S_SWAP_IN  0   /* Amount of memory swapped in */
-#define VIRTIO_BALLOON_S_SWAP_OUT 1   /* Amount of memory swapped out */
-#define VIRTIO_BALLOON_S_MAJFLT   2   /* Number of major faults */
-#define VIRTIO_BALLOON_S_MINFLT   3   /* Number of minor faults */
-#define VIRTIO_BALLOON_S_MEMFREE  4   /* Total amount of free memory */
-#define VIRTIO_BALLOON_S_MEMTOT   5   /* Total amount of memory */
-#define VIRTIO_BALLOON_S_NR       6
-
-typedef struct VirtIOBalloonStat {
-    uint16_t tag;
-    uint64_t val;
-} QEMU_PACKED VirtIOBalloonStat;
+typedef struct virtio_balloon_stat VirtIOBalloonStat;
 
 typedef struct VirtIOBalloon {
     VirtIODevice parent_obj;
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index fc7d311a43..b3ffcd96b8 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -14,6 +14,7 @@
 #ifndef _QEMU_VIRTIO_BLK_H
 #define _QEMU_VIRTIO_BLK_H
 
+#include "standard-headers/linux/virtio_blk.h"
 #include "hw/virtio/virtio.h"
 #include "hw/block/block.h"
 #include "sysemu/iothread.h"
@@ -23,88 +24,12 @@
 #define VIRTIO_BLK(obj) \
         OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK)
 
-/* from Linux's linux/virtio_blk.h */
-
-/* The ID for virtio_block */
-#define VIRTIO_ID_BLOCK 2
-
-/* Feature bits */
-#define VIRTIO_BLK_F_BARRIER    0       /* Does host support barriers? */
-#define VIRTIO_BLK_F_SIZE_MAX   1       /* Indicates maximum segment size */
-#define VIRTIO_BLK_F_SEG_MAX    2       /* Indicates maximum # of segments */
-#define VIRTIO_BLK_F_GEOMETRY   4       /* Indicates support of legacy geometry */
-#define VIRTIO_BLK_F_RO         5       /* Disk is read-only */
-#define VIRTIO_BLK_F_BLK_SIZE   6       /* Block size of disk is available*/
-#define VIRTIO_BLK_F_SCSI       7       /* Supports scsi command passthru */
-/* #define VIRTIO_BLK_F_IDENTIFY   8       ATA IDENTIFY supported, DEPRECATED */
-#define VIRTIO_BLK_F_WCE        9       /* write cache enabled */
-#define VIRTIO_BLK_F_TOPOLOGY   10      /* Topology information is available */
-#define VIRTIO_BLK_F_CONFIG_WCE 11      /* write cache configurable */
-
-#define VIRTIO_BLK_ID_BYTES     20      /* ID string length */
-
-struct virtio_blk_config
-{
-    uint64_t capacity;
-    uint32_t size_max;
-    uint32_t seg_max;
-    uint16_t cylinders;
-    uint8_t heads;
-    uint8_t sectors;
-    uint32_t blk_size;
-    uint8_t physical_block_exp;
-    uint8_t alignment_offset;
-    uint16_t min_io_size;
-    uint32_t opt_io_size;
-    uint8_t wce;
-} QEMU_PACKED;
-
-/* These two define direction. */
-#define VIRTIO_BLK_T_IN         0
-#define VIRTIO_BLK_T_OUT        1
-
-/* This bit says it's a scsi command, not an actual read or write. */
-#define VIRTIO_BLK_T_SCSI_CMD   2
-
-/* Flush the volatile write cache */
-#define VIRTIO_BLK_T_FLUSH      4
-
-/* return the device ID string */
-#define VIRTIO_BLK_T_GET_ID     8
-
-/* Barrier before this op. */
-#define VIRTIO_BLK_T_BARRIER    0x80000000
-
-/* This is the first element of the read scatter-gather list. */
-struct virtio_blk_outhdr
-{
-    /* VIRTIO_BLK_T* */
-    uint32_t type;
-    /* io priority. */
-    uint32_t ioprio;
-    /* Sector (ie. 512 byte offset) */
-    uint64_t sector;
-};
-
-#define VIRTIO_BLK_S_OK         0
-#define VIRTIO_BLK_S_IOERR      1
-#define VIRTIO_BLK_S_UNSUPP     2
-
 /* This is the last element of the write scatter-gather list */
 struct virtio_blk_inhdr
 {
     unsigned char status;
 };
 
-/* SCSI pass-through header */
-struct virtio_scsi_inhdr
-{
-    uint32_t errors;
-    uint32_t data_len;
-    uint32_t sense_len;
-    uint32_t residual;
-};
-
 struct VirtIOBlkConf
 {
     BlockConf conf;
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index 0756545d4d..0d2e7b49b2 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -84,9 +84,6 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus);
 /* Get the features of the plugged device. */
 uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
                                     uint32_t requested_features);
-/* Set the features of the plugged device. */
-void virtio_bus_set_vdev_features(VirtioBusState *bus,
-                                  uint32_t requested_features);
 /* Get bad features of the plugged device. */
 uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus);
 /* Get config of the plugged device. */
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index 6ceb5aa92e..4c2fe83b6b 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -14,49 +14,15 @@
 #ifndef _QEMU_VIRTIO_NET_H
 #define _QEMU_VIRTIO_NET_H
 
+#include "standard-headers/linux/virtio_net.h"
 #include "hw/virtio/virtio.h"
-#include "hw/pci/pci.h"
 
 #define TYPE_VIRTIO_NET "virtio-net-device"
 #define VIRTIO_NET(obj) \
         OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET)
 
-#define ETH_ALEN    6
-
-/* from Linux's virtio_net.h */
-
-/* The ID for virtio_net */
-#define VIRTIO_ID_NET   1
-
-/* The feature bitmap for virtio net */
-#define VIRTIO_NET_F_CSUM       0       /* Host handles pkts w/ partial csum */
-#define VIRTIO_NET_F_GUEST_CSUM 1       /* Guest handles pkts w/ partial csum */
 #define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Control channel offload
                                          * configuration support */
-#define VIRTIO_NET_F_MAC        5       /* Host has given MAC address. */
-#define VIRTIO_NET_F_GSO        6       /* Host handles pkts w/ any GSO type */
-#define VIRTIO_NET_F_GUEST_TSO4 7       /* Guest can handle TSOv4 in. */
-#define VIRTIO_NET_F_GUEST_TSO6 8       /* Guest can handle TSOv6 in. */
-#define VIRTIO_NET_F_GUEST_ECN  9       /* Guest can handle TSO[6] w/ ECN in. */
-#define VIRTIO_NET_F_GUEST_UFO  10      /* Guest can handle UFO in. */
-#define VIRTIO_NET_F_HOST_TSO4  11      /* Host can handle TSOv4 in. */
-#define VIRTIO_NET_F_HOST_TSO6  12      /* Host can handle TSOv6 in. */
-#define VIRTIO_NET_F_HOST_ECN   13      /* Host can handle TSO[6] w/ ECN in. */
-#define VIRTIO_NET_F_HOST_UFO   14      /* Host can handle UFO in. */
-#define VIRTIO_NET_F_MRG_RXBUF  15      /* Host can merge receive buffers. */
-#define VIRTIO_NET_F_STATUS     16      /* virtio_net_config.status available */
-#define VIRTIO_NET_F_CTRL_VQ    17      /* Control channel available */
-#define VIRTIO_NET_F_CTRL_RX    18      /* Control channel RX mode support */
-#define VIRTIO_NET_F_CTRL_VLAN  19      /* Control channel VLAN filtering */
-#define VIRTIO_NET_F_CTRL_RX_EXTRA 20   /* Extra RX mode control support */
-#define VIRTIO_NET_F_GUEST_ANNOUNCE 21  /* Guest can announce itself */
-#define VIRTIO_NET_F_MQ         22      /* Device supports Receive Flow
-                                         * Steering */
-
-#define VIRTIO_NET_F_CTRL_MAC_ADDR   23 /* Set MAC address */
-
-#define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
-#define VIRTIO_NET_S_ANNOUNCE   2       /* Announcement is needed */
 
 #define TX_TIMER_INTERVAL 150000 /* 150 us */
 
@@ -77,72 +43,6 @@ typedef struct virtio_net_conf
 /* Maximum packet size we can receive from tap device: header + 64k */
 #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
 
-struct virtio_net_config
-{
-    /* The config defining mac address ($ETH_ALEN bytes) */
-    uint8_t mac[ETH_ALEN];
-    /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
-    uint16_t status;
-    /* Max virtqueue pairs supported by the device */
-    uint16_t max_virtqueue_pairs;
-} QEMU_PACKED;
-
-/*
- * Control virtqueue data structures
- *
- * The control virtqueue expects a header in the first sg entry
- * and an ack/status response in the last entry.  Data for the
- * command goes in between.
- */
-struct virtio_net_ctrl_hdr {
-    uint8_t class;
-    uint8_t cmd;
-};
-
-typedef uint8_t virtio_net_ctrl_ack;
-
-#define VIRTIO_NET_OK     0
-#define VIRTIO_NET_ERR    1
-
-/*
- * Control the RX mode, ie. promisucous, allmulti, etc...
- * All commands require an "out" sg entry containing a 1 byte
- * state value, zero = disable, non-zero = enable.  Commands
- * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.
- * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.
- */
-#define VIRTIO_NET_CTRL_RX    0
- #define VIRTIO_NET_CTRL_RX_PROMISC      0
- #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
- #define VIRTIO_NET_CTRL_RX_ALLUNI       2
- #define VIRTIO_NET_CTRL_RX_NOMULTI      3
- #define VIRTIO_NET_CTRL_RX_NOUNI        4
- #define VIRTIO_NET_CTRL_RX_NOBCAST      5
-
-/*
- * Control the MAC
- *
- * The MAC filter table is managed by the hypervisor, the guest should
- * assume the size is infinite.  Filtering should be considered
- * non-perfect, ie. based on hypervisor resources, the guest may
- * received packets from sources not specified in the filter list.
- *
- * In addition to the class/cmd header, the TABLE_SET command requires
- * two out scatterlists.  Each contains a 4 byte count of entries followed
- * by a concatenated byte stream of the ETH_ALEN MAC addresses.  The
- * first sg list contains unicast addresses, the second is for multicast.
- * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
- * is available.
- *
- * The ADDR_SET command requests one out scatterlist, it contains a
- * 6 bytes MAC address. This functionality is present if the
- * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
- */
-struct virtio_net_ctrl_mac {
-    uint32_t entries;
-    uint8_t macs[][ETH_ALEN];
-};
-
 typedef struct VirtIONetQueue {
     VirtQueue *rx_vq;
     VirtQueue *tx_vq;
@@ -199,55 +99,6 @@ typedef struct VirtIONet {
     int announce_counter;
 } VirtIONet;
 
-#define VIRTIO_NET_CTRL_MAC    1
- #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
- #define VIRTIO_NET_CTRL_MAC_ADDR_SET         1
-
-/*
- * Control VLAN filtering
- *
- * The VLAN filter table is controlled via a simple ADD/DEL interface.
- * VLAN IDs not added may be filterd by the hypervisor.  Del is the
- * opposite of add.  Both commands expect an out entry containing a 2
- * byte VLAN ID.  VLAN filterting is available with the
- * VIRTIO_NET_F_CTRL_VLAN feature bit.
- */
-#define VIRTIO_NET_CTRL_VLAN       2
- #define VIRTIO_NET_CTRL_VLAN_ADD             0
- #define VIRTIO_NET_CTRL_VLAN_DEL             1
-
-/*
- * Control link announce acknowledgement
- *
- * VIRTIO_NET_S_ANNOUNCE bit in the status field requests link announcement from
- * guest driver. The driver is notified by config space change interrupt.  The
- * command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that the driver has
- * received the notification. It makes the device clear the bit
- * VIRTIO_NET_S_ANNOUNCE in the status field.
- */
-#define VIRTIO_NET_CTRL_ANNOUNCE       3
- #define VIRTIO_NET_CTRL_ANNOUNCE_ACK         0
-
-/*
- * Control Multiqueue
- *
- * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET
- * enables multiqueue, specifying the number of the transmit and
- * receive queues that will be used. After the command is consumed and acked by
- * the device, the device will not steer new packets on receive virtqueues
- * other than specified nor read from transmit virtqueues other than specified.
- * Accordingly, driver should not transmit new packets  on virtqueues other than
- * specified.
- */
-struct virtio_net_ctrl_mq {
-    uint16_t virtqueue_pairs;
-};
-
-#define VIRTIO_NET_CTRL_MQ   4
- #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET        0
- #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN        1
- #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000
-
 /*
  * Control network offloads
  *
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
index 14e85a5a3a..7702ff4749 100644
--- a/include/hw/virtio/virtio-rng.h
+++ b/include/hw/virtio/virtio-rng.h
@@ -14,6 +14,7 @@
 
 #include "sysemu/rng.h"
 #include "sysemu/rng-random.h"
+#include "standard-headers/linux/virtio_rng.h"
 
 #define TYPE_VIRTIO_RNG "virtio-rng-device"
 #define VIRTIO_RNG(obj) \
@@ -21,9 +22,6 @@
 #define VIRTIO_RNG_GET_PARENT_CLASS(obj) \
         OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_RNG)
 
-/* The Virtio ID for the virtio rng device */
-#define VIRTIO_ID_RNG    4
-
 struct VirtIORNGConf {
     RngBackend *rng;
     uint64_t max_bytes;
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index c122e7ae5c..de2c739d22 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -14,6 +14,7 @@
 #ifndef _QEMU_VIRTIO_SCSI_H
 #define _QEMU_VIRTIO_SCSI_H
 
+#include "standard-headers/linux/virtio_scsi.h"
 #include "hw/virtio/virtio.h"
 #include "hw/pci/pci.h"
 #include "hw/scsi/scsi.h"
@@ -28,15 +29,6 @@
 #define VIRTIO_SCSI(obj) \
         OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI)
 
-
-/* The ID for virtio_scsi */
-#define VIRTIO_ID_SCSI  8
-
-/* Feature Bits */
-#define VIRTIO_SCSI_F_INOUT                    0
-#define VIRTIO_SCSI_F_HOTPLUG                  1
-#define VIRTIO_SCSI_F_CHANGE                   2
-
 #define VIRTIO_SCSI_VQ_SIZE     128
 #define VIRTIO_SCSI_CDB_SIZE    32
 #define VIRTIO_SCSI_SENSE_SIZE  96
@@ -44,108 +36,14 @@
 #define VIRTIO_SCSI_MAX_TARGET  255
 #define VIRTIO_SCSI_MAX_LUN     16383
 
-/* Response codes */
-#define VIRTIO_SCSI_S_OK                       0
-#define VIRTIO_SCSI_S_OVERRUN                  1
-#define VIRTIO_SCSI_S_ABORTED                  2
-#define VIRTIO_SCSI_S_BAD_TARGET               3
-#define VIRTIO_SCSI_S_RESET                    4
-#define VIRTIO_SCSI_S_BUSY                     5
-#define VIRTIO_SCSI_S_TRANSPORT_FAILURE        6
-#define VIRTIO_SCSI_S_TARGET_FAILURE           7
-#define VIRTIO_SCSI_S_NEXUS_FAILURE            8
-#define VIRTIO_SCSI_S_FAILURE                  9
-#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED       10
-#define VIRTIO_SCSI_S_FUNCTION_REJECTED        11
-#define VIRTIO_SCSI_S_INCORRECT_LUN            12
-
-/* Controlq type codes.  */
-#define VIRTIO_SCSI_T_TMF                      0
-#define VIRTIO_SCSI_T_AN_QUERY                 1
-#define VIRTIO_SCSI_T_AN_SUBSCRIBE             2
-
-/* Valid TMF subtypes.  */
-#define VIRTIO_SCSI_T_TMF_ABORT_TASK           0
-#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET       1
-#define VIRTIO_SCSI_T_TMF_CLEAR_ACA            2
-#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET       3
-#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET      4
-#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET   5
-#define VIRTIO_SCSI_T_TMF_QUERY_TASK           6
-#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET       7
-
-/* Events.  */
-#define VIRTIO_SCSI_T_EVENTS_MISSED            0x80000000
-#define VIRTIO_SCSI_T_NO_EVENT                 0
-#define VIRTIO_SCSI_T_TRANSPORT_RESET          1
-#define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
-#define VIRTIO_SCSI_T_PARAM_CHANGE             3
-
-/* Reasons for transport reset event */
-#define VIRTIO_SCSI_EVT_RESET_HARD             0
-#define VIRTIO_SCSI_EVT_RESET_RESCAN           1
-#define VIRTIO_SCSI_EVT_RESET_REMOVED          2
-
-/* SCSI command request, followed by CDB and data-out */
-typedef struct {
-    uint8_t lun[8];              /* Logical Unit Number */
-    uint64_t tag;                /* Command identifier */
-    uint8_t task_attr;           /* Task attribute */
-    uint8_t prio;
-    uint8_t crn;
-} QEMU_PACKED VirtIOSCSICmdReq;
-
-/* Response, followed by sense data and data-in */
-typedef struct {
-    uint32_t sense_len;          /* Sense data length */
-    uint32_t resid;              /* Residual bytes in data buffer */
-    uint16_t status_qualifier;   /* Status qualifier */
-    uint8_t status;              /* Command completion status */
-    uint8_t response;            /* Response values */
-} QEMU_PACKED VirtIOSCSICmdResp;
-
-/* Task Management Request */
-typedef struct {
-    uint32_t type;
-    uint32_t subtype;
-    uint8_t lun[8];
-    uint64_t tag;
-} QEMU_PACKED VirtIOSCSICtrlTMFReq;
-
-typedef struct {
-    uint8_t response;
-} QEMU_PACKED VirtIOSCSICtrlTMFResp;
-
-/* Asynchronous notification query/subscription */
-typedef struct {
-    uint32_t type;
-    uint8_t lun[8];
-    uint32_t event_requested;
-} QEMU_PACKED VirtIOSCSICtrlANReq;
-
-typedef struct {
-    uint32_t event_actual;
-    uint8_t response;
-} QEMU_PACKED VirtIOSCSICtrlANResp;
-
-typedef struct {
-    uint32_t event;
-    uint8_t lun[8];
-    uint32_t reason;
-} QEMU_PACKED VirtIOSCSIEvent;
-
-typedef struct {
-    uint32_t num_queues;
-    uint32_t seg_max;
-    uint32_t max_sectors;
-    uint32_t cmd_per_lun;
-    uint32_t event_info_size;
-    uint32_t sense_size;
-    uint32_t cdb_size;
-    uint16_t max_channel;
-    uint16_t max_target;
-    uint32_t max_lun;
-} QEMU_PACKED VirtIOSCSIConfig;
+typedef struct virtio_scsi_cmd_req VirtIOSCSICmdReq;
+typedef struct virtio_scsi_cmd_resp VirtIOSCSICmdResp;
+typedef struct virtio_scsi_ctrl_tmf_req VirtIOSCSICtrlTMFReq;
+typedef struct virtio_scsi_ctrl_tmf_resp VirtIOSCSICtrlTMFResp;
+typedef struct virtio_scsi_ctrl_an_req VirtIOSCSICtrlANReq;
+typedef struct virtio_scsi_ctrl_an_resp VirtIOSCSICtrlANResp;
+typedef struct virtio_scsi_event VirtIOSCSIEvent;
+typedef struct virtio_scsi_config VirtIOSCSIConfig;
 
 struct VirtIOSCSIConf {
     uint32_t num_queues;
diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h
index 11af978a96..ccf8459829 100644
--- a/include/hw/virtio/virtio-serial.h
+++ b/include/hw/virtio/virtio-serial.h
@@ -15,53 +15,15 @@
 #ifndef _QEMU_VIRTIO_SERIAL_H
 #define _QEMU_VIRTIO_SERIAL_H
 
+#include "standard-headers/linux/virtio_console.h"
 #include "hw/qdev.h"
 #include "hw/virtio/virtio.h"
 
-/* == Interface shared between the guest kernel and qemu == */
-
-/* The Virtio ID for virtio console / serial ports */
-#define VIRTIO_ID_CONSOLE		3
-
-/* Features supported */
-#define VIRTIO_CONSOLE_F_MULTIPORT	1
-
-#define VIRTIO_CONSOLE_BAD_ID           (~(uint32_t)0)
-
-struct virtio_console_config {
-    /*
-     * These two fields are used by VIRTIO_CONSOLE_F_SIZE which
-     * isn't implemented here yet
-     */
-    uint16_t cols;
-    uint16_t rows;
-
-    uint32_t max_nr_ports;
-} QEMU_PACKED;
-
-struct virtio_console_control {
-    uint32_t id;		/* Port number */
-    uint16_t event;		/* The kind of control event (see below) */
-    uint16_t value;		/* Extra information for the key */
-};
-
 struct virtio_serial_conf {
     /* Max. number of ports we can have for a virtio-serial device */
     uint32_t max_virtserial_ports;
 };
 
-/* Some events for the internal messages (control packets) */
-#define VIRTIO_CONSOLE_DEVICE_READY	0
-#define VIRTIO_CONSOLE_PORT_ADD		1
-#define VIRTIO_CONSOLE_PORT_REMOVE	2
-#define VIRTIO_CONSOLE_PORT_READY	3
-#define VIRTIO_CONSOLE_CONSOLE_PORT	4
-#define VIRTIO_CONSOLE_RESIZE		5
-#define VIRTIO_CONSOLE_PORT_OPEN	6
-#define VIRTIO_CONSOLE_PORT_NAME	7
-
-/* == In-qemu interface == */
-
 #define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port"
 #define VIRTIO_SERIAL_PORT(obj) \
      OBJECT_CHECK(VirtIOSerialPort, (obj), TYPE_VIRTIO_SERIAL_PORT)
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index f24997d218..d95f8b6d50 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -19,56 +19,12 @@
 #include "hw/qdev.h"
 #include "sysemu/sysemu.h"
 #include "qemu/event_notifier.h"
-#ifdef CONFIG_VIRTFS
-#include "hw/virtio/virtio-9p.h"
-#endif
+#include "standard-headers/linux/virtio_config.h"
+#include "standard-headers/linux/virtio_ring.h"
 
-/* from Linux's linux/virtio_config.h */
-
-/* Status byte for guest to report progress, and synchronize features. */
-/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
-#define VIRTIO_CONFIG_S_ACKNOWLEDGE     1
-/* We have found a driver for the device. */
-#define VIRTIO_CONFIG_S_DRIVER          2
-/* Driver has used its parts of the config, and is happy */
-#define VIRTIO_CONFIG_S_DRIVER_OK       4
-/* We've given up on this device. */
-#define VIRTIO_CONFIG_S_FAILED          0x80
-
-/* Some virtio feature bits (currently bits 28 through 31) are reserved for the
- * transport being used (eg. virtio_ring), the rest are per-device feature bits. */
-#define VIRTIO_TRANSPORT_F_START        28
-#define VIRTIO_TRANSPORT_F_END          32
-
-/* We notify when the ring is completely used, even if the guest is suppressing
- * callbacks */
-#define VIRTIO_F_NOTIFY_ON_EMPTY        24
-/* Can the device handle any descriptor layout? */
-#define VIRTIO_F_ANY_LAYOUT             27
-/* We support indirect buffer descriptors */
-#define VIRTIO_RING_F_INDIRECT_DESC     28
-/* The Guest publishes the used index for which it expects an interrupt
- * at the end of the avail ring. Host should ignore the avail->flags field. */
-/* The Host publishes the avail index for which it expects a kick
- * at the end of the used ring. Guest should ignore the used->flags field. */
-#define VIRTIO_RING_F_EVENT_IDX         29
 /* A guest should never accept this.  It implies negotiation is broken. */
 #define VIRTIO_F_BAD_FEATURE		30
 
-/* from Linux's linux/virtio_ring.h */
-
-/* This marks a buffer as continuing via the next field. */
-#define VRING_DESC_F_NEXT       1
-/* This marks a buffer as write-only (otherwise read-only). */
-#define VRING_DESC_F_WRITE      2
-/* This means the buffer contains a list of buffer descriptors. */
-#define VRING_DESC_F_INDIRECT  4
-
-/* This means don't notify other side when buffer added. */
-#define VRING_USED_F_NO_NOTIFY  1
-/* This means don't interrupt guest when buffer consumed. */
-#define VRING_AVAIL_F_NO_INTERRUPT      1
-
 struct VirtQueue;
 
 static inline hwaddr vring_align(hwaddr addr,
@@ -263,6 +219,29 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign,
 void virtio_queue_notify_vq(VirtQueue *vq);
 void virtio_irq(VirtQueue *vq);
 
+static inline void virtio_add_feature(uint32_t *features, unsigned int fbit)
+{
+    assert(fbit < 32);
+    *features |= (1 << fbit);
+}
+
+static inline void virtio_clear_feature(uint32_t *features, unsigned int fbit)
+{
+    assert(fbit < 32);
+    *features &= ~(1 << fbit);
+}
+
+static inline bool __virtio_has_feature(uint32_t features, unsigned int fbit)
+{
+    assert(fbit < 32);
+    return !!(features & (1 << fbit));
+}
+
+static inline bool virtio_has_feature(VirtIODevice *vdev, unsigned int fbit)
+{
+    return __virtio_has_feature(vdev->guest_features, fbit);
+}
+
 static inline bool virtio_is_big_endian(VirtIODevice *vdev)
 {
     assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
diff --git a/include/net/tap.h b/include/net/tap.h
index 6daeb42b0f..5da4edc692 100644
--- a/include/net/tap.h
+++ b/include/net/tap.h
@@ -28,6 +28,7 @@
 
 #include "qemu-common.h"
 #include "qapi-types.h"
+#include "standard-headers/linux/virtio_net.h"
 
 int tap_enable(NetClientState *nc);
 int tap_disable(NetClientState *nc);
@@ -37,27 +38,4 @@ int tap_get_fd(NetClientState *nc);
 struct vhost_net;
 struct vhost_net *tap_get_vhost_net(NetClientState *nc);
 
-struct virtio_net_hdr
-{
-#define VIRTIO_NET_HDR_F_NEEDS_CSUM     1       // Use csum_start, csum_offset
-#define VIRTIO_NET_HDR_F_DATA_VALID    2       // Csum is valid
-    uint8_t flags;
-#define VIRTIO_NET_HDR_GSO_NONE         0       // Not a GSO frame
-#define VIRTIO_NET_HDR_GSO_TCPV4        1       // GSO frame, IPv4 TCP (TSO)
-#define VIRTIO_NET_HDR_GSO_UDP          3       // GSO frame, IPv4 UDP (UFO)
-#define VIRTIO_NET_HDR_GSO_TCPV6        4       // GSO frame, IPv6 TCP
-#define VIRTIO_NET_HDR_GSO_ECN          0x80    // TCP has ECN set
-    uint8_t gso_type;
-    uint16_t hdr_len;
-    uint16_t gso_size;
-    uint16_t csum_start;
-    uint16_t csum_offset;
-};
-
-struct virtio_net_hdr_mrg_rxbuf
-{
-    struct virtio_net_hdr hdr;
-    uint16_t num_buffers;   /* Number of merged rx buffers */
-};
-
 #endif /* QEMU_NET_TAP_H */
diff --git a/include/standard-headers/asm-s390/kvm_virtio.h b/include/standard-headers/asm-s390/kvm_virtio.h
new file mode 100644
index 0000000000..daad3249d2
--- /dev/null
+++ b/include/standard-headers/asm-s390/kvm_virtio.h
@@ -0,0 +1,64 @@
+/*
+ * definition for virtio for kvm on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#ifndef __KVM_S390_VIRTIO_H
+#define __KVM_S390_VIRTIO_H
+
+#include "standard-headers/linux/types.h"
+
+struct kvm_device_desc {
+	/* The device type: console, network, disk etc.  Type 0 terminates. */
+	uint8_t type;
+	/* The number of virtqueues (first in config array) */
+	uint8_t num_vq;
+	/*
+	 * The number of bytes of feature bits.  Multiply by 2: one for host
+	 * features and one for guest acknowledgements.
+	 */
+	uint8_t feature_len;
+	/* The number of bytes of the config array after virtqueues. */
+	uint8_t config_len;
+	/* A status byte, written by the Guest. */
+	uint8_t status;
+	uint8_t config[0];
+};
+
+/*
+ * This is how we expect the device configuration field for a virtqueue
+ * to be laid out in config space.
+ */
+struct kvm_vqconfig {
+	/* The token returned with an interrupt. Set by the guest */
+	uint64_t token;
+	/* The address of the virtio ring */
+	uint64_t address;
+	/* The number of entries in the virtio_ring */
+	uint16_t num;
+
+};
+
+#define KVM_S390_VIRTIO_NOTIFY		0
+#define KVM_S390_VIRTIO_RESET		1
+#define KVM_S390_VIRTIO_SET_STATUS	2
+
+/* The alignment to use between consumer and producer parts of vring.
+ * This is pagesize for historical reasons. */
+#define KVM_S390_VIRTIO_RING_ALIGN	4096
+
+
+/* These values are supposed to be in ext_params on an interrupt */
+#define VIRTIO_PARAM_MASK		0xff
+#define VIRTIO_PARAM_VRING_INTERRUPT	0x0
+#define VIRTIO_PARAM_CONFIG_CHANGED	0x1
+#define VIRTIO_PARAM_DEV_ADD		0x2
+
+#endif
diff --git a/include/standard-headers/asm-s390/virtio-ccw.h b/include/standard-headers/asm-s390/virtio-ccw.h
new file mode 100644
index 0000000000..a9a4ebf79f
--- /dev/null
+++ b/include/standard-headers/asm-s390/virtio-ccw.h
@@ -0,0 +1,21 @@
+/*
+ * Definitions for virtio-ccw devices.
+ *
+ * Copyright IBM Corp. 2013
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *  Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
+ */
+#ifndef __KVM_VIRTIO_CCW_H
+#define __KVM_VIRTIO_CCW_H
+
+/* Alignment of vring buffers. */
+#define KVM_VIRTIO_CCW_RING_ALIGN 4096
+
+/* Subcode for diagnose 500 (virtio hypercall). */
+#define KVM_S390_VIRTIO_CCW_NOTIFY 3
+
+#endif
diff --git a/include/standard-headers/linux/if_ether.h b/include/standard-headers/linux/if_ether.h
new file mode 100644
index 0000000000..91cf735fb5
--- /dev/null
+++ b/include/standard-headers/linux/if_ether.h
@@ -0,0 +1 @@
+#define ETH_ALEN    6
diff --git a/include/standard-headers/linux/types.h b/include/standard-headers/linux/types.h
new file mode 100644
index 0000000000..0526c2b87c
--- /dev/null
+++ b/include/standard-headers/linux/types.h
@@ -0,0 +1,2 @@
+#include <stdint.h>
+#include "qemu/compiler.h"
diff --git a/include/standard-headers/linux/virtio_9p.h b/include/standard-headers/linux/virtio_9p.h
new file mode 100644
index 0000000000..e68f71dbe6
--- /dev/null
+++ b/include/standard-headers/linux/virtio_9p.h
@@ -0,0 +1,44 @@
+#ifndef _LINUX_VIRTIO_9P_H
+#define _LINUX_VIRTIO_9P_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+#include "standard-headers/linux/types.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_config.h"
+
+/* The feature bitmap for virtio 9P */
+
+/* The mount point is specified in a config variable */
+#define VIRTIO_9P_MOUNT_TAG 0
+
+struct virtio_9p_config {
+	/* length of the tag name */
+	uint16_t tag_len;
+	/* non-NULL terminated tag name */
+	uint8_t tag[0];
+} QEMU_PACKED;
+
+#endif /* _LINUX_VIRTIO_9P_H */
diff --git a/include/standard-headers/linux/virtio_balloon.h b/include/standard-headers/linux/virtio_balloon.h
new file mode 100644
index 0000000000..799376d414
--- /dev/null
+++ b/include/standard-headers/linux/virtio_balloon.h
@@ -0,0 +1,59 @@
+#ifndef _LINUX_VIRTIO_BALLOON_H
+#define _LINUX_VIRTIO_BALLOON_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_config.h"
+
+/* The feature bitmap for virtio balloon */
+#define VIRTIO_BALLOON_F_MUST_TELL_HOST	0 /* Tell before reclaiming pages */
+#define VIRTIO_BALLOON_F_STATS_VQ	1 /* Memory Stats virtqueue */
+#define VIRTIO_BALLOON_F_DEFLATE_ON_OOM	2 /* Deflate balloon on OOM */
+
+/* Size of a PFN in the balloon interface. */
+#define VIRTIO_BALLOON_PFN_SHIFT 12
+
+struct virtio_balloon_config {
+	/* Number of pages host wants Guest to give up. */
+	uint32_t num_pages;
+	/* Number of pages we've actually got in balloon. */
+	uint32_t actual;
+};
+
+#define VIRTIO_BALLOON_S_SWAP_IN  0   /* Amount of memory swapped in */
+#define VIRTIO_BALLOON_S_SWAP_OUT 1   /* Amount of memory swapped out */
+#define VIRTIO_BALLOON_S_MAJFLT   2   /* Number of major faults */
+#define VIRTIO_BALLOON_S_MINFLT   3   /* Number of minor faults */
+#define VIRTIO_BALLOON_S_MEMFREE  4   /* Total amount of free memory */
+#define VIRTIO_BALLOON_S_MEMTOT   5   /* Total amount of memory */
+#define VIRTIO_BALLOON_S_NR       6
+
+struct virtio_balloon_stat {
+	uint16_t tag;
+	uint64_t val;
+} QEMU_PACKED;
+
+#endif /* _LINUX_VIRTIO_BALLOON_H */
diff --git a/include/standard-headers/linux/virtio_blk.h b/include/standard-headers/linux/virtio_blk.h
new file mode 100644
index 0000000000..12016b47f3
--- /dev/null
+++ b/include/standard-headers/linux/virtio_blk.h
@@ -0,0 +1,143 @@
+#ifndef _LINUX_VIRTIO_BLK_H
+#define _LINUX_VIRTIO_BLK_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+#include "standard-headers/linux/types.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_config.h"
+#include "standard-headers/linux/virtio_types.h"
+
+/* Feature bits */
+#define VIRTIO_BLK_F_SIZE_MAX	1	/* Indicates maximum segment size */
+#define VIRTIO_BLK_F_SEG_MAX	2	/* Indicates maximum # of segments */
+#define VIRTIO_BLK_F_GEOMETRY	4	/* Legacy geometry available  */
+#define VIRTIO_BLK_F_RO		5	/* Disk is read-only */
+#define VIRTIO_BLK_F_BLK_SIZE	6	/* Block size of disk is available*/
+#define VIRTIO_BLK_F_TOPOLOGY	10	/* Topology information is available */
+#define VIRTIO_BLK_F_MQ		12	/* support more than one vq */
+
+/* Legacy feature bits */
+#ifndef VIRTIO_BLK_NO_LEGACY
+#define VIRTIO_BLK_F_BARRIER	0	/* Does host support barriers? */
+#define VIRTIO_BLK_F_SCSI	7	/* Supports scsi command passthru */
+#define VIRTIO_BLK_F_WCE	9	/* Writeback mode enabled after reset */
+#define VIRTIO_BLK_F_CONFIG_WCE	11	/* Writeback mode available in config */
+/* Old (deprecated) name for VIRTIO_BLK_F_WCE. */
+#define VIRTIO_BLK_F_FLUSH VIRTIO_BLK_F_WCE
+#endif /* !VIRTIO_BLK_NO_LEGACY */
+
+#define VIRTIO_BLK_ID_BYTES	20	/* ID string length */
+
+struct virtio_blk_config {
+	/* The capacity (in 512-byte sectors). */
+	uint64_t capacity;
+	/* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */
+	uint32_t size_max;
+	/* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
+	uint32_t seg_max;
+	/* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */
+	struct virtio_blk_geometry {
+		uint16_t cylinders;
+		uint8_t heads;
+		uint8_t sectors;
+	} geometry;
+
+	/* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
+	uint32_t blk_size;
+
+	/* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY  */
+	/* exponent for physical block per logical block. */
+	uint8_t physical_block_exp;
+	/* alignment offset in logical blocks. */
+	uint8_t alignment_offset;
+	/* minimum I/O size without performance penalty in logical blocks. */
+	uint16_t min_io_size;
+	/* optimal sustained I/O size in logical blocks. */
+	uint32_t opt_io_size;
+
+	/* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
+	uint8_t wce;
+	uint8_t unused;
+
+	/* number of vqs, only available when VIRTIO_BLK_F_MQ is set */
+	uint16_t num_queues;
+} QEMU_PACKED;
+
+/*
+ * Command types
+ *
+ * Usage is a bit tricky as some bits are used as flags and some are not.
+ *
+ * Rules:
+ *   VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
+ *   VIRTIO_BLK_T_BARRIER.  VIRTIO_BLK_T_FLUSH is a command of its own
+ *   and may not be combined with any of the other flags.
+ */
+
+/* These two define direction. */
+#define VIRTIO_BLK_T_IN		0
+#define VIRTIO_BLK_T_OUT	1
+
+#ifndef VIRTIO_BLK_NO_LEGACY
+/* This bit says it's a scsi command, not an actual read or write. */
+#define VIRTIO_BLK_T_SCSI_CMD	2
+#endif /* VIRTIO_BLK_NO_LEGACY */
+
+/* Cache flush command */
+#define VIRTIO_BLK_T_FLUSH	4
+
+/* Get device ID command */
+#define VIRTIO_BLK_T_GET_ID    8
+
+#ifndef VIRTIO_BLK_NO_LEGACY
+/* Barrier before this op. */
+#define VIRTIO_BLK_T_BARRIER	0x80000000
+#endif /* !VIRTIO_BLK_NO_LEGACY */
+
+/* This is the first element of the read scatter-gather list. */
+struct virtio_blk_outhdr {
+	/* VIRTIO_BLK_T* */
+	__virtio32 type;
+	/* io priority. */
+	__virtio32 ioprio;
+	/* Sector (ie. 512 byte offset) */
+	__virtio64 sector;
+};
+
+#ifndef VIRTIO_BLK_NO_LEGACY
+struct virtio_scsi_inhdr {
+	__virtio32 errors;
+	__virtio32 data_len;
+	__virtio32 sense_len;
+	__virtio32 residual;
+};
+#endif /* !VIRTIO_BLK_NO_LEGACY */
+
+/* And this is the final byte of the write scatter-gather list. */
+#define VIRTIO_BLK_S_OK		0
+#define VIRTIO_BLK_S_IOERR	1
+#define VIRTIO_BLK_S_UNSUPP	2
+#endif /* _LINUX_VIRTIO_BLK_H */
diff --git a/include/standard-headers/linux/virtio_config.h b/include/standard-headers/linux/virtio_config.h
new file mode 100644
index 0000000000..bcc445b3d8
--- /dev/null
+++ b/include/standard-headers/linux/virtio_config.h
@@ -0,0 +1,64 @@
+#ifndef _LINUX_VIRTIO_CONFIG_H
+#define _LINUX_VIRTIO_CONFIG_H
+/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
+ * anyone can use the definitions to implement compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+/* Virtio devices use a standardized configuration space to define their
+ * features and pass configuration information, but each implementation can
+ * store and access that space differently. */
+#include "standard-headers/linux/types.h"
+
+/* Status byte for guest to report progress, and synchronize features. */
+/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE	1
+/* We have found a driver for the device. */
+#define VIRTIO_CONFIG_S_DRIVER		2
+/* Driver has used its parts of the config, and is happy */
+#define VIRTIO_CONFIG_S_DRIVER_OK	4
+/* Driver has finished configuring features */
+#define VIRTIO_CONFIG_S_FEATURES_OK	8
+/* We've given up on this device. */
+#define VIRTIO_CONFIG_S_FAILED		0x80
+
+/* Some virtio feature bits (currently bits 28 through 32) are reserved for the
+ * transport being used (eg. virtio_ring), the rest are per-device feature
+ * bits. */
+#define VIRTIO_TRANSPORT_F_START	28
+#define VIRTIO_TRANSPORT_F_END		33
+
+#ifndef VIRTIO_CONFIG_NO_LEGACY
+/* Do we get callbacks when the ring is completely used, even if we've
+ * suppressed them? */
+#define VIRTIO_F_NOTIFY_ON_EMPTY	24
+
+/* Can the device handle any descriptor layout? */
+#define VIRTIO_F_ANY_LAYOUT		27
+#endif /* VIRTIO_CONFIG_NO_LEGACY */
+
+/* v1.0 compliant. */
+#define VIRTIO_F_VERSION_1		32
+
+#endif /* _LINUX_VIRTIO_CONFIG_H */
diff --git a/include/standard-headers/linux/virtio_console.h b/include/standard-headers/linux/virtio_console.h
new file mode 100644
index 0000000000..0dedc9e6f5
--- /dev/null
+++ b/include/standard-headers/linux/virtio_console.h
@@ -0,0 +1,78 @@
+/*
+ * This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
+ * anyone can use the definitions to implement compatible drivers/servers:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (C) Red Hat, Inc., 2009, 2010, 2011
+ * Copyright (C) Amit Shah <amit.shah@redhat.com>, 2009, 2010, 2011
+ */
+#ifndef _LINUX_VIRTIO_CONSOLE_H
+#define _LINUX_VIRTIO_CONSOLE_H
+#include "standard-headers/linux/types.h"
+#include "standard-headers/linux/virtio_types.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_config.h"
+
+/* Feature bits */
+#define VIRTIO_CONSOLE_F_SIZE	0	/* Does host provide console size? */
+#define VIRTIO_CONSOLE_F_MULTIPORT 1	/* Does host provide multiple ports? */
+#define VIRTIO_CONSOLE_F_EMERG_WRITE 2 /* Does host support emergency write? */
+
+#define VIRTIO_CONSOLE_BAD_ID		(~(uint32_t)0)
+
+struct virtio_console_config {
+	/* colums of the screens */
+	uint16_t cols;
+	/* rows of the screens */
+	uint16_t rows;
+	/* max. number of ports this device can hold */
+	uint32_t max_nr_ports;
+	/* emergency write register */
+	uint32_t emerg_wr;
+} QEMU_PACKED;
+
+/*
+ * A message that's passed between the Host and the Guest for a
+ * particular port.
+ */
+struct virtio_console_control {
+	__virtio32 id;		/* Port number */
+	__virtio16 event;	/* The kind of control event (see below) */
+	__virtio16 value;	/* Extra information for the key */
+};
+
+/* Some events for control messages */
+#define VIRTIO_CONSOLE_DEVICE_READY	0
+#define VIRTIO_CONSOLE_PORT_ADD		1
+#define VIRTIO_CONSOLE_PORT_REMOVE	2
+#define VIRTIO_CONSOLE_PORT_READY	3
+#define VIRTIO_CONSOLE_CONSOLE_PORT	4
+#define VIRTIO_CONSOLE_RESIZE		5
+#define VIRTIO_CONSOLE_PORT_OPEN	6
+#define VIRTIO_CONSOLE_PORT_NAME	7
+
+
+#endif /* _LINUX_VIRTIO_CONSOLE_H */
diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h
new file mode 100644
index 0000000000..284fc3a05f
--- /dev/null
+++ b/include/standard-headers/linux/virtio_ids.h
@@ -0,0 +1,43 @@
+#ifndef _LINUX_VIRTIO_IDS_H
+#define _LINUX_VIRTIO_IDS_H
+/*
+ * Virtio IDs
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+#define VIRTIO_ID_NET		1 /* virtio net */
+#define VIRTIO_ID_BLOCK		2 /* virtio block */
+#define VIRTIO_ID_CONSOLE	3 /* virtio console */
+#define VIRTIO_ID_RNG		4 /* virtio rng */
+#define VIRTIO_ID_BALLOON	5 /* virtio balloon */
+#define VIRTIO_ID_RPMSG		7 /* virtio remote processor messaging */
+#define VIRTIO_ID_SCSI		8 /* virtio scsi */
+#define VIRTIO_ID_9P		9 /* 9p virtio console */
+#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
+#define VIRTIO_ID_CAIF	       12 /* Virtio caif */
+
+#endif /* _LINUX_VIRTIO_IDS_H */
diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h
new file mode 100644
index 0000000000..95faf67b48
--- /dev/null
+++ b/include/standard-headers/linux/virtio_net.h
@@ -0,0 +1,233 @@
+#ifndef _LINUX_VIRTIO_NET_H
+#define _LINUX_VIRTIO_NET_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+#include "standard-headers/linux/types.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_config.h"
+#include "standard-headers/linux/virtio_types.h"
+#include "standard-headers/linux/if_ether.h"
+
+/* The feature bitmap for virtio net */
+#define VIRTIO_NET_F_CSUM	0	/* Host handles pkts w/ partial csum */
+#define VIRTIO_NET_F_GUEST_CSUM	1	/* Guest handles pkts w/ partial csum */
+#define VIRTIO_NET_F_MAC	5	/* Host has given MAC address. */
+#define VIRTIO_NET_F_GUEST_TSO4	7	/* Guest can handle TSOv4 in. */
+#define VIRTIO_NET_F_GUEST_TSO6	8	/* Guest can handle TSOv6 in. */
+#define VIRTIO_NET_F_GUEST_ECN	9	/* Guest can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_GUEST_UFO	10	/* Guest can handle UFO in. */
+#define VIRTIO_NET_F_HOST_TSO4	11	/* Host can handle TSOv4 in. */
+#define VIRTIO_NET_F_HOST_TSO6	12	/* Host can handle TSOv6 in. */
+#define VIRTIO_NET_F_HOST_ECN	13	/* Host can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_HOST_UFO	14	/* Host can handle UFO in. */
+#define VIRTIO_NET_F_MRG_RXBUF	15	/* Host can merge receive buffers. */
+#define VIRTIO_NET_F_STATUS	16	/* virtio_net_config.status available */
+#define VIRTIO_NET_F_CTRL_VQ	17	/* Control channel available */
+#define VIRTIO_NET_F_CTRL_RX	18	/* Control channel RX mode support */
+#define VIRTIO_NET_F_CTRL_VLAN	19	/* Control channel VLAN filtering */
+#define VIRTIO_NET_F_CTRL_RX_EXTRA 20	/* Extra RX mode control support */
+#define VIRTIO_NET_F_GUEST_ANNOUNCE 21	/* Guest can announce device on the
+					 * network */
+#define VIRTIO_NET_F_MQ	22	/* Device supports Receive Flow
+					 * Steering */
+#define VIRTIO_NET_F_CTRL_MAC_ADDR 23	/* Set MAC address */
+
+#ifndef VIRTIO_NET_NO_LEGACY
+#define VIRTIO_NET_F_GSO	6	/* Host handles pkts w/ any GSO type */
+#endif /* VIRTIO_NET_NO_LEGACY */
+
+#define VIRTIO_NET_S_LINK_UP	1	/* Link is up */
+#define VIRTIO_NET_S_ANNOUNCE	2	/* Announcement is needed */
+
+struct virtio_net_config {
+	/* The config defining mac address (if VIRTIO_NET_F_MAC) */
+	uint8_t mac[ETH_ALEN];
+	/* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
+	uint16_t status;
+	/* Maximum number of each of transmit and receive queues;
+	 * see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ.
+	 * Legal values are between 1 and 0x8000
+	 */
+	uint16_t max_virtqueue_pairs;
+} QEMU_PACKED;
+
+#ifndef VIRTIO_NET_NO_LEGACY
+/* This header comes first in the scatter-gather list.
+ * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must
+ * be the first element of the scatter-gather list.  If you don't
+ * specify GSO or CSUM features, you can simply ignore the header. */
+struct virtio_net_hdr {
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM	1	// Use csum_start, csum_offset
+#define VIRTIO_NET_HDR_F_DATA_VALID	2	// Csum is valid
+	uint8_t flags;
+#define VIRTIO_NET_HDR_GSO_NONE		0	// Not a GSO frame
+#define VIRTIO_NET_HDR_GSO_TCPV4	1	// GSO frame, IPv4 TCP (TSO)
+#define VIRTIO_NET_HDR_GSO_UDP		3	// GSO frame, IPv4 UDP (UFO)
+#define VIRTIO_NET_HDR_GSO_TCPV6	4	// GSO frame, IPv6 TCP
+#define VIRTIO_NET_HDR_GSO_ECN		0x80	// TCP has ECN set
+	uint8_t gso_type;
+	__virtio16 hdr_len;		/* Ethernet + IP + tcp/udp hdrs */
+	__virtio16 gso_size;		/* Bytes to append to hdr_len per frame */
+	__virtio16 csum_start;	/* Position to start checksumming from */
+	__virtio16 csum_offset;	/* Offset after that to place checksum */
+};
+
+/* This is the version of the header to use when the MRG_RXBUF
+ * feature has been negotiated. */
+struct virtio_net_hdr_mrg_rxbuf {
+	struct virtio_net_hdr hdr;
+	__virtio16 num_buffers;	/* Number of merged rx buffers */
+};
+#else /* ... VIRTIO_NET_NO_LEGACY */
+/*
+ * This header comes first in the scatter-gather list.  If you don't
+ * specify GSO or CSUM features, you can simply ignore the header.
+ *
+ * This is bitwise-equivalent to the legacy struct virtio_net_hdr_mrg_rxbuf.
+ */
+struct virtio_net_hdr_v1 {
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM	1	/* Use csum_start, csum_offset */
+#define VIRTIO_NET_HDR_F_DATA_VALID	2	/* Csum is valid */
+	uint8_t flags;
+#define VIRTIO_NET_HDR_GSO_NONE		0	/* Not a GSO frame */
+#define VIRTIO_NET_HDR_GSO_TCPV4	1	/* GSO frame, IPv4 TCP (TSO) */
+#define VIRTIO_NET_HDR_GSO_UDP		3	/* GSO frame, IPv4 UDP (UFO) */
+#define VIRTIO_NET_HDR_GSO_TCPV6	4	/* GSO frame, IPv6 TCP */
+#define VIRTIO_NET_HDR_GSO_ECN		0x80	/* TCP has ECN set */
+	uint8_t gso_type;
+	__virtio16 hdr_len;	/* Ethernet + IP + tcp/udp hdrs */
+	__virtio16 gso_size;	/* Bytes to append to hdr_len per frame */
+	__virtio16 csum_start;	/* Position to start checksumming from */
+	__virtio16 csum_offset;	/* Offset after that to place checksum */
+	__virtio16 num_buffers;	/* Number of merged rx buffers */
+};
+#endif /* ...VIRTIO_NET_NO_LEGACY */
+
+/*
+ * Control virtqueue data structures
+ *
+ * The control virtqueue expects a header in the first sg entry
+ * and an ack/status response in the last entry.  Data for the
+ * command goes in between.
+ */
+struct virtio_net_ctrl_hdr {
+	uint8_t class;
+	uint8_t cmd;
+} QEMU_PACKED;
+
+typedef uint8_t virtio_net_ctrl_ack;
+
+#define VIRTIO_NET_OK     0
+#define VIRTIO_NET_ERR    1
+
+/*
+ * Control the RX mode, ie. promisucous, allmulti, etc...
+ * All commands require an "out" sg entry containing a 1 byte
+ * state value, zero = disable, non-zero = enable.  Commands
+ * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.
+ * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.
+ */
+#define VIRTIO_NET_CTRL_RX    0
+ #define VIRTIO_NET_CTRL_RX_PROMISC      0
+ #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
+ #define VIRTIO_NET_CTRL_RX_ALLUNI       2
+ #define VIRTIO_NET_CTRL_RX_NOMULTI      3
+ #define VIRTIO_NET_CTRL_RX_NOUNI        4
+ #define VIRTIO_NET_CTRL_RX_NOBCAST      5
+
+/*
+ * Control the MAC
+ *
+ * The MAC filter table is managed by the hypervisor, the guest should
+ * assume the size is infinite.  Filtering should be considered
+ * non-perfect, ie. based on hypervisor resources, the guest may
+ * received packets from sources not specified in the filter list.
+ *
+ * In addition to the class/cmd header, the TABLE_SET command requires
+ * two out scatterlists.  Each contains a 4 byte count of entries followed
+ * by a concatenated byte stream of the ETH_ALEN MAC addresses.  The
+ * first sg list contains unicast addresses, the second is for multicast.
+ * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
+ * is available.
+ *
+ * The ADDR_SET command requests one out scatterlist, it contains a
+ * 6 bytes MAC address. This functionality is present if the
+ * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
+ */
+struct virtio_net_ctrl_mac {
+	__virtio32 entries;
+	uint8_t macs[][ETH_ALEN];
+} QEMU_PACKED;
+
+#define VIRTIO_NET_CTRL_MAC    1
+ #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
+ #define VIRTIO_NET_CTRL_MAC_ADDR_SET         1
+
+/*
+ * Control VLAN filtering
+ *
+ * The VLAN filter table is controlled via a simple ADD/DEL interface.
+ * VLAN IDs not added may be filterd by the hypervisor.  Del is the
+ * opposite of add.  Both commands expect an out entry containing a 2
+ * byte VLAN ID.  VLAN filterting is available with the
+ * VIRTIO_NET_F_CTRL_VLAN feature bit.
+ */
+#define VIRTIO_NET_CTRL_VLAN       2
+ #define VIRTIO_NET_CTRL_VLAN_ADD             0
+ #define VIRTIO_NET_CTRL_VLAN_DEL             1
+
+/*
+ * Control link announce acknowledgement
+ *
+ * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
+ * driver has recevied the notification; device would clear the
+ * VIRTIO_NET_S_ANNOUNCE bit in the status field after it receives
+ * this command.
+ */
+#define VIRTIO_NET_CTRL_ANNOUNCE       3
+ #define VIRTIO_NET_CTRL_ANNOUNCE_ACK         0
+
+/*
+ * Control Receive Flow Steering
+ *
+ * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET
+ * enables Receive Flow Steering, specifying the number of the transmit and
+ * receive queues that will be used. After the command is consumed and acked by
+ * the device, the device will not steer new packets on receive virtqueues
+ * other than specified nor read from transmit virtqueues other than specified.
+ * Accordingly, driver should not transmit new packets  on virtqueues other than
+ * specified.
+ */
+struct virtio_net_ctrl_mq {
+	__virtio16 virtqueue_pairs;
+};
+
+#define VIRTIO_NET_CTRL_MQ   4
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET        0
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN        1
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000
+
+#endif /* _LINUX_VIRTIO_NET_H */
diff --git a/include/standard-headers/linux/virtio_pci.h b/include/standard-headers/linux/virtio_pci.h
new file mode 100644
index 0000000000..ecdc133d59
--- /dev/null
+++ b/include/standard-headers/linux/virtio_pci.h
@@ -0,0 +1,193 @@
+/*
+ * Virtio PCI driver
+ *
+ * This module allows virtio devices to be used over a virtual PCI device.
+ * This can be used with QEMU based VMMs like KVM or Xen.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors:
+ *  Anthony Liguori  <aliguori@us.ibm.com>
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LINUX_VIRTIO_PCI_H
+#define _LINUX_VIRTIO_PCI_H
+
+#include "standard-headers/linux/types.h"
+
+#ifndef VIRTIO_PCI_NO_LEGACY
+
+/* A 32-bit r/o bitmask of the features supported by the host */
+#define VIRTIO_PCI_HOST_FEATURES	0
+
+/* A 32-bit r/w bitmask of features activated by the guest */
+#define VIRTIO_PCI_GUEST_FEATURES	4
+
+/* A 32-bit r/w PFN for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_PFN		8
+
+/* A 16-bit r/o queue size for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_NUM		12
+
+/* A 16-bit r/w queue selector */
+#define VIRTIO_PCI_QUEUE_SEL		14
+
+/* A 16-bit r/w queue notifier */
+#define VIRTIO_PCI_QUEUE_NOTIFY		16
+
+/* An 8-bit device status register.  */
+#define VIRTIO_PCI_STATUS		18
+
+/* An 8-bit r/o interrupt status register.  Reading the value will return the
+ * current contents of the ISR and will also clear it.  This is effectively
+ * a read-and-acknowledge. */
+#define VIRTIO_PCI_ISR			19
+
+/* MSI-X registers: only enabled if MSI-X is enabled. */
+/* A 16-bit vector for configuration changes. */
+#define VIRTIO_MSI_CONFIG_VECTOR        20
+/* A 16-bit vector for selected queue notifications. */
+#define VIRTIO_MSI_QUEUE_VECTOR         22
+
+/* The remaining space is defined by each driver as the per-driver
+ * configuration space */
+#define VIRTIO_PCI_CONFIG_OFF(msix_enabled)	((msix_enabled) ? 24 : 20)
+/* Deprecated: please use VIRTIO_PCI_CONFIG_OFF instead */
+#define VIRTIO_PCI_CONFIG(dev)	VIRTIO_PCI_CONFIG_OFF((dev)->msix_enabled)
+
+/* Virtio ABI version, this must match exactly */
+#define VIRTIO_PCI_ABI_VERSION		0
+
+/* How many bits to shift physical queue address written to QUEUE_PFN.
+ * 12 is historical, and due to x86 page size. */
+#define VIRTIO_PCI_QUEUE_ADDR_SHIFT	12
+
+/* The alignment to use between consumer and producer parts of vring.
+ * x86 pagesize again. */
+#define VIRTIO_PCI_VRING_ALIGN		4096
+
+#endif /* VIRTIO_PCI_NO_LEGACY */
+
+/* The bit of the ISR which indicates a device configuration change. */
+#define VIRTIO_PCI_ISR_CONFIG		0x2
+/* Vector value used to disable MSI for queue */
+#define VIRTIO_MSI_NO_VECTOR            0xffff
+
+#ifndef VIRTIO_PCI_NO_MODERN
+
+/* IDs for different capabilities.  Must all exist. */
+
+/* Common configuration */
+#define VIRTIO_PCI_CAP_COMMON_CFG	1
+/* Notifications */
+#define VIRTIO_PCI_CAP_NOTIFY_CFG	2
+/* ISR access */
+#define VIRTIO_PCI_CAP_ISR_CFG		3
+/* Device specific configuration */
+#define VIRTIO_PCI_CAP_DEVICE_CFG	4
+/* PCI configuration access */
+#define VIRTIO_PCI_CAP_PCI_CFG		5
+
+/* This is the PCI capability header: */
+struct virtio_pci_cap {
+	uint8_t cap_vndr;		/* Generic PCI field: PCI_CAP_ID_VNDR */
+	uint8_t cap_next;		/* Generic PCI field: next ptr. */
+	uint8_t cap_len;		/* Generic PCI field: capability length */
+	uint8_t cfg_type;		/* Identifies the structure. */
+	uint8_t bar;		/* Where to find it. */
+	uint8_t padding[3];	/* Pad to full dword. */
+	uint32_t offset;		/* Offset within bar. */
+	uint32_t length;		/* Length of the structure, in bytes. */
+};
+
+struct virtio_pci_notify_cap {
+	struct virtio_pci_cap cap;
+	uint32_t notify_off_multiplier;	/* Multiplier for queue_notify_off. */
+};
+
+/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */
+struct virtio_pci_common_cfg {
+	/* About the whole device. */
+	uint32_t device_feature_select;	/* read-write */
+	uint32_t device_feature;		/* read-only */
+	uint32_t guest_feature_select;	/* read-write */
+	uint32_t guest_feature;		/* read-write */
+	uint16_t msix_config;		/* read-write */
+	uint16_t num_queues;		/* read-only */
+	uint8_t device_status;		/* read-write */
+	uint8_t config_generation;		/* read-only */
+
+	/* About a specific virtqueue. */
+	uint16_t queue_select;		/* read-write */
+	uint16_t queue_size;		/* read-write, power of 2. */
+	uint16_t queue_msix_vector;	/* read-write */
+	uint16_t queue_enable;		/* read-write */
+	uint16_t queue_notify_off;	/* read-only */
+	uint32_t queue_desc_lo;		/* read-write */
+	uint32_t queue_desc_hi;		/* read-write */
+	uint32_t queue_avail_lo;		/* read-write */
+	uint32_t queue_avail_hi;		/* read-write */
+	uint32_t queue_used_lo;		/* read-write */
+	uint32_t queue_used_hi;		/* read-write */
+};
+
+/* Macro versions of offsets for the Old Timers! */
+#define VIRTIO_PCI_CAP_VNDR		0
+#define VIRTIO_PCI_CAP_NEXT		1
+#define VIRTIO_PCI_CAP_LEN		2
+#define VIRTIO_PCI_CAP_CFG_TYPE		3
+#define VIRTIO_PCI_CAP_BAR		4
+#define VIRTIO_PCI_CAP_OFFSET		8
+#define VIRTIO_PCI_CAP_LENGTH		12
+
+#define VIRTIO_PCI_NOTIFY_CAP_MULT	16
+
+#define VIRTIO_PCI_COMMON_DFSELECT	0
+#define VIRTIO_PCI_COMMON_DF		4
+#define VIRTIO_PCI_COMMON_GFSELECT	8
+#define VIRTIO_PCI_COMMON_GF		12
+#define VIRTIO_PCI_COMMON_MSIX		16
+#define VIRTIO_PCI_COMMON_NUMQ		18
+#define VIRTIO_PCI_COMMON_STATUS	20
+#define VIRTIO_PCI_COMMON_CFGGENERATION	21
+#define VIRTIO_PCI_COMMON_Q_SELECT	22
+#define VIRTIO_PCI_COMMON_Q_SIZE	24
+#define VIRTIO_PCI_COMMON_Q_MSIX	26
+#define VIRTIO_PCI_COMMON_Q_ENABLE	28
+#define VIRTIO_PCI_COMMON_Q_NOFF	30
+#define VIRTIO_PCI_COMMON_Q_DESCLO	32
+#define VIRTIO_PCI_COMMON_Q_DESCHI	36
+#define VIRTIO_PCI_COMMON_Q_AVAILLO	40
+#define VIRTIO_PCI_COMMON_Q_AVAILHI	44
+#define VIRTIO_PCI_COMMON_Q_USEDLO	48
+#define VIRTIO_PCI_COMMON_Q_USEDHI	52
+
+#endif /* VIRTIO_PCI_NO_MODERN */
+
+#endif
diff --git a/include/hw/virtio/virtio_ring.h b/include/standard-headers/linux/virtio_ring.h
index 0b42e6eae5..cc647d61fc 100644
--- a/include/hw/virtio/virtio_ring.h
+++ b/include/standard-headers/linux/virtio_ring.h
@@ -1,10 +1,5 @@
 #ifndef _LINUX_VIRTIO_RING_H
 #define _LINUX_VIRTIO_RING_H
-/*
- * This file is copied from /usr/include/linux while converting __uNN types
- * to uXX_t, __inline__ to inline, and tab to spaces.
- * */
-
 /* An interface for efficient virtio implementation, currently for use by KVM
  * and lguest, but hopefully others soon.  Do NOT change this since it will
  * break existing servers and clients.
@@ -36,118 +31,127 @@
  * SUCH DAMAGE.
  *
  * Copyright Rusty Russell IBM Corporation 2007. */
+#include "standard-headers/linux/types.h"
+#include "standard-headers/linux/virtio_types.h"
 
 /* This marks a buffer as continuing via the next field. */
-#define VRING_DESC_F_NEXT   1
+#define VRING_DESC_F_NEXT	1
 /* This marks a buffer as write-only (otherwise read-only). */
-#define VRING_DESC_F_WRITE  2
+#define VRING_DESC_F_WRITE	2
 /* This means the buffer contains a list of buffer descriptors. */
-#define VRING_DESC_F_INDIRECT   4
+#define VRING_DESC_F_INDIRECT	4
 
 /* The Host uses this in used->flags to advise the Guest: don't kick me when
  * you add a buffer.  It's unreliable, so it's simply an optimization.  Guest
  * will still kick if it's out of buffers. */
-#define VRING_USED_F_NO_NOTIFY  1
+#define VRING_USED_F_NO_NOTIFY	1
 /* The Guest uses this in avail->flags to advise the Host: don't interrupt me
  * when you consume a buffer.  It's unreliable, so it's simply an
  * optimization.  */
-#define VRING_AVAIL_F_NO_INTERRUPT  1
+#define VRING_AVAIL_F_NO_INTERRUPT	1
 
 /* We support indirect buffer descriptors */
-#define VIRTIO_RING_F_INDIRECT_DESC 28
+#define VIRTIO_RING_F_INDIRECT_DESC	28
 
 /* The Guest publishes the used index for which it expects an interrupt
  * at the end of the avail ring. Host should ignore the avail->flags field. */
 /* The Host publishes the avail index for which it expects a kick
  * at the end of the used ring. Guest should ignore the used->flags field. */
-#define VIRTIO_RING_F_EVENT_IDX     29
+#define VIRTIO_RING_F_EVENT_IDX		29
 
 /* Virtio ring descriptors: 16 bytes.  These can chain together via "next". */
 struct vring_desc {
-    /* Address (guest-physical). */
-    uint64_t addr;
-    /* Length. */
-    uint32_t len;
-    /* The flags as indicated above. */
-    uint16_t flags;
-    /* We chain unused descriptors via this, too */
-    uint16_t next;
+	/* Address (guest-physical). */
+	__virtio64 addr;
+	/* Length. */
+	__virtio32 len;
+	/* The flags as indicated above. */
+	__virtio16 flags;
+	/* We chain unused descriptors via this, too */
+	__virtio16 next;
 };
 
 struct vring_avail {
-    uint16_t flags;
-    uint16_t idx;
-    uint16_t ring[];
+	__virtio16 flags;
+	__virtio16 idx;
+	__virtio16 ring[];
 };
 
 /* u32 is used here for ids for padding reasons. */
 struct vring_used_elem {
-    /* Index of start of used descriptor chain. */
-    uint32_t id;
-    /* Total length of the descriptor chain which was used (written to) */
-    uint32_t len;
+	/* Index of start of used descriptor chain. */
+	__virtio32 id;
+	/* Total length of the descriptor chain which was used (written to) */
+	__virtio32 len;
 };
 
 struct vring_used {
-    uint16_t flags;
-    uint16_t idx;
-    struct vring_used_elem ring[];
+	__virtio16 flags;
+	__virtio16 idx;
+	struct vring_used_elem ring[];
 };
 
 struct vring {
-    unsigned int num;
+	unsigned int num;
 
-    struct vring_desc *desc;
+	struct vring_desc *desc;
 
-    struct vring_avail *avail;
+	struct vring_avail *avail;
 
-    struct vring_used *used;
+	struct vring_used *used;
 };
 
+/* Alignment requirements for vring elements.
+ * When using pre-virtio 1.0 layout, these fall out naturally.
+ */
+#define VRING_AVAIL_ALIGN_SIZE 2
+#define VRING_USED_ALIGN_SIZE 4
+#define VRING_DESC_ALIGN_SIZE 16
+
 /* The standard layout for the ring is a continuous chunk of memory which looks
  * like this.  We assume num is a power of 2.
  *
  * struct vring
  * {
- *  // The actual descriptors (16 bytes each)
- *  struct vring_desc desc[num];
+ *	// The actual descriptors (16 bytes each)
+ *	struct vring_desc desc[num];
  *
- *  // A ring of available descriptor heads with free-running index.
- *  uint16_t avail_flags;
- *  uint16_t avail_idx;
- *  uint16_t available[num];
- *  uint16_t used_event_idx;
+ *	// A ring of available descriptor heads with free-running index.
+ *	__virtio16 avail_flags;
+ *	__virtio16 avail_idx;
+ *	__virtio16 available[num];
+ *	__virtio16 used_event_idx;
  *
- *  // Padding to the next align boundary.
- *  char pad[];
+ *	// Padding to the next align boundary.
+ *	char pad[];
  *
- *  // A ring of used descriptor heads with free-running index.
- *  uint16_t used_flags;
- *  uint16_t used_idx;
- *  struct vring_used_elem used[num];
- *  uint16_t avail_event_idx;
+ *	// A ring of used descriptor heads with free-running index.
+ *	__virtio16 used_flags;
+ *	__virtio16 used_idx;
+ *	struct vring_used_elem used[num];
+ *	__virtio16 avail_event_idx;
  * };
  */
 /* We publish the used event index at the end of the available ring, and vice
  * versa. They are at the end for backwards compatibility. */
 #define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])
-#define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num])
+#define vring_avail_event(vr) (*(__virtio16 *)&(vr)->used->ring[(vr)->num])
 
 static inline void vring_init(struct vring *vr, unsigned int num, void *p,
-                  unsigned long align)
+			      unsigned long align)
 {
-    vr->num = num;
-    vr->desc = p;
-    vr->avail = p + num*sizeof(struct vring_desc);
-    vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + sizeof(uint16_t)
-        + align - 1) & ~(align - 1));
+	vr->num = num;
+	vr->desc = p;
+	vr->avail = p + num*sizeof(struct vring_desc);
+	vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__virtio16)
+		+ align-1) & ~(align - 1));
 }
 
 static inline unsigned vring_size(unsigned int num, unsigned long align)
 {
-    return ((sizeof(struct vring_desc) * num + sizeof(uint16_t) * (3 + num)
-         + align - 1) & ~(align - 1))
-        + sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * num;
+	return ((sizeof(struct vring_desc) * num + sizeof(__virtio16) * (3 + num)
+		 + align - 1) & ~(align - 1))
+		+ sizeof(__virtio16) * 3 + sizeof(struct vring_used_elem) * num;
 }
 
 /* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */
@@ -156,12 +160,12 @@ static inline unsigned vring_size(unsigned int num, unsigned long align)
  * should we trigger an event? */
 static inline int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)
 {
-    /* Note: Xen has similar logic for notification hold-off
-     * in include/xen/interface/io/ring.h with req_event and req_prod
-     * corresponding to event_idx + 1 and new_idx respectively.
-     * Note also that req_event and req_prod in Xen start at 1,
-     * event indexes in virtio start at 0. */
-    return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
+	/* Note: Xen has similar logic for notification hold-off
+	 * in include/xen/interface/io/ring.h with req_event and req_prod
+	 * corresponding to event_idx + 1 and new_idx respectively.
+	 * Note also that req_event and req_prod in Xen start at 1,
+	 * event indexes in virtio start at 0. */
+	return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
 }
 
 #endif /* _LINUX_VIRTIO_RING_H */
diff --git a/include/standard-headers/linux/virtio_rng.h b/include/standard-headers/linux/virtio_rng.h
new file mode 100644
index 0000000000..60fc798bde
--- /dev/null
+++ b/include/standard-headers/linux/virtio_rng.h
@@ -0,0 +1,8 @@
+#ifndef _LINUX_VIRTIO_RNG_H
+#define _LINUX_VIRTIO_RNG_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_config.h"
+
+#endif /* _LINUX_VIRTIO_RNG_H */
diff --git a/include/standard-headers/linux/virtio_scsi.h b/include/standard-headers/linux/virtio_scsi.h
new file mode 100644
index 0000000000..78ba9d3635
--- /dev/null
+++ b/include/standard-headers/linux/virtio_scsi.h
@@ -0,0 +1,164 @@
+/*
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LINUX_VIRTIO_SCSI_H
+#define _LINUX_VIRTIO_SCSI_H
+
+#include "standard-headers/linux/virtio_types.h"
+
+#define VIRTIO_SCSI_CDB_SIZE   32
+#define VIRTIO_SCSI_SENSE_SIZE 96
+
+/* SCSI command request, followed by data-out */
+struct virtio_scsi_cmd_req {
+	uint8_t lun[8];		/* Logical Unit Number */
+	__virtio64 tag;		/* Command identifier */
+	uint8_t task_attr;		/* Task attribute */
+	uint8_t prio;		/* SAM command priority field */
+	uint8_t crn;
+	uint8_t cdb[VIRTIO_SCSI_CDB_SIZE];
+} QEMU_PACKED;
+
+/* SCSI command request, followed by protection information */
+struct virtio_scsi_cmd_req_pi {
+	uint8_t lun[8];		/* Logical Unit Number */
+	__virtio64 tag;		/* Command identifier */
+	uint8_t task_attr;		/* Task attribute */
+	uint8_t prio;		/* SAM command priority field */
+	uint8_t crn;
+	__virtio32 pi_bytesout;	/* DataOUT PI Number of bytes */
+	__virtio32 pi_bytesin;		/* DataIN PI Number of bytes */
+	uint8_t cdb[VIRTIO_SCSI_CDB_SIZE];
+} QEMU_PACKED;
+
+/* Response, followed by sense data and data-in */
+struct virtio_scsi_cmd_resp {
+	__virtio32 sense_len;		/* Sense data length */
+	__virtio32 resid;		/* Residual bytes in data buffer */
+	__virtio16 status_qualifier;	/* Status qualifier */
+	uint8_t status;		/* Command completion status */
+	uint8_t response;		/* Response values */
+	uint8_t sense[VIRTIO_SCSI_SENSE_SIZE];
+} QEMU_PACKED;
+
+/* Task Management Request */
+struct virtio_scsi_ctrl_tmf_req {
+	__virtio32 type;
+	__virtio32 subtype;
+	uint8_t lun[8];
+	__virtio64 tag;
+} QEMU_PACKED;
+
+struct virtio_scsi_ctrl_tmf_resp {
+	uint8_t response;
+} QEMU_PACKED;
+
+/* Asynchronous notification query/subscription */
+struct virtio_scsi_ctrl_an_req {
+	__virtio32 type;
+	uint8_t lun[8];
+	__virtio32 event_requested;
+} QEMU_PACKED;
+
+struct virtio_scsi_ctrl_an_resp {
+	__virtio32 event_actual;
+	uint8_t response;
+} QEMU_PACKED;
+
+struct virtio_scsi_event {
+	__virtio32 event;
+	uint8_t lun[8];
+	__virtio32 reason;
+} QEMU_PACKED;
+
+struct virtio_scsi_config {
+	uint32_t num_queues;
+	uint32_t seg_max;
+	uint32_t max_sectors;
+	uint32_t cmd_per_lun;
+	uint32_t event_info_size;
+	uint32_t sense_size;
+	uint32_t cdb_size;
+	uint16_t max_channel;
+	uint16_t max_target;
+	uint32_t max_lun;
+} QEMU_PACKED;
+
+/* Feature Bits */
+#define VIRTIO_SCSI_F_INOUT                    0
+#define VIRTIO_SCSI_F_HOTPLUG                  1
+#define VIRTIO_SCSI_F_CHANGE                   2
+#define VIRTIO_SCSI_F_T10_PI                   3
+
+/* Response codes */
+#define VIRTIO_SCSI_S_OK                       0
+#define VIRTIO_SCSI_S_OVERRUN                  1
+#define VIRTIO_SCSI_S_ABORTED                  2
+#define VIRTIO_SCSI_S_BAD_TARGET               3
+#define VIRTIO_SCSI_S_RESET                    4
+#define VIRTIO_SCSI_S_BUSY                     5
+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE        6
+#define VIRTIO_SCSI_S_TARGET_FAILURE           7
+#define VIRTIO_SCSI_S_NEXUS_FAILURE            8
+#define VIRTIO_SCSI_S_FAILURE                  9
+#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED       10
+#define VIRTIO_SCSI_S_FUNCTION_REJECTED        11
+#define VIRTIO_SCSI_S_INCORRECT_LUN            12
+
+/* Controlq type codes.  */
+#define VIRTIO_SCSI_T_TMF                      0
+#define VIRTIO_SCSI_T_AN_QUERY                 1
+#define VIRTIO_SCSI_T_AN_SUBSCRIBE             2
+
+/* Valid TMF subtypes.  */
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK           0
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET       1
+#define VIRTIO_SCSI_T_TMF_CLEAR_ACA            2
+#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET       3
+#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET      4
+#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET   5
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK           6
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET       7
+
+/* Events.  */
+#define VIRTIO_SCSI_T_EVENTS_MISSED            0x80000000
+#define VIRTIO_SCSI_T_NO_EVENT                 0
+#define VIRTIO_SCSI_T_TRANSPORT_RESET          1
+#define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
+#define VIRTIO_SCSI_T_PARAM_CHANGE             3
+
+/* Reasons of transport reset event */
+#define VIRTIO_SCSI_EVT_RESET_HARD             0
+#define VIRTIO_SCSI_EVT_RESET_RESCAN           1
+#define VIRTIO_SCSI_EVT_RESET_REMOVED          2
+
+#define VIRTIO_SCSI_S_SIMPLE                   0
+#define VIRTIO_SCSI_S_ORDERED                  1
+#define VIRTIO_SCSI_S_HEAD                     2
+#define VIRTIO_SCSI_S_ACA                      3
+
+
+#endif /* _LINUX_VIRTIO_SCSI_H */
diff --git a/include/standard-headers/linux/virtio_types.h b/include/standard-headers/linux/virtio_types.h
new file mode 100644
index 0000000000..fd0d3511ff
--- /dev/null
+++ b/include/standard-headers/linux/virtio_types.h
@@ -0,0 +1,46 @@
+#ifndef _LINUX_VIRTIO_TYPES_H
+#define _LINUX_VIRTIO_TYPES_H
+/* Type definitions for virtio implementations.
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ */
+#include "standard-headers/linux/types.h"
+
+/*
+ * __virtio{16,32,64} have the following meaning:
+ * - __u{16,32,64} for virtio devices in legacy mode, accessed in native endian
+ * - __le{16,32,64} for standard-compliant virtio devices
+ */
+
+typedef uint16_t  __virtio16;
+typedef uint32_t  __virtio32;
+typedef uint64_t  __virtio64;
+
+#endif /* _LINUX_VIRTIO_TYPES_H */
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 0c6264391e..7ca59b5070 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -63,8 +63,6 @@ DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type);
 
 /* device-hotplug */
 
-DriveInfo *add_init_drive(const char *opts);
-
 void qmp_change_blockdev(const char *device, const char *filename,
                          const char *format, Error **errp);
 void hmp_commit(Monitor *mon, const QDict *qdict);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 11040b476f..6e8509735a 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -156,11 +156,6 @@ extern int nb_option_roms;
 extern const char *prom_envs[MAX_PROM_ENVS];
 extern unsigned int nb_prom_envs;
 
-/* pci-hotplug */
-void hmp_pci_add(Monitor *mon, const QDict *qdict);
-int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo);
-void hmp_pci_del(Monitor *mon, const QDict *qdict);
-
 /* generic hotplug */
 void hmp_drive_add(Monitor *mon, const QDict *qdict);
 
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index 825f33bdc3..540ee25477 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -56,7 +56,7 @@ struct TPMBackend {
     QLIST_ENTRY(TPMBackend) list;
 };
 
-typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty);
+typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty, bool selftest_done);
 
 typedef struct TPMSizedBuffer {
     uint32_t size;
diff --git a/linux-headers/linux/virtio_config.h b/linux-headers/linux/virtio_config.h
index 75dc20ba6f..5590f7d4a6 100644
--- a/linux-headers/linux/virtio_config.h
+++ b/linux-headers/linux/virtio_config.h
@@ -1,57 +1 @@
-#ifndef _LINUX_VIRTIO_CONFIG_H
-#define _LINUX_VIRTIO_CONFIG_H
-/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
- * anyone can use the definitions to implement compatible drivers/servers.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of IBM nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE. */
-
-/* Virtio devices use a standardized configuration space to define their
- * features and pass configuration information, but each implementation can
- * store and access that space differently. */
-#include <linux/types.h>
-
-/* Status byte for guest to report progress, and synchronize features. */
-/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
-#define VIRTIO_CONFIG_S_ACKNOWLEDGE	1
-/* We have found a driver for the device. */
-#define VIRTIO_CONFIG_S_DRIVER		2
-/* Driver has used its parts of the config, and is happy */
-#define VIRTIO_CONFIG_S_DRIVER_OK	4
-/* We've given up on this device. */
-#define VIRTIO_CONFIG_S_FAILED		0x80
-
-/* Some virtio feature bits (currently bits 28 through 31) are reserved for the
- * transport being used (eg. virtio_ring), the rest are per-device feature
- * bits. */
-#define VIRTIO_TRANSPORT_F_START	28
-#define VIRTIO_TRANSPORT_F_END		32
-
-/* Do we get callbacks when the ring is completely used, even if we've
- * suppressed them? */
-#define VIRTIO_F_NOTIFY_ON_EMPTY	24
-
-/* Can the device handle any descriptor layout? */
-#define VIRTIO_F_ANY_LAYOUT		27
-
-#endif /* _LINUX_VIRTIO_CONFIG_H */
+#include "standard-headers/linux/virtio_config.h"
diff --git a/linux-headers/linux/virtio_ring.h b/linux-headers/linux/virtio_ring.h
index 1b333e2536..c6f0fb6cd9 100644
--- a/linux-headers/linux/virtio_ring.h
+++ b/linux-headers/linux/virtio_ring.h
@@ -1,163 +1 @@
-#ifndef _LINUX_VIRTIO_RING_H
-#define _LINUX_VIRTIO_RING_H
-/* An interface for efficient virtio implementation, currently for use by KVM
- * and lguest, but hopefully others soon.  Do NOT change this since it will
- * break existing servers and clients.
- *
- * This header is BSD licensed so anyone can use the definitions to implement
- * compatible drivers/servers.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of IBM nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Copyright Rusty Russell IBM Corporation 2007. */
-#include <linux/types.h>
-
-/* This marks a buffer as continuing via the next field. */
-#define VRING_DESC_F_NEXT	1
-/* This marks a buffer as write-only (otherwise read-only). */
-#define VRING_DESC_F_WRITE	2
-/* This means the buffer contains a list of buffer descriptors. */
-#define VRING_DESC_F_INDIRECT	4
-
-/* The Host uses this in used->flags to advise the Guest: don't kick me when
- * you add a buffer.  It's unreliable, so it's simply an optimization.  Guest
- * will still kick if it's out of buffers. */
-#define VRING_USED_F_NO_NOTIFY	1
-/* The Guest uses this in avail->flags to advise the Host: don't interrupt me
- * when you consume a buffer.  It's unreliable, so it's simply an
- * optimization.  */
-#define VRING_AVAIL_F_NO_INTERRUPT	1
-
-/* We support indirect buffer descriptors */
-#define VIRTIO_RING_F_INDIRECT_DESC	28
-
-/* The Guest publishes the used index for which it expects an interrupt
- * at the end of the avail ring. Host should ignore the avail->flags field. */
-/* The Host publishes the avail index for which it expects a kick
- * at the end of the used ring. Guest should ignore the used->flags field. */
-#define VIRTIO_RING_F_EVENT_IDX		29
-
-/* Virtio ring descriptors: 16 bytes.  These can chain together via "next". */
-struct vring_desc {
-	/* Address (guest-physical). */
-	__u64 addr;
-	/* Length. */
-	__u32 len;
-	/* The flags as indicated above. */
-	__u16 flags;
-	/* We chain unused descriptors via this, too */
-	__u16 next;
-};
-
-struct vring_avail {
-	__u16 flags;
-	__u16 idx;
-	__u16 ring[];
-};
-
-/* u32 is used here for ids for padding reasons. */
-struct vring_used_elem {
-	/* Index of start of used descriptor chain. */
-	__u32 id;
-	/* Total length of the descriptor chain which was used (written to) */
-	__u32 len;
-};
-
-struct vring_used {
-	__u16 flags;
-	__u16 idx;
-	struct vring_used_elem ring[];
-};
-
-struct vring {
-	unsigned int num;
-
-	struct vring_desc *desc;
-
-	struct vring_avail *avail;
-
-	struct vring_used *used;
-};
-
-/* The standard layout for the ring is a continuous chunk of memory which looks
- * like this.  We assume num is a power of 2.
- *
- * struct vring
- * {
- *	// The actual descriptors (16 bytes each)
- *	struct vring_desc desc[num];
- *
- *	// A ring of available descriptor heads with free-running index.
- *	__u16 avail_flags;
- *	__u16 avail_idx;
- *	__u16 available[num];
- *	__u16 used_event_idx;
- *
- *	// Padding to the next align boundary.
- *	char pad[];
- *
- *	// A ring of used descriptor heads with free-running index.
- *	__u16 used_flags;
- *	__u16 used_idx;
- *	struct vring_used_elem used[num];
- *	__u16 avail_event_idx;
- * };
- */
-/* We publish the used event index at the end of the available ring, and vice
- * versa. They are at the end for backwards compatibility. */
-#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])
-#define vring_avail_event(vr) (*(__u16 *)&(vr)->used->ring[(vr)->num])
-
-static __inline__ void vring_init(struct vring *vr, unsigned int num, void *p,
-			      unsigned long align)
-{
-	vr->num = num;
-	vr->desc = p;
-	vr->avail = p + num*sizeof(struct vring_desc);
-	vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__u16)
-		+ align-1) & ~(align - 1));
-}
-
-static __inline__ unsigned vring_size(unsigned int num, unsigned long align)
-{
-	return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num)
-		 + align - 1) & ~(align - 1))
-		+ sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num;
-}
-
-/* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */
-/* Assuming a given event_idx value from the other size, if
- * we have just incremented index from old to new_idx,
- * should we trigger an event? */
-static __inline__ int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old)
-{
-	/* Note: Xen has similar logic for notification hold-off
-	 * in include/xen/interface/io/ring.h with req_event and req_prod
-	 * corresponding to event_idx + 1 and new_idx respectively.
-	 * Note also that req_event and req_prod in Xen start at 1,
-	 * event indexes in virtio start at 0. */
-	return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old);
-}
-
-#endif /* _LINUX_VIRTIO_RING_H */
+#include "standard-headers/linux/virtio_ring.h"
diff --git a/net/vhost-user.c b/net/vhost-user.c
index 24e050c772..2435b0f826 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -18,7 +18,6 @@
 typedef struct VhostUserState {
     NetClientState nc;
     CharDriverState *chr;
-    bool vhostforce;
     VHostNetState *vhost_net;
 } VhostUserState;
 
@@ -51,7 +50,7 @@ static int vhost_user_start(VhostUserState *s)
     options.backend_type = VHOST_BACKEND_TYPE_USER;
     options.net_backend = &s->nc;
     options.opaque = s->chr;
-    options.force = s->vhostforce;
+    options.force = true;
 
     s->vhost_net = vhost_net_init(&options);
 
@@ -133,8 +132,7 @@ static void net_vhost_user_event(void *opaque, int event)
 }
 
 static int net_vhost_user_init(NetClientState *peer, const char *device,
-                               const char *name, CharDriverState *chr,
-                               bool vhostforce)
+                               const char *name, CharDriverState *chr)
 {
     NetClientState *nc;
     VhostUserState *s;
@@ -149,7 +147,6 @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
     /* We don't provide a receive callback */
     s->nc.receive_disabled = 1;
     s->chr = chr;
-    s->vhostforce = vhostforce;
 
     qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
 
@@ -230,7 +227,6 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
 {
     const NetdevVhostUserOptions *vhost_user_opts;
     CharDriverState *chr;
-    bool vhostforce;
 
     assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
     vhost_user_opts = opts->vhost_user;
@@ -247,12 +243,6 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
         return -1;
     }
 
-    /* vhostforce for non-MSIX */
-    if (vhost_user_opts->has_vhostforce) {
-        vhostforce = vhost_user_opts->vhostforce;
-    } else {
-        vhostforce = false;
-    }
 
-    return net_vhost_user_init(peer, "vhost_user", name, chr, vhostforce);
+    return net_vhost_user_init(peer, "vhost_user", name, chr);
 }
diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index c8e026d37e..f208ec9c51 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -28,6 +28,37 @@ if [ -z "$output" ]; then
     output="$PWD"
 fi
 
+cp_virtio() {
+    from=$1
+    to=$2
+    virtio=$(find "$from" -name '*virtio*h')
+    if [ "$virtio" ]; then
+        rm -rf "$to"
+        mkdir -p "$to"
+        for f in $virtio; do
+            if
+                grep '#include' "$f" | grep -v -e 'linux/virtio' \
+                                             -e 'linux/types' \
+                                             -e 'linux/if_ether' \
+                                             > /dev/null
+            then
+                echo "Unexpected #include in input file $f".
+                exit 2
+            fi
+
+            header=$(basename "$f");
+            sed -e 's/__u\([0-9][0-9]*\)/uint\1_t/g' \
+                -e 's/__le\([0-9][0-9]*\)/uint\1_t/g' \
+                -e 's/__be\([0-9][0-9]*\)/uint\1_t/g' \
+                -e 's/<linux\/\([^>]*\)>/"standard-headers\/linux\/\1"/' \
+                -e 's/__bitwise__//' \
+                -e 's/__attribute__((packed))/QEMU_PACKED/' \
+                -e 's/__inline__/inline/' \
+                "$f" > "$to/$header";
+        done
+    fi
+}
+
 # This will pick up non-directories too (eg "Kconfig") but we will
 # ignore them in the next loop.
 ARCHLIST=$(cd "$linux/arch" && echo *)
@@ -57,11 +88,13 @@ for arch in $ARCHLIST; do
     if [ $arch = powerpc ]; then
         cp "$tmpdir/include/asm/epapr_hcalls.h" "$output/linux-headers/asm-powerpc/"
     fi
+
+    cp_virtio "$tmpdir/include/asm" "$output/include/standard-headers/asm-$arch"
 done
 
 rm -rf "$output/linux-headers/linux"
 mkdir -p "$output/linux-headers/linux"
-for header in kvm.h kvm_para.h vfio.h vhost.h virtio_config.h virtio_ring.h \
+for header in kvm.h kvm_para.h vfio.h vhost.h \
               psci.h; do
     cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux"
 done
@@ -76,4 +109,21 @@ else
     cp "$linux/COPYING" "$output/linux-headers"
 fi
 
+cat <<EOF >$output/linux-headers/linux/virtio_config.h
+#include "standard-headers/linux/virtio_config.h"
+EOF
+cat <<EOF >$output/linux-headers/linux/virtio_ring.h
+#include "standard-headers/linux/virtio_ring.h"
+EOF
+
+cp_virtio "$tmpdir/include/linux/" "$output/include/standard-headers/linux"
+
+cat <<EOF >$output/include/standard-headers/linux/types.h
+#include <stdint.h>
+#include "qemu/compiler.h"
+EOF
+cat <<EOF >$output/include/standard-headers/linux/if_ether.h
+#define ETH_ALEN    6
+EOF
+
 rm -rf "$tmpdir"
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 5e347d04bd..8beff4c732 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -24,7 +24,6 @@ stub-obj-y += mon-printf.o
 stub-obj-y += mon-set-error.o
 stub-obj-y += monitor-init.o
 stub-obj-y += notify-event.o
-stub-obj-y += pci-drive-hot-add.o
 stub-obj-$(CONFIG_SPICE) += qemu-chr-open-spice.o
 stub-obj-y += qtest.o
 stub-obj-y += reset.o
diff --git a/stubs/pci-drive-hot-add.c b/stubs/pci-drive-hot-add.c
deleted file mode 100644
index 1d98145802..0000000000
--- a/stubs/pci-drive-hot-add.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <monitor/monitor.h>
-#include <sysemu/sysemu.h>
-#include <sysemu/blockdev.h>
-
-int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
-{
-    /* On non-x86 we don't do PCI hotplug */
-    monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
-    return -1;
-}
diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT
index 010d74603f..1693c3783b 100644
--- a/tests/acpi-test-data/pc/DSDT
+++ b/tests/acpi-test-data/pc/DSDT
Binary files differdiff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT
index 558e4c85b0..87c3e9fc02 100644
--- a/tests/acpi-test-data/pc/SSDT
+++ b/tests/acpi-test-data/pc/SSDT
Binary files differdiff --git a/tests/acpi-test-data/pc/SSDT.bridge b/tests/acpi-test-data/pc/SSDT.bridge
new file mode 100644
index 0000000000..325899a757
--- /dev/null
+++ b/tests/acpi-test-data/pc/SSDT.bridge
Binary files differdiff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT
index 8ac32efc03..e9ac11c38f 100644
--- a/tests/acpi-test-data/q35/DSDT
+++ b/tests/acpi-test-data/q35/DSDT
Binary files differdiff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT
index 2cb3e08bd4..6a5c0423b9 100644
--- a/tests/acpi-test-data/q35/SSDT
+++ b/tests/acpi-test-data/q35/SSDT
Binary files differdiff --git a/tests/acpi-test-data/q35/SSDT.bridge b/tests/acpi-test-data/q35/SSDT.bridge
new file mode 100644
index 0000000000..5fc83a0340
--- /dev/null
+++ b/tests/acpi-test-data/q35/SSDT.bridge
Binary files differdiff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 4d0fa848b1..735ac610be 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -40,6 +40,7 @@ typedef struct {
 
 typedef struct {
     const char *machine;
+    const char *variant;
     uint32_t rsdp_addr;
     AcpiRsdpDescriptor rsdp_table;
     AcpiRsdtDescriptorRev1 rsdt_table;
@@ -396,13 +397,14 @@ static void dump_aml_files(test_data *data, bool rebuild)
     int i;
 
     for (i = 0; i < data->tables->len; ++i) {
+        const char *ext = data->variant ? data->variant : "";
         sdt = &g_array_index(data->tables, AcpiSdtTable, i);
         g_assert(sdt->aml);
 
         if (rebuild) {
             uint32_t signature = cpu_to_le32(sdt->header.signature);
-            aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
-                                       (gchar *)&signature);
+            aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine,
+                                       (gchar *)&signature, ext);
             fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
                         S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
         } else {
@@ -509,7 +511,7 @@ static GArray *load_expected_aml(test_data *data)
 {
     int i;
     AcpiSdtTable *sdt;
-    gchar *aml_file;
+    gchar *aml_file = NULL;
     GError *error = NULL;
     gboolean ret;
 
@@ -517,6 +519,7 @@ static GArray *load_expected_aml(test_data *data)
     for (i = 0; i < data->tables->len; ++i) {
         AcpiSdtTable exp_sdt;
         uint32_t signature;
+        const char *ext = data->variant ? data->variant : "";
 
         sdt = &g_array_index(data->tables, AcpiSdtTable, i);
 
@@ -524,8 +527,15 @@ static GArray *load_expected_aml(test_data *data)
         exp_sdt.header.signature = sdt->header.signature;
 
         signature = cpu_to_le32(sdt->header.signature);
-        aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
-                                   (gchar *)&signature);
+
+try_again:
+        aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine,
+                                   (gchar *)&signature, ext);
+        if (data->variant && !g_file_test(aml_file, G_FILE_TEST_EXISTS)) {
+            g_free(aml_file);
+            ext = "";
+            goto try_again;
+        }
         exp_sdt.aml_file = aml_file;
         g_assert(g_file_test(aml_file, G_FILE_TEST_EXISTS));
         ret = g_file_get_contents(aml_file, &exp_sdt.aml,
@@ -778,6 +788,17 @@ static void test_acpi_piix4_tcg(void)
     free_test_data(&data);
 }
 
+static void test_acpi_piix4_tcg_bridge(void)
+{
+    test_data data;
+
+    memset(&data, 0, sizeof(data));
+    data.machine = MACHINE_PC;
+    data.variant = ".bridge";
+    test_acpi_one("-machine accel=tcg -device pci-bridge,chassis_nr=1", &data);
+    free_test_data(&data);
+}
+
 static void test_acpi_q35_tcg(void)
 {
     test_data data;
@@ -788,6 +809,18 @@ static void test_acpi_q35_tcg(void)
     free_test_data(&data);
 }
 
+static void test_acpi_q35_tcg_bridge(void)
+{
+    test_data data;
+
+    memset(&data, 0, sizeof(data));
+    data.machine = MACHINE_Q35;
+    data.variant = ".bridge";
+    test_acpi_one("-machine q35,accel=tcg -device pci-bridge,chassis_nr=1",
+                  &data);
+    free_test_data(&data);
+}
+
 int main(int argc, char *argv[])
 {
     const char *arch = qtest_get_arch();
@@ -805,7 +838,9 @@ int main(int argc, char *argv[])
 
     if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
         qtest_add_func("acpi/piix4/tcg", test_acpi_piix4_tcg);
+        qtest_add_func("acpi/piix4/tcg/bridge", test_acpi_piix4_tcg_bridge);
         qtest_add_func("acpi/q35/tcg", test_acpi_q35_tcg);
+        qtest_add_func("acpi/q35/tcg/bridge", test_acpi_q35_tcg_bridge);
     }
     ret = g_test_run();
     unlink(disk);
diff --git a/vl.c b/vl.c
index 4063c8e8c8..b47e223a49 100644
--- a/vl.c
+++ b/vl.c
@@ -2694,29 +2694,27 @@ static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size)
         uint64_t slots;
 
         sz = qemu_opt_get_size(opts, "maxmem", 0);
+        slots = qemu_opt_get_number(opts, "slots", 0);
         if (sz < ram_size) {
-            error_report("invalid -m option value: maxmem "
-                    "(0x%" PRIx64 ") <= initial memory (0x"
-                    RAM_ADDR_FMT ")", sz, ram_size);
+            error_report("invalid value of -m option maxmem: "
+                         "maximum memory size (0x%" PRIx64 ") must be at least "
+                         "the initial memory size (0x" RAM_ADDR_FMT ")",
+                         sz, ram_size);
             exit(EXIT_FAILURE);
-        }
-
-        slots = qemu_opt_get_number(opts, "slots", 0);
-        if ((sz > ram_size) && !slots) {
-            error_report("invalid -m option value: maxmem "
-                    "(0x%" PRIx64 ") more than initial memory (0x"
-                    RAM_ADDR_FMT ") but no hotplug slots where "
-                    "specified", sz, ram_size);
+        } else if (sz > ram_size) {
+            if (!slots) {
+                error_report("invalid value of -m option: maxmem was "
+                             "specified, but no hotplug slots were specified");
+                exit(EXIT_FAILURE);
+            }
+        } else if (slots) {
+            error_report("invalid value of -m option maxmem: "
+                         "memory slots were specified but maximum memory size "
+                         "(0x%" PRIx64 ") is equal to the initial memory size "
+                         "(0x" RAM_ADDR_FMT ")", sz, ram_size);
             exit(EXIT_FAILURE);
         }
 
-        if ((sz <= ram_size) && slots) {
-            error_report("invalid -m option value:  %"
-                    PRIu64 " hotplug slots where specified but "
-                    "maxmem (0x%" PRIx64 ") <= initial memory (0x"
-                    RAM_ADDR_FMT ")", slots, sz, ram_size);
-            exit(EXIT_FAILURE);
-        }
         *maxram_size = sz;
         *ram_slots = slots;
     } else if ((!maxmem_str && slots_str) ||