Merge remote-tracking branch 'remotes/sstabellini/tags/xen-20160614-tag' into staging

Xen 2016/06/14

# gpg: Signature made Tue 14 Jun 2016 16:01:52 BST
# gpg:                using RSA key 0x894F8F4870E1AE90
# gpg: Good signature from "Stefano Stabellini <stefano.stabellini@eu.citrix.com>"
# Primary key fingerprint: D04E 33AB A51F 67BA 07D3  0AEA 894F 8F48 70E1 AE90

* remotes/sstabellini/tags/xen-20160614-tag:
  xen: Clean up includes
  xen/blkif: avoid double access to any shared ring request fields

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
index 96dd994..2449483 100644
--- a/default-configs/aarch64-softmmu.mak
+++ b/default-configs/aarch64-softmmu.mak
@@ -3,4 +3,7 @@
 # We support all the 32 bit boards so need all their config
 include arm-softmmu.mak
 
+CONFIG_AUX=y
+CONFIG_DDC=y
+CONFIG_DPCD=y
 CONFIG_XLNX_ZYNQMP=y
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index d4eb141..fea911e 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -1351,7 +1351,7 @@
     n8x0_dss_setup(s);
     n8x0_cbus_setup(s);
     n8x0_uart_setup(s);
-    if (usb_enabled()) {
+    if (machine_usb(machine)) {
         n8x0_usb_setup(s);
     }
 
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index e41a7c9..cb55704 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -2165,10 +2165,8 @@
         s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
     }
 
-    if (usb_enabled()) {
-        sysbus_create_simple("sysbus-ohci", 0x4c000000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
-    }
+    sysbus_create_simple("sysbus-ohci", 0x4c000000,
+                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
 
     s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
     s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
@@ -2298,10 +2296,8 @@
         s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
     }
 
-    if (usb_enabled()) {
-        sysbus_create_simple("sysbus-ohci", 0x4c000000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
-    }
+    sysbus_create_simple("sysbus-ohci", 0x4c000000,
+                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
 
     s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
     s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index 7d0aa6f..8eafcca 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -254,7 +254,7 @@
         sysbus_connect_irq(busdev, 2, pic[50]);
         sysbus_connect_irq(busdev, 3, pic[51]);
         pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
-        if (usb_enabled()) {
+        if (machine_usb(machine)) {
             pci_create_simple(pci_bus, -1, "pci-ohci");
         }
         n = drive_get_max_bus(IF_SCSI);
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 20dd356..8ae5392 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -276,7 +276,7 @@
             pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL);
         }
     }
-    if (usb_enabled()) {
+    if (machine_usb(machine)) {
         pci_create_simple(pci_bus, -1, "pci-ohci");
     }
     n = drive_get_max_bus(IF_SCSI);
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 735ab86..1fa0581 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -538,6 +538,10 @@
         gicc->arm_mpidr = armcpu->mp_affinity;
         gicc->uid = i;
         gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED);
+
+        if (armcpu->has_pmu) {
+            gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
+        }
     }
 
     if (guest_info->gic_version == 3) {
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 73113cf..c5c125e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -42,6 +42,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
 #include "hw/boards.h"
+#include "hw/compat.h"
 #include "hw/loader.h"
 #include "exec/address-spaces.h"
 #include "qemu/bitops.h"
@@ -98,6 +99,36 @@
 #define VIRT_MACHINE_CLASS(klass) \
     OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE)
 
+
+#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
+    static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
+                                                    void *data) \
+    { \
+        MachineClass *mc = MACHINE_CLASS(oc); \
+        virt_machine_##major##_##minor##_options(mc); \
+        mc->desc = "QEMU " # major "." # minor " ARM Virtual Machine"; \
+        if (latest) { \
+            mc->alias = "virt"; \
+        } \
+    } \
+    static const TypeInfo machvirt_##major##_##minor##_info = { \
+        .name = MACHINE_TYPE_NAME("virt-" # major "." # minor), \
+        .parent = TYPE_VIRT_MACHINE, \
+        .instance_init = virt_##major##_##minor##_instance_init, \
+        .class_init = virt_##major##_##minor##_class_init, \
+    }; \
+    static void machvirt_machine_##major##_##minor##_init(void) \
+    { \
+        type_register_static(&machvirt_##major##_##minor##_info); \
+    } \
+    type_init(machvirt_machine_##major##_##minor##_init);
+
+#define DEFINE_VIRT_MACHINE_AS_LATEST(major, minor) \
+    DEFINE_VIRT_MACHINE_LATEST(major, minor, true)
+#define DEFINE_VIRT_MACHINE(major, minor) \
+    DEFINE_VIRT_MACHINE_LATEST(major, minor, false)
+
+
 /* RAM limit in GB. Since VIRT_MEM starts at the 1GB mark, this means
  * RAM can go up to the 256GB mark, leaving 256GB of the physical
  * address space unallocated and free for future use between 256G and 512G.
@@ -436,6 +467,37 @@
     qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle);
 }
 
+static void fdt_add_pmu_nodes(const VirtBoardInfo *vbi, int gictype)
+{
+    CPUState *cpu;
+    ARMCPU *armcpu;
+    uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
+
+    CPU_FOREACH(cpu) {
+        armcpu = ARM_CPU(cpu);
+        if (!armcpu->has_pmu ||
+            !kvm_arm_pmu_create(cpu, PPI(VIRTUAL_PMU_IRQ))) {
+            return;
+        }
+    }
+
+    if (gictype == 2) {
+        irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
+                             GIC_FDT_IRQ_PPI_CPU_WIDTH,
+                             (1 << vbi->smp_cpus) - 1);
+    }
+
+    armcpu = ARM_CPU(qemu_get_cpu(0));
+    qemu_fdt_add_subnode(vbi->fdt, "/pmu");
+    if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
+        const char compat[] = "arm,armv8-pmuv3";
+        qemu_fdt_setprop(vbi->fdt, "/pmu", "compatible",
+                         compat, sizeof(compat));
+        qemu_fdt_setprop_cells(vbi->fdt, "/pmu", "interrupts",
+                               GIC_FDT_IRQ_TYPE_PPI, VIRTUAL_PMU_IRQ, irqflags);
+    }
+}
+
 static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
 {
     int i;
@@ -1259,6 +1321,8 @@
 
     create_gic(vbi, pic, gic_version, vms->secure);
 
+    fdt_add_pmu_nodes(vbi, gic_version);
+
     create_uart(vbi, pic, VIRT_UART, sysmem, serial_hds[0]);
 
     if (vms->secure) {
@@ -1387,7 +1451,13 @@
     .class_init    = virt_machine_class_init,
 };
 
-static void virt_2_6_instance_init(Object *obj)
+static void machvirt_machine_init(void)
+{
+    type_register_static(&virt_machine_info);
+}
+type_init(machvirt_machine_init);
+
+static void virt_2_7_instance_init(Object *obj)
 {
     VirtMachineState *vms = VIRT_MACHINE(obj);
 
@@ -1420,25 +1490,22 @@
                                     "Valid values are 2, 3 and host", NULL);
 }
 
-static void virt_2_6_class_init(ObjectClass *oc, void *data)
+static void virt_machine_2_7_options(MachineClass *mc)
 {
-    MachineClass *mc = MACHINE_CLASS(oc);
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(2, 7)
 
-    mc->desc = "QEMU 2.6 ARM Virtual Machine";
-    mc->alias = "virt";
+#define VIRT_COMPAT_2_6 \
+    HW_COMPAT_2_6
+
+static void virt_2_6_instance_init(Object *obj)
+{
+    virt_2_7_instance_init(obj);
 }
 
-static const TypeInfo machvirt_info = {
-    .name = MACHINE_TYPE_NAME("virt-2.6"),
-    .parent = TYPE_VIRT_MACHINE,
-    .instance_init = virt_2_6_instance_init,
-    .class_init = virt_2_6_class_init,
-};
-
-static void machvirt_machine_init(void)
+static void virt_machine_2_6_options(MachineClass *mc)
 {
-    type_register_static(&virt_machine_info);
-    type_register_static(&machvirt_info);
+    virt_machine_2_7_options(mc);
+    SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_6);
 }
-
-type_init(machvirt_machine_init);
+DEFINE_VIRT_MACHINE(2, 6)
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 308d677..23c7199 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -38,6 +38,12 @@
 #define SATA_ADDR           0xFD0C0000
 #define SATA_NUM_PORTS      2
 
+#define DP_ADDR             0xfd4a0000
+#define DP_IRQ              113
+
+#define DPDMA_ADDR          0xfd4c0000
+#define DPDMA_IRQ           116
+
 static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
     0xFF0B0000, 0xFF0C0000, 0xFF0D0000, 0xFF0E0000,
 };
@@ -165,6 +171,12 @@
                           TYPE_XILINX_SPIPS);
         qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
     }
+
+    object_initialize(&s->dp, sizeof(s->dp), TYPE_XLNX_DP);
+    qdev_set_parent_bus(DEVICE(&s->dp), sysbus_get_default());
+
+    object_initialize(&s->dpdma, sizeof(s->dpdma), TYPE_XLNX_DPDMA);
+    qdev_set_parent_bus(DEVICE(&s->dpdma), sysbus_get_default());
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -388,8 +400,26 @@
         object_property_add_alias(OBJECT(s), bus_name,
                                   OBJECT(&s->spi[i]), "spi0",
                                   &error_abort);
-	g_free(bus_name);
+        g_free(bus_name);
     }
+
+    object_property_set_bool(OBJECT(&s->dp), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->dp), 0, DP_ADDR);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->dp), 0, gic_spi[DP_IRQ]);
+
+    object_property_set_bool(OBJECT(&s->dpdma), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    object_property_set_link(OBJECT(&s->dp), OBJECT(&s->dpdma), "dpdma",
+                             &error_abort);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->dpdma), 0, DPDMA_ADDR);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->dpdma), 0, gic_spi[DPDMA_IRQ]);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 0a05a52..dcc00f8 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -35,6 +35,7 @@
 #include "qemu/error-report.h"
 #include "hw/hotplug.h"
 #include "hw/boards.h"
+#include "hw/sysbus.h"
 #include "qapi-event.h"
 
 int qdev_hotplug = 0;
@@ -140,6 +141,12 @@
     }
 
     if (!bus) {
+        /* Assert that the device really is a SysBusDevice before
+         * we put it onto the sysbus. Non-sysbus devices which aren't
+         * being put onto a bus should be created with object_new(TYPE_FOO),
+         * not qdev_create(NULL, TYPE_FOO).
+         */
+        g_assert(object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE));
         bus = sysbus_get_default();
     }
 
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index d99780e..063889b 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -43,3 +43,5 @@
 virtio-gpu.o-libs += $(VIRGL_LIBS)
 virtio-gpu-3d.o-cflags := $(VIRGL_CFLAGS)
 virtio-gpu-3d.o-libs += $(VIRGL_LIBS)
+obj-$(CONFIG_DPCD) += dpcd.o
+obj-$(CONFIG_XLNX_ZYNQMP) += xlnx_dp.o
diff --git a/hw/display/dpcd.c b/hw/display/dpcd.c
new file mode 100644
index 0000000..5a36855
--- /dev/null
+++ b/hw/display/dpcd.c
@@ -0,0 +1,173 @@
+/*
+ * dpcd.c
+ *
+ *  Copyright (C) 2015 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.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/>.
+ *
+ */
+
+/*
+ * This is a simple AUX slave which emulates a connected screen.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/misc/aux.h"
+#include "hw/display/dpcd.h"
+
+#ifndef DEBUG_DPCD
+#define DEBUG_DPCD 0
+#endif
+
+#define DPRINTF(fmt, ...) do {                                                 \
+    if (DEBUG_DPCD) {                                                          \
+        qemu_log("dpcd: " fmt, ## __VA_ARGS__);                                \
+    }                                                                          \
+} while (0);
+
+#define DPCD_READABLE_AREA                      0x600
+
+struct DPCDState {
+    /*< private >*/
+    AUXSlave parent_obj;
+
+    /*< public >*/
+    /*
+     * The DCPD is 0x7FFFF length but read as 0 after offset 0x5FF.
+     */
+    uint8_t dpcd_info[DPCD_READABLE_AREA];
+
+    MemoryRegion iomem;
+};
+
+static uint64_t dpcd_read(void *opaque, hwaddr offset, unsigned size)
+{
+    uint8_t ret;
+    DPCDState *e = DPCD(opaque);
+
+    if (offset < DPCD_READABLE_AREA) {
+        ret = e->dpcd_info[offset];
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
+                                       offset);
+        ret = 0;
+    }
+
+    DPRINTF("read 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", ret, offset);
+    return ret;
+}
+
+static void dpcd_write(void *opaque, hwaddr offset, uint64_t value,
+                       unsigned size)
+{
+    DPCDState *e = DPCD(opaque);
+
+    DPRINTF("write 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", (uint8_t)value, offset);
+
+    if (offset < DPCD_READABLE_AREA) {
+        e->dpcd_info[offset] = value;
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
+                                       offset);
+    }
+}
+
+static const MemoryRegionOps aux_ops = {
+    .read = dpcd_read,
+    .write = dpcd_write,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static void dpcd_reset(DeviceState *dev)
+{
+    DPCDState *s = DPCD(dev);
+
+    memset(&(s->dpcd_info), 0, sizeof(s->dpcd_info));
+
+    s->dpcd_info[DPCD_REVISION] = DPCD_REV_1_0;
+    s->dpcd_info[DPCD_MAX_LINK_RATE] = DPCD_5_4GBPS;
+    s->dpcd_info[DPCD_MAX_LANE_COUNT] = DPCD_FOUR_LANES;
+    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_0] = DPCD_EDID_PRESENT;
+    /* buffer size */
+    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_1] = 0xFF;
+
+    s->dpcd_info[DPCD_LANE0_1_STATUS] = DPCD_LANE0_CR_DONE
+                                      | DPCD_LANE0_CHANNEL_EQ_DONE
+                                      | DPCD_LANE0_SYMBOL_LOCKED
+                                      | DPCD_LANE1_CR_DONE
+                                      | DPCD_LANE1_CHANNEL_EQ_DONE
+                                      | DPCD_LANE1_SYMBOL_LOCKED;
+    s->dpcd_info[DPCD_LANE2_3_STATUS] = DPCD_LANE2_CR_DONE
+                                      | DPCD_LANE2_CHANNEL_EQ_DONE
+                                      | DPCD_LANE2_SYMBOL_LOCKED
+                                      | DPCD_LANE3_CR_DONE
+                                      | DPCD_LANE3_CHANNEL_EQ_DONE
+                                      | DPCD_LANE3_SYMBOL_LOCKED;
+
+    s->dpcd_info[DPCD_LANE_ALIGN_STATUS_UPDATED] = DPCD_INTERLANE_ALIGN_DONE;
+    s->dpcd_info[DPCD_SINK_STATUS] = DPCD_RECEIVE_PORT_0_STATUS;
+}
+
+static void dpcd_init(Object *obj)
+{
+    DPCDState *s = DPCD(obj);
+
+    memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x7FFFF);
+    aux_init_mmio(AUX_SLAVE(obj), &s->iomem);
+}
+
+static const VMStateDescription vmstate_dpcd = {
+    .name = TYPE_DPCD,
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8_ARRAY_V(dpcd_info, DPCDState, DPCD_READABLE_AREA, 0),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void dpcd_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->reset = dpcd_reset;
+    dc->vmsd = &vmstate_dpcd;
+}
+
+static const TypeInfo dpcd_info = {
+    .name          = TYPE_DPCD,
+    .parent        = TYPE_AUX_SLAVE,
+    .instance_size = sizeof(DPCDState),
+    .class_init    = dpcd_class_init,
+    .instance_init = dpcd_init,
+};
+
+static void dpcd_register_types(void)
+{
+    type_register_static(&dpcd_info);
+}
+
+type_init(dpcd_register_types)
diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
new file mode 100644
index 0000000..be53b75
--- /dev/null
+++ b/hw/display/xlnx_dp.c
@@ -0,0 +1,1336 @@
+/*
+ * xlnx_dp.c
+ *
+ *  Copyright (C) 2015 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.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 "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/display/xlnx_dp.h"
+
+#ifndef DEBUG_DP
+#define DEBUG_DP 0
+#endif
+
+#define DPRINTF(fmt, ...) do {                                                 \
+    if (DEBUG_DP) {                                                            \
+        qemu_log("xlnx_dp: " fmt , ## __VA_ARGS__);                            \
+    }                                                                          \
+} while (0);
+
+/*
+ * Register offset for DP.
+ */
+#define DP_LINK_BW_SET                      (0x0000 >> 2)
+#define DP_LANE_COUNT_SET                   (0x0004 >> 2)
+#define DP_ENHANCED_FRAME_EN                (0x0008 >> 2)
+#define DP_TRAINING_PATTERN_SET             (0x000C >> 2)
+#define DP_LINK_QUAL_PATTERN_SET            (0x0010 >> 2)
+#define DP_SCRAMBLING_DISABLE               (0x0014 >> 2)
+#define DP_DOWNSPREAD_CTRL                  (0x0018 >> 2)
+#define DP_SOFTWARE_RESET                   (0x001C >> 2)
+#define DP_TRANSMITTER_ENABLE               (0x0080 >> 2)
+#define DP_MAIN_STREAM_ENABLE               (0x0084 >> 2)
+#define DP_FORCE_SCRAMBLER_RESET            (0x00C0 >> 2)
+#define DP_VERSION_REGISTER                 (0x00F8 >> 2)
+#define DP_CORE_ID                          (0x00FC >> 2)
+
+#define DP_AUX_COMMAND_REGISTER             (0x0100 >> 2)
+#define AUX_ADDR_ONLY_MASK                  (0x1000)
+#define AUX_COMMAND_MASK                    (0x0F00)
+#define AUX_COMMAND_SHIFT                   (8)
+#define AUX_COMMAND_NBYTES                  (0x000F)
+
+#define DP_AUX_WRITE_FIFO                   (0x0104 >> 2)
+#define DP_AUX_ADDRESS                      (0x0108 >> 2)
+#define DP_AUX_CLOCK_DIVIDER                (0x010C >> 2)
+#define DP_TX_USER_FIFO_OVERFLOW            (0x0110 >> 2)
+#define DP_INTERRUPT_SIGNAL_STATE           (0x0130 >> 2)
+#define DP_AUX_REPLY_DATA                   (0x0134 >> 2)
+#define DP_AUX_REPLY_CODE                   (0x0138 >> 2)
+#define DP_AUX_REPLY_COUNT                  (0x013C >> 2)
+#define DP_REPLY_DATA_COUNT                 (0x0148 >> 2)
+#define DP_REPLY_STATUS                     (0x014C >> 2)
+#define DP_HPD_DURATION                     (0x0150 >> 2)
+#define DP_MAIN_STREAM_HTOTAL               (0x0180 >> 2)
+#define DP_MAIN_STREAM_VTOTAL               (0x0184 >> 2)
+#define DP_MAIN_STREAM_POLARITY             (0x0188 >> 2)
+#define DP_MAIN_STREAM_HSWIDTH              (0x018C >> 2)
+#define DP_MAIN_STREAM_VSWIDTH              (0x0190 >> 2)
+#define DP_MAIN_STREAM_HRES                 (0x0194 >> 2)
+#define DP_MAIN_STREAM_VRES                 (0x0198 >> 2)
+#define DP_MAIN_STREAM_HSTART               (0x019C >> 2)
+#define DP_MAIN_STREAM_VSTART               (0x01A0 >> 2)
+#define DP_MAIN_STREAM_MISC0                (0x01A4 >> 2)
+#define DP_MAIN_STREAM_MISC1                (0x01A8 >> 2)
+#define DP_MAIN_STREAM_M_VID                (0x01AC >> 2)
+#define DP_MSA_TRANSFER_UNIT_SIZE           (0x01B0 >> 2)
+#define DP_MAIN_STREAM_N_VID                (0x01B4 >> 2)
+#define DP_USER_DATA_COUNT_PER_LANE         (0x01BC >> 2)
+#define DP_MIN_BYTES_PER_TU                 (0x01C4 >> 2)
+#define DP_FRAC_BYTES_PER_TU                (0x01C8 >> 2)
+#define DP_INIT_WAIT                        (0x01CC >> 2)
+#define DP_PHY_RESET                        (0x0200 >> 2)
+#define DP_PHY_VOLTAGE_DIFF_LANE_0          (0x0220 >> 2)
+#define DP_PHY_VOLTAGE_DIFF_LANE_1          (0x0224 >> 2)
+#define DP_TRANSMIT_PRBS7                   (0x0230 >> 2)
+#define DP_PHY_CLOCK_SELECT                 (0x0234 >> 2)
+#define DP_TX_PHY_POWER_DOWN                (0x0238 >> 2)
+#define DP_PHY_PRECURSOR_LANE_0             (0x023C >> 2)
+#define DP_PHY_PRECURSOR_LANE_1             (0x0240 >> 2)
+#define DP_PHY_POSTCURSOR_LANE_0            (0x024C >> 2)
+#define DP_PHY_POSTCURSOR_LANE_1            (0x0250 >> 2)
+#define DP_PHY_STATUS                       (0x0280 >> 2)
+
+#define DP_TX_AUDIO_CONTROL                 (0x0300 >> 2)
+#define DP_TX_AUD_CTRL                      (1)
+
+#define DP_TX_AUDIO_CHANNELS                (0x0304 >> 2)
+#define DP_TX_AUDIO_INFO_DATA(n)            ((0x0308 + 4 * n) >> 2)
+#define DP_TX_M_AUD                         (0x0328 >> 2)
+#define DP_TX_N_AUD                         (0x032C >> 2)
+#define DP_TX_AUDIO_EXT_DATA(n)             ((0x0330 + 4 * n) >> 2)
+#define DP_INT_STATUS                       (0x03A0 >> 2)
+#define DP_INT_MASK                         (0x03A4 >> 2)
+#define DP_INT_EN                           (0x03A8 >> 2)
+#define DP_INT_DS                           (0x03AC >> 2)
+
+/*
+ * Registers offset for Audio Video Buffer configuration.
+ */
+#define V_BLEND_OFFSET                      (0xA000)
+#define V_BLEND_BG_CLR_0                    (0x0000 >> 2)
+#define V_BLEND_BG_CLR_1                    (0x0004 >> 2)
+#define V_BLEND_BG_CLR_2                    (0x0008 >> 2)
+#define V_BLEND_SET_GLOBAL_ALPHA_REG        (0x000C >> 2)
+#define V_BLEND_OUTPUT_VID_FORMAT           (0x0014 >> 2)
+#define V_BLEND_LAYER0_CONTROL              (0x0018 >> 2)
+#define V_BLEND_LAYER1_CONTROL              (0x001C >> 2)
+
+#define V_BLEND_RGB2YCBCR_COEFF(n)          ((0x0020 + 4 * n) >> 2)
+#define V_BLEND_IN1CSC_COEFF(n)             ((0x0044 + 4 * n) >> 2)
+
+#define V_BLEND_LUMA_IN1CSC_OFFSET          (0x0068 >> 2)
+#define V_BLEND_CR_IN1CSC_OFFSET            (0x006C >> 2)
+#define V_BLEND_CB_IN1CSC_OFFSET            (0x0070 >> 2)
+#define V_BLEND_LUMA_OUTCSC_OFFSET          (0x0074 >> 2)
+#define V_BLEND_CR_OUTCSC_OFFSET            (0x0078 >> 2)
+#define V_BLEND_CB_OUTCSC_OFFSET            (0x007C >> 2)
+
+#define V_BLEND_IN2CSC_COEFF(n)             ((0x0080 + 4 * n) >> 2)
+
+#define V_BLEND_LUMA_IN2CSC_OFFSET          (0x00A4 >> 2)
+#define V_BLEND_CR_IN2CSC_OFFSET            (0x00A8 >> 2)
+#define V_BLEND_CB_IN2CSC_OFFSET            (0x00AC >> 2)
+#define V_BLEND_CHROMA_KEY_ENABLE           (0x01D0 >> 2)
+#define V_BLEND_CHROMA_KEY_COMP1            (0x01D4 >> 2)
+#define V_BLEND_CHROMA_KEY_COMP2            (0x01D8 >> 2)
+#define V_BLEND_CHROMA_KEY_COMP3            (0x01DC >> 2)
+
+/*
+ * Registers offset for Audio Video Buffer configuration.
+ */
+#define AV_BUF_MANAGER_OFFSET               (0xB000)
+#define AV_BUF_FORMAT                       (0x0000 >> 2)
+#define AV_BUF_NON_LIVE_LATENCY             (0x0008 >> 2)
+#define AV_CHBUF0                           (0x0010 >> 2)
+#define AV_CHBUF1                           (0x0014 >> 2)
+#define AV_CHBUF2                           (0x0018 >> 2)
+#define AV_CHBUF3                           (0x001C >> 2)
+#define AV_CHBUF4                           (0x0020 >> 2)
+#define AV_CHBUF5                           (0x0024 >> 2)
+#define AV_BUF_STC_CONTROL                  (0x002C >> 2)
+#define AV_BUF_STC_INIT_VALUE0              (0x0030 >> 2)
+#define AV_BUF_STC_INIT_VALUE1              (0x0034 >> 2)
+#define AV_BUF_STC_ADJ                      (0x0038 >> 2)
+#define AV_BUF_STC_VIDEO_VSYNC_TS_REG0      (0x003C >> 2)
+#define AV_BUF_STC_VIDEO_VSYNC_TS_REG1      (0x0040 >> 2)
+#define AV_BUF_STC_EXT_VSYNC_TS_REG0        (0x0044 >> 2)
+#define AV_BUF_STC_EXT_VSYNC_TS_REG1        (0x0048 >> 2)
+#define AV_BUF_STC_CUSTOM_EVENT_TS_REG0     (0x004C >> 2)
+#define AV_BUF_STC_CUSTOM_EVENT_TS_REG1     (0x0050 >> 2)
+#define AV_BUF_STC_CUSTOM_EVENT2_TS_REG0    (0x0054 >> 2)
+#define AV_BUF_STC_CUSTOM_EVENT2_TS_REG1    (0x0058 >> 2)
+#define AV_BUF_STC_SNAPSHOT0                (0x0060 >> 2)
+#define AV_BUF_STC_SNAPSHOT1                (0x0064 >> 2)
+#define AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT    (0x0070 >> 2)
+#define AV_BUF_HCOUNT_VCOUNT_INT0           (0x0074 >> 2)
+#define AV_BUF_HCOUNT_VCOUNT_INT1           (0x0078 >> 2)
+#define AV_BUF_DITHER_CONFIG                (0x007C >> 2)
+#define AV_BUF_DITHER_CONFIG_MAX            (0x008C >> 2)
+#define AV_BUF_DITHER_CONFIG_MIN            (0x0090 >> 2)
+#define AV_BUF_PATTERN_GEN_SELECT           (0x0100 >> 2)
+#define AV_BUF_AUD_VID_CLK_SOURCE           (0x0120 >> 2)
+#define AV_BUF_SRST_REG                     (0x0124 >> 2)
+#define AV_BUF_AUDIO_RDY_INTERVAL           (0x0128 >> 2)
+#define AV_BUF_AUDIO_CH_CONFIG              (0x012C >> 2)
+
+#define AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(n)((0x0200 + 4 * n) >> 2)
+
+#define AV_BUF_VIDEO_COMP_SCALE_FACTOR(n)   ((0x020C + 4 * n) >> 2)
+
+#define AV_BUF_LIVE_VIDEO_COMP_SF(n)        ((0x0218 + 4 * n) >> 2)
+
+#define AV_BUF_LIVE_VID_CONFIG              (0x0224 >> 2)
+
+#define AV_BUF_LIVE_GFX_COMP_SF(n)          ((0x0228 + 4 * n) >> 2)
+
+#define AV_BUF_LIVE_GFX_CONFIG              (0x0234 >> 2)
+
+#define AUDIO_MIXER_REGISTER_OFFSET         (0xC000)
+#define AUDIO_MIXER_VOLUME_CONTROL          (0x0000 >> 2)
+#define AUDIO_MIXER_META_DATA               (0x0004 >> 2)
+#define AUD_CH_STATUS_REG(n)                ((0x0008 + 4 * n) >> 2)
+#define AUD_CH_A_DATA_REG(n)                ((0x0020 + 4 * n) >> 2)
+#define AUD_CH_B_DATA_REG(n)                ((0x0038 + 4 * n) >> 2)
+
+#define DP_AUDIO_DMA_CHANNEL(n)             (4 + n)
+#define DP_GRAPHIC_DMA_CHANNEL              (3)
+#define DP_VIDEO_DMA_CHANNEL                (0)
+
+enum DPGraphicFmt {
+    DP_GRAPHIC_RGBA8888 = 0 << 8,
+    DP_GRAPHIC_ABGR8888 = 1 << 8,
+    DP_GRAPHIC_RGB888 = 2 << 8,
+    DP_GRAPHIC_BGR888 = 3 << 8,
+    DP_GRAPHIC_RGBA5551 = 4 << 8,
+    DP_GRAPHIC_RGBA4444 = 5 << 8,
+    DP_GRAPHIC_RGB565 = 6 << 8,
+    DP_GRAPHIC_8BPP = 7 << 8,
+    DP_GRAPHIC_4BPP = 8 << 8,
+    DP_GRAPHIC_2BPP = 9 << 8,
+    DP_GRAPHIC_1BPP = 10 << 8,
+    DP_GRAPHIC_MASK = 0xF << 8
+};
+
+enum DPVideoFmt {
+    DP_NL_VID_CB_Y0_CR_Y1 = 0,
+    DP_NL_VID_CR_Y0_CB_Y1 = 1,
+    DP_NL_VID_Y0_CR_Y1_CB = 2,
+    DP_NL_VID_Y0_CB_Y1_CR = 3,
+    DP_NL_VID_YV16 = 4,
+    DP_NL_VID_YV24 = 5,
+    DP_NL_VID_YV16CL = 6,
+    DP_NL_VID_MONO = 7,
+    DP_NL_VID_YV16CL2 = 8,
+    DP_NL_VID_YUV444 = 9,
+    DP_NL_VID_RGB888 = 10,
+    DP_NL_VID_RGBA8880 = 11,
+    DP_NL_VID_RGB888_10BPC = 12,
+    DP_NL_VID_YUV444_10BPC = 13,
+    DP_NL_VID_YV16CL2_10BPC = 14,
+    DP_NL_VID_YV16CL_10BPC = 15,
+    DP_NL_VID_YV16_10BPC = 16,
+    DP_NL_VID_YV24_10BPC = 17,
+    DP_NL_VID_Y_ONLY_10BPC = 18,
+    DP_NL_VID_YV16_420 = 19,
+    DP_NL_VID_YV16CL_420 = 20,
+    DP_NL_VID_YV16CL2_420 = 21,
+    DP_NL_VID_YV16_420_10BPC = 22,
+    DP_NL_VID_YV16CL_420_10BPC = 23,
+    DP_NL_VID_YV16CL2_420_10BPC = 24,
+    DP_NL_VID_FMT_MASK = 0x1F
+};
+
+typedef enum DPGraphicFmt DPGraphicFmt;
+typedef enum DPVideoFmt DPVideoFmt;
+
+static const VMStateDescription vmstate_dp = {
+    .name = TYPE_XLNX_DP,
+    .version_id = 1,
+    .fields = (VMStateField[]){
+        VMSTATE_UINT32_ARRAY(core_registers, XlnxDPState,
+                             DP_CORE_REG_ARRAY_SIZE),
+        VMSTATE_UINT32_ARRAY(avbufm_registers, XlnxDPState,
+                             DP_AVBUF_REG_ARRAY_SIZE),
+        VMSTATE_UINT32_ARRAY(vblend_registers, XlnxDPState,
+                             DP_VBLEND_REG_ARRAY_SIZE),
+        VMSTATE_UINT32_ARRAY(audio_registers, XlnxDPState,
+                             DP_AUDIO_REG_ARRAY_SIZE),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xlnx_dp_update_irq(XlnxDPState *s);
+
+static uint64_t xlnx_dp_audio_read(void *opaque, hwaddr offset, unsigned size)
+{
+    XlnxDPState *s = XLNX_DP(opaque);
+
+    offset = offset >> 2;
+    return s->audio_registers[offset];
+}
+
+static void xlnx_dp_audio_write(void *opaque, hwaddr offset, uint64_t value,
+                                unsigned size)
+{
+    XlnxDPState *s = XLNX_DP(opaque);
+
+    offset = offset >> 2;
+
+    switch (offset) {
+    case AUDIO_MIXER_META_DATA:
+        s->audio_registers[offset] = value & 0x00000001;
+        break;
+    default:
+        s->audio_registers[offset] = value;
+        break;
+    }
+}
+
+static const MemoryRegionOps audio_ops = {
+    .read = xlnx_dp_audio_read,
+    .write = xlnx_dp_audio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static inline uint32_t xlnx_dp_audio_get_volume(XlnxDPState *s,
+                                                uint8_t channel)
+{
+    switch (channel) {
+    case 0:
+        return extract32(s->audio_registers[AUDIO_MIXER_VOLUME_CONTROL], 0, 16);
+    case 1:
+        return extract32(s->audio_registers[AUDIO_MIXER_VOLUME_CONTROL], 16,
+                                                                         16);
+    default:
+        return 0;
+    }
+}
+
+static inline void xlnx_dp_audio_activate(XlnxDPState *s)
+{
+    bool activated = ((s->core_registers[DP_TX_AUDIO_CONTROL]
+                   & DP_TX_AUD_CTRL) != 0);
+    AUD_set_active_out(s->amixer_output_stream, activated);
+    xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(0),
+                                      &s->audio_buffer_0);
+    xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(1),
+                                      &s->audio_buffer_1);
+}
+
+static inline void xlnx_dp_audio_mix_buffer(XlnxDPState *s)
+{
+    /*
+     * Audio packets are signed and have this shape:
+     * | 16 | 16 | 16 | 16 | 16 | 16 | 16 | 16 |
+     * | R3 | L3 | R2 | L2 | R1 | L1 | R0 | L0 |
+     *
+     * Output audio is 16bits saturated.
+     */
+    int i;
+
+    if ((s->audio_data_available[0]) && (xlnx_dp_audio_get_volume(s, 0))) {
+        for (i = 0; i < s->audio_data_available[0] / 2; i++) {
+            s->temp_buffer[i] = (int64_t)(s->audio_buffer_0[i])
+                              * xlnx_dp_audio_get_volume(s, 0) / 8192;
+        }
+        s->byte_left = s->audio_data_available[0];
+    } else {
+        memset(s->temp_buffer, 0, s->audio_data_available[1] / 2);
+    }
+
+    if ((s->audio_data_available[1]) && (xlnx_dp_audio_get_volume(s, 1))) {
+        if ((s->audio_data_available[0] == 0)
+        || (s->audio_data_available[1] == s->audio_data_available[0])) {
+            for (i = 0; i < s->audio_data_available[1] / 2; i++) {
+                s->temp_buffer[i] += (int64_t)(s->audio_buffer_1[i])
+                                   * xlnx_dp_audio_get_volume(s, 1) / 8192;
+            }
+            s->byte_left = s->audio_data_available[1];
+        }
+    }
+
+    for (i = 0; i < s->byte_left / 2; i++) {
+        s->out_buffer[i] = MAX(-32767, MIN(s->temp_buffer[i], 32767));
+    }
+
+    s->data_ptr = 0;
+}
+
+static void xlnx_dp_audio_callback(void *opaque, int avail)
+{
+    /*
+     * Get some data from the DPDMA and compute these datas.
+     * Then wait for QEMU's audio subsystem to call this callback.
+     */
+    XlnxDPState *s = XLNX_DP(opaque);
+    size_t written = 0;
+
+    /* If there are already some data don't get more data. */
+    if (s->byte_left == 0) {
+        s->audio_data_available[0] = xlnx_dpdma_start_operation(s->dpdma, 4,
+                                                                  true);
+        s->audio_data_available[1] = xlnx_dpdma_start_operation(s->dpdma, 5,
+                                                                  true);
+        xlnx_dp_audio_mix_buffer(s);
+    }
+
+    /* Send the buffer through the audio. */
+    if (s->byte_left <= MAX_QEMU_BUFFER_SIZE) {
+        if (s->byte_left != 0) {
+            written = AUD_write(s->amixer_output_stream,
+                                &s->out_buffer[s->data_ptr], s->byte_left);
+        } else {
+            /*
+             * There is nothing to play.. We don't have any data! Fill the
+             * buffer with zero's and send it.
+             */
+            written = 0;
+            memset(s->out_buffer, 0, 1024);
+            AUD_write(s->amixer_output_stream, s->out_buffer, 1024);
+        }
+    } else {
+        written = AUD_write(s->amixer_output_stream,
+                            &s->out_buffer[s->data_ptr], MAX_QEMU_BUFFER_SIZE);
+    }
+    s->byte_left -= written;
+    s->data_ptr += written;
+}
+
+/*
+ * AUX channel related function.
+ */
+static void xlnx_dp_aux_clear_rx_fifo(XlnxDPState *s)
+{
+    fifo8_reset(&s->rx_fifo);
+}
+
+static void xlnx_dp_aux_push_rx_fifo(XlnxDPState *s, uint8_t *buf, size_t len)
+{
+    DPRINTF("Push %u data in rx_fifo\n", (unsigned)len);
+    fifo8_push_all(&s->rx_fifo, buf, len);
+}
+
+static uint8_t xlnx_dp_aux_pop_rx_fifo(XlnxDPState *s)
+{
+    uint8_t ret;
+
+    if (fifo8_is_empty(&s->rx_fifo)) {
+        DPRINTF("rx_fifo underflow..\n");
+        abort();
+    }
+    ret = fifo8_pop(&s->rx_fifo);
+    DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret);
+    return ret;
+}
+
+static void xlnx_dp_aux_clear_tx_fifo(XlnxDPState *s)
+{
+    fifo8_reset(&s->tx_fifo);
+}
+
+static void xlnx_dp_aux_push_tx_fifo(XlnxDPState *s, uint8_t val, size_t len)
+{
+    DPRINTF("Push %u data in tx_fifo\n", (unsigned)len);
+    fifo8_push_all(&s->tx_fifo, &val, len);
+}
+
+static uint8_t xlnx_dp_aux_pop_tx_fifo(XlnxDPState *s)
+{
+    uint8_t ret;
+
+    if (fifo8_is_empty(&s->tx_fifo)) {
+        DPRINTF("tx_fifo underflow..\n");
+        abort();
+    }
+    ret = fifo8_pop(&s->tx_fifo);
+    DPRINTF("pop 0x%2.2X from tx_fifo.\n", ret);
+    return ret;
+}
+
+static uint32_t xlnx_dp_aux_get_address(XlnxDPState *s)
+{
+    return s->core_registers[DP_AUX_ADDRESS];
+}
+
+/*
+ * Get command from the register.
+ */
+static void xlnx_dp_aux_set_command(XlnxDPState *s, uint32_t value)
+{
+    bool address_only = (value & AUX_ADDR_ONLY_MASK) != 0;
+    AUXCommand cmd = (value & AUX_COMMAND_MASK) >> AUX_COMMAND_SHIFT;
+    uint8_t nbytes = (value & AUX_COMMAND_NBYTES) + 1;
+    uint8_t buf[16];
+    int i;
+
+    /*
+     * When an address_only command is executed nothing happen to the fifo, so
+     * just make nbytes = 0.
+     */
+    if (address_only) {
+        nbytes = 0;
+    }
+
+    switch (cmd) {
+    case READ_AUX:
+    case READ_I2C:
+    case READ_I2C_MOT:
+        s->core_registers[DP_AUX_REPLY_CODE] = aux_request(s->aux_bus, cmd,
+                                               xlnx_dp_aux_get_address(s),
+                                               nbytes, buf);
+        s->core_registers[DP_REPLY_DATA_COUNT] = nbytes;
+
+        if (s->core_registers[DP_AUX_REPLY_CODE] == AUX_I2C_ACK) {
+            xlnx_dp_aux_push_rx_fifo(s, buf, nbytes);
+        }
+        break;
+    case WRITE_AUX:
+    case WRITE_I2C:
+    case WRITE_I2C_MOT:
+        for (i = 0; i < nbytes; i++) {
+            buf[i] = xlnx_dp_aux_pop_tx_fifo(s);
+        }
+        s->core_registers[DP_AUX_REPLY_CODE] = aux_request(s->aux_bus, cmd,
+                                               xlnx_dp_aux_get_address(s),
+                                               nbytes, buf);
+        xlnx_dp_aux_clear_tx_fifo(s);
+        break;
+    case WRITE_I2C_STATUS:
+        qemu_log_mask(LOG_UNIMP, "xlnx_dp: Write i2c status not implemented\n");
+        break;
+    default:
+        abort();
+    }
+
+    s->core_registers[DP_INTERRUPT_SIGNAL_STATE] |= 0x04;
+}
+
+static void xlnx_dp_set_dpdma(Object *obj, const char *name, Object *val,
+                              Error **errp)
+{
+    XlnxDPState *s = XLNX_DP(obj);
+    if (s->console) {
+        DisplaySurface *surface = qemu_console_surface(s->console);
+        XlnxDPDMAState *dma = XLNX_DPDMA(val);
+        xlnx_dpdma_set_host_data_location(dma, DP_GRAPHIC_DMA_CHANNEL,
+                                          surface_data(surface));
+    }
+}
+
+static inline uint8_t xlnx_dp_global_alpha_value(XlnxDPState *s)
+{
+    return (s->vblend_registers[V_BLEND_SET_GLOBAL_ALPHA_REG] & 0x1FE) >> 1;
+}
+
+static inline bool xlnx_dp_global_alpha_enabled(XlnxDPState *s)
+{
+    /*
+     * If the alpha is totally opaque (255) we consider the alpha is disabled to
+     * reduce CPU consumption.
+     */
+    return ((xlnx_dp_global_alpha_value(s) != 0xFF) &&
+           ((s->vblend_registers[V_BLEND_SET_GLOBAL_ALPHA_REG] & 0x01) != 0));
+}
+
+static void xlnx_dp_recreate_surface(XlnxDPState *s)
+{
+    /*
+     * Two possibilities, if blending is enabled the console displays
+     * bout_plane, if not g_plane is displayed.
+     */
+    uint16_t width = s->core_registers[DP_MAIN_STREAM_HRES];
+    uint16_t height = s->core_registers[DP_MAIN_STREAM_VRES];
+    DisplaySurface *current_console_surface = qemu_console_surface(s->console);
+
+    if ((width != 0) && (height != 0)) {
+        /*
+         * As dpy_gfx_replace_surface calls qemu_free_displaysurface on the
+         * surface we need to be carefull and don't free the surface associated
+         * to the console or double free will happen.
+         */
+        if (s->bout_plane.surface != current_console_surface) {
+            qemu_free_displaysurface(s->bout_plane.surface);
+        }
+        if (s->v_plane.surface != current_console_surface) {
+            qemu_free_displaysurface(s->v_plane.surface);
+        }
+        if (s->g_plane.surface != current_console_surface) {
+            qemu_free_displaysurface(s->g_plane.surface);
+        }
+
+        s->g_plane.surface
+                = qemu_create_displaysurface_from(width, height,
+                                                  s->g_plane.format, 0, NULL);
+        s->v_plane.surface
+                = qemu_create_displaysurface_from(width, height,
+                                                  s->v_plane.format, 0, NULL);
+        if (xlnx_dp_global_alpha_enabled(s)) {
+            s->bout_plane.surface =
+                            qemu_create_displaysurface_from(width,
+                                                            height,
+                                                            s->g_plane.format,
+                                                            0, NULL);
+            dpy_gfx_replace_surface(s->console, s->bout_plane.surface);
+        } else {
+            s->bout_plane.surface = NULL;
+            dpy_gfx_replace_surface(s->console, s->g_plane.surface);
+        }
+
+        xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL,
+                                            surface_data(s->g_plane.surface));
+        xlnx_dpdma_set_host_data_location(s->dpdma, DP_VIDEO_DMA_CHANNEL,
+                                            surface_data(s->v_plane.surface));
+    }
+}
+
+/*
+ * Change the graphic format of the surface.
+ */
+static void xlnx_dp_change_graphic_fmt(XlnxDPState *s)
+{
+    switch (s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK) {
+    case DP_GRAPHIC_RGBA8888:
+        s->g_plane.format = PIXMAN_r8g8b8a8;
+        break;
+    case DP_GRAPHIC_ABGR8888:
+        s->g_plane.format = PIXMAN_a8b8g8r8;
+        break;
+    case DP_GRAPHIC_RGB565:
+        s->g_plane.format = PIXMAN_r5g6b5;
+        break;
+    case DP_GRAPHIC_RGB888:
+        s->g_plane.format = PIXMAN_r8g8b8;
+        break;
+    case DP_GRAPHIC_BGR888:
+        s->g_plane.format = PIXMAN_b8g8r8;
+        break;
+    default:
+        DPRINTF("error: unsupported graphic format %u.\n",
+                s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK);
+        abort();
+    }
+
+    switch (s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK) {
+    case 0:
+        s->v_plane.format = PIXMAN_x8b8g8r8;
+        break;
+    case DP_NL_VID_RGBA8880:
+        s->v_plane.format = PIXMAN_x8b8g8r8;
+        break;
+    default:
+        DPRINTF("error: unsupported video format %u.\n",
+                s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK);
+        abort();
+    }
+
+    xlnx_dp_recreate_surface(s);
+}
+
+static void xlnx_dp_update_irq(XlnxDPState *s)
+{
+    uint32_t flags;
+
+    flags = s->core_registers[DP_INT_STATUS] & ~s->core_registers[DP_INT_MASK];
+    DPRINTF("update IRQ value = %" PRIx32 "\n", flags);
+    qemu_set_irq(s->irq, flags != 0);
+}
+
+static uint64_t xlnx_dp_read(void *opaque, hwaddr offset, unsigned size)
+{
+    XlnxDPState *s = XLNX_DP(opaque);
+    uint64_t ret = 0;
+
+    offset = offset >> 2;
+
+    switch (offset) {
+    case DP_TX_USER_FIFO_OVERFLOW:
+        /* This register is cleared after a read */
+        ret = s->core_registers[DP_TX_USER_FIFO_OVERFLOW];
+        s->core_registers[DP_TX_USER_FIFO_OVERFLOW] = 0;
+        break;
+    case DP_AUX_REPLY_DATA:
+        ret = xlnx_dp_aux_pop_rx_fifo(s);
+        break;
+    case DP_INTERRUPT_SIGNAL_STATE:
+        /*
+         * XXX: Not sure it is the right thing to do actually.
+         * The register is not written by the device driver so it's stuck
+         * to 0x04.
+         */
+        ret = s->core_registers[DP_INTERRUPT_SIGNAL_STATE];
+        s->core_registers[DP_INTERRUPT_SIGNAL_STATE] &= ~0x04;
+        break;
+    case DP_AUX_WRITE_FIFO:
+    case DP_TX_AUDIO_INFO_DATA(0):
+    case DP_TX_AUDIO_INFO_DATA(1):
+    case DP_TX_AUDIO_INFO_DATA(2):
+    case DP_TX_AUDIO_INFO_DATA(3):
+    case DP_TX_AUDIO_INFO_DATA(4):
+    case DP_TX_AUDIO_INFO_DATA(5):
+    case DP_TX_AUDIO_INFO_DATA(6):
+    case DP_TX_AUDIO_INFO_DATA(7):
+    case DP_TX_AUDIO_EXT_DATA(0):
+    case DP_TX_AUDIO_EXT_DATA(1):
+    case DP_TX_AUDIO_EXT_DATA(2):
+    case DP_TX_AUDIO_EXT_DATA(3):
+    case DP_TX_AUDIO_EXT_DATA(4):
+    case DP_TX_AUDIO_EXT_DATA(5):
+    case DP_TX_AUDIO_EXT_DATA(6):
+    case DP_TX_AUDIO_EXT_DATA(7):
+    case DP_TX_AUDIO_EXT_DATA(8):
+        /* write only registers */
+        ret = 0;
+        break;
+    default:
+        assert(offset <= (0x3AC >> 2));
+        ret = s->core_registers[offset];
+        break;
+    }
+
+    DPRINTF("core read @%" PRIx64 " = 0x%8.8" PRIX64 "\n", offset << 2, ret);
+    return ret;
+}
+
+static void xlnx_dp_write(void *opaque, hwaddr offset, uint64_t value,
+                          unsigned size)
+{
+    XlnxDPState *s = XLNX_DP(opaque);
+
+    DPRINTF("core write @%" PRIx64 " = 0x%8.8" PRIX64 "\n", offset, value);
+
+    offset = offset >> 2;
+
+    switch (offset) {
+    /*
+     * Only special write case are handled.
+     */
+    case DP_LINK_BW_SET:
+        s->core_registers[offset] = value & 0x000000FF;
+        break;
+    case DP_LANE_COUNT_SET:
+    case DP_MAIN_STREAM_MISC0:
+        s->core_registers[offset] = value & 0x0000000F;
+        break;
+    case DP_TRAINING_PATTERN_SET:
+    case DP_LINK_QUAL_PATTERN_SET:
+    case DP_MAIN_STREAM_POLARITY:
+    case DP_PHY_VOLTAGE_DIFF_LANE_0:
+    case DP_PHY_VOLTAGE_DIFF_LANE_1:
+        s->core_registers[offset] = value & 0x00000003;
+        break;
+    case DP_ENHANCED_FRAME_EN:
+    case DP_SCRAMBLING_DISABLE:
+    case DP_DOWNSPREAD_CTRL:
+    case DP_MAIN_STREAM_ENABLE:
+    case DP_TRANSMIT_PRBS7:
+        s->core_registers[offset] = value & 0x00000001;
+        break;
+    case DP_PHY_CLOCK_SELECT:
+        s->core_registers[offset] = value & 0x00000007;
+        break;
+    case DP_SOFTWARE_RESET:
+        /*
+         * No need to update this bit as it's read '0'.
+         */
+        /*
+         * TODO: reset IP.
+         */
+        break;
+    case DP_TRANSMITTER_ENABLE:
+        s->core_registers[offset] = value & 0x01;
+        break;
+    case DP_FORCE_SCRAMBLER_RESET:
+        /*
+         * No need to update this bit as it's read '0'.
+         */
+        /*
+         * TODO: force a scrambler reset??
+         */
+        break;
+    case DP_AUX_COMMAND_REGISTER:
+        s->core_registers[offset] = value & 0x00001F0F;
+        xlnx_dp_aux_set_command(s, s->core_registers[offset]);
+        break;
+    case DP_MAIN_STREAM_HTOTAL:
+    case DP_MAIN_STREAM_VTOTAL:
+    case DP_MAIN_STREAM_HSTART:
+    case DP_MAIN_STREAM_VSTART:
+        s->core_registers[offset] = value & 0x0000FFFF;
+        break;
+    case DP_MAIN_STREAM_HRES:
+    case DP_MAIN_STREAM_VRES:
+        s->core_registers[offset] = value & 0x0000FFFF;
+        xlnx_dp_recreate_surface(s);
+        break;
+    case DP_MAIN_STREAM_HSWIDTH:
+    case DP_MAIN_STREAM_VSWIDTH:
+        s->core_registers[offset] = value & 0x00007FFF;
+        break;
+    case DP_MAIN_STREAM_MISC1:
+        s->core_registers[offset] = value & 0x00000086;
+        break;
+    case DP_MAIN_STREAM_M_VID:
+    case DP_MAIN_STREAM_N_VID:
+        s->core_registers[offset] = value & 0x00FFFFFF;
+        break;
+    case DP_MSA_TRANSFER_UNIT_SIZE:
+    case DP_MIN_BYTES_PER_TU:
+    case DP_INIT_WAIT:
+        s->core_registers[offset] = value & 0x00000007;
+        break;
+    case DP_USER_DATA_COUNT_PER_LANE:
+        s->core_registers[offset] = value & 0x0003FFFF;
+        break;
+    case DP_FRAC_BYTES_PER_TU:
+        s->core_registers[offset] = value & 0x000003FF;
+        break;
+    case DP_PHY_RESET:
+        s->core_registers[offset] = value & 0x00010003;
+        /*
+         * TODO: Reset something?
+         */
+        break;
+    case DP_TX_PHY_POWER_DOWN:
+        s->core_registers[offset] = value & 0x0000000F;
+        /*
+         * TODO: Power down things?
+         */
+        break;
+    case DP_AUX_WRITE_FIFO:
+        xlnx_dp_aux_push_tx_fifo(s, value, 1);
+        break;
+    case DP_AUX_CLOCK_DIVIDER:
+        break;
+    case DP_AUX_REPLY_COUNT:
+        /*
+         * Writing to this register clear the counter.
+         */
+        s->core_registers[offset] = 0x00000000;
+        break;
+    case DP_AUX_ADDRESS:
+        s->core_registers[offset] = value & 0x000FFFFF;
+        break;
+    case DP_VERSION_REGISTER:
+    case DP_CORE_ID:
+    case DP_TX_USER_FIFO_OVERFLOW:
+    case DP_AUX_REPLY_DATA:
+    case DP_AUX_REPLY_CODE:
+    case DP_REPLY_DATA_COUNT:
+    case DP_REPLY_STATUS:
+    case DP_HPD_DURATION:
+        /*
+         * Write to read only location..
+         */
+        break;
+    case DP_TX_AUDIO_CONTROL:
+        s->core_registers[offset] = value & 0x00000001;
+        xlnx_dp_audio_activate(s);
+        break;
+    case DP_TX_AUDIO_CHANNELS:
+        s->core_registers[offset] = value & 0x00000007;
+        xlnx_dp_audio_activate(s);
+        break;
+    case DP_INT_STATUS:
+        s->core_registers[DP_INT_STATUS] &= ~value;
+        xlnx_dp_update_irq(s);
+        break;
+    case DP_INT_EN:
+        s->core_registers[DP_INT_MASK] &= ~value;
+        xlnx_dp_update_irq(s);
+        break;
+    case DP_INT_DS:
+        s->core_registers[DP_INT_MASK] |= ~value;
+        xlnx_dp_update_irq(s);
+        break;
+    default:
+        assert(offset <= (0x504C >> 2));
+        s->core_registers[offset] = value;
+        break;
+    }
+}
+
+static const MemoryRegionOps dp_ops = {
+    .read = xlnx_dp_read,
+    .write = xlnx_dp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+/*
+ * This is to handle Read/Write to the Video Blender.
+ */
+static void xlnx_dp_vblend_write(void *opaque, hwaddr offset,
+                                 uint64_t value, unsigned size)
+{
+    XlnxDPState *s = XLNX_DP(opaque);
+    bool alpha_was_enabled;
+
+    DPRINTF("vblend: write @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset,
+                                                               (uint32_t)value);
+    offset = offset >> 2;
+
+    switch (offset) {
+    case V_BLEND_BG_CLR_0:
+    case V_BLEND_BG_CLR_1:
+    case V_BLEND_BG_CLR_2:
+        s->vblend_registers[offset] = value & 0x00000FFF;
+        break;
+    case V_BLEND_SET_GLOBAL_ALPHA_REG:
+        /*
+         * A write to this register can enable or disable blending. Thus we need
+         * to recreate the surfaces.
+         */
+        alpha_was_enabled = xlnx_dp_global_alpha_enabled(s);
+        s->vblend_registers[offset] = value & 0x000001FF;
+        if (xlnx_dp_global_alpha_enabled(s) != alpha_was_enabled) {
+            xlnx_dp_recreate_surface(s);
+        }
+        break;
+    case V_BLEND_OUTPUT_VID_FORMAT:
+        s->vblend_registers[offset] = value & 0x00000017;
+        break;
+    case V_BLEND_LAYER0_CONTROL:
+    case V_BLEND_LAYER1_CONTROL:
+        s->vblend_registers[offset] = value & 0x00000103;
+        break;
+    case V_BLEND_RGB2YCBCR_COEFF(0):
+    case V_BLEND_RGB2YCBCR_COEFF(1):
+    case V_BLEND_RGB2YCBCR_COEFF(2):
+    case V_BLEND_RGB2YCBCR_COEFF(3):
+    case V_BLEND_RGB2YCBCR_COEFF(4):
+    case V_BLEND_RGB2YCBCR_COEFF(5):
+    case V_BLEND_RGB2YCBCR_COEFF(6):
+    case V_BLEND_RGB2YCBCR_COEFF(7):
+    case V_BLEND_RGB2YCBCR_COEFF(8):
+    case V_BLEND_IN1CSC_COEFF(0):
+    case V_BLEND_IN1CSC_COEFF(1):
+    case V_BLEND_IN1CSC_COEFF(2):
+    case V_BLEND_IN1CSC_COEFF(3):
+    case V_BLEND_IN1CSC_COEFF(4):
+    case V_BLEND_IN1CSC_COEFF(5):
+    case V_BLEND_IN1CSC_COEFF(6):
+    case V_BLEND_IN1CSC_COEFF(7):
+    case V_BLEND_IN1CSC_COEFF(8):
+    case V_BLEND_IN2CSC_COEFF(0):
+    case V_BLEND_IN2CSC_COEFF(1):
+    case V_BLEND_IN2CSC_COEFF(2):
+    case V_BLEND_IN2CSC_COEFF(3):
+    case V_BLEND_IN2CSC_COEFF(4):
+    case V_BLEND_IN2CSC_COEFF(5):
+    case V_BLEND_IN2CSC_COEFF(6):
+    case V_BLEND_IN2CSC_COEFF(7):
+    case V_BLEND_IN2CSC_COEFF(8):
+        s->vblend_registers[offset] = value & 0x0000FFFF;
+        break;
+    case V_BLEND_LUMA_IN1CSC_OFFSET:
+    case V_BLEND_CR_IN1CSC_OFFSET:
+    case V_BLEND_CB_IN1CSC_OFFSET:
+    case V_BLEND_LUMA_IN2CSC_OFFSET:
+    case V_BLEND_CR_IN2CSC_OFFSET:
+    case V_BLEND_CB_IN2CSC_OFFSET:
+    case V_BLEND_LUMA_OUTCSC_OFFSET:
+    case V_BLEND_CR_OUTCSC_OFFSET:
+    case V_BLEND_CB_OUTCSC_OFFSET:
+        s->vblend_registers[offset] = value & 0x3FFF7FFF;
+        break;
+    case V_BLEND_CHROMA_KEY_ENABLE:
+        s->vblend_registers[offset] = value & 0x00000003;
+        break;
+    case V_BLEND_CHROMA_KEY_COMP1:
+    case V_BLEND_CHROMA_KEY_COMP2:
+    case V_BLEND_CHROMA_KEY_COMP3:
+        s->vblend_registers[offset] = value & 0x0FFF0FFF;
+        break;
+    default:
+        s->vblend_registers[offset] = value;
+        break;
+    }
+}
+
+static uint64_t xlnx_dp_vblend_read(void *opaque, hwaddr offset,
+                                    unsigned size)
+{
+    XlnxDPState *s = XLNX_DP(opaque);
+
+    DPRINTF("vblend: read @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset,
+            s->vblend_registers[offset >> 2]);
+    return s->vblend_registers[offset >> 2];
+}
+
+static const MemoryRegionOps vblend_ops = {
+    .read = xlnx_dp_vblend_read,
+    .write = xlnx_dp_vblend_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+/*
+ * This is to handle Read/Write to the Audio Video buffer manager.
+ */
+static void xlnx_dp_avbufm_write(void *opaque, hwaddr offset, uint64_t value,
+                                 unsigned size)
+{
+    XlnxDPState *s = XLNX_DP(opaque);
+
+    DPRINTF("avbufm: write @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset,
+                                                               (uint32_t)value);
+    offset = offset >> 2;
+
+    switch (offset) {
+    case AV_BUF_FORMAT:
+        s->avbufm_registers[offset] = value & 0x00000FFF;
+        xlnx_dp_change_graphic_fmt(s);
+        break;
+    case AV_CHBUF0:
+    case AV_CHBUF1:
+    case AV_CHBUF2:
+    case AV_CHBUF3:
+    case AV_CHBUF4:
+    case AV_CHBUF5:
+        s->avbufm_registers[offset] = value & 0x0000007F;
+        break;
+    case AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT:
+        s->avbufm_registers[offset] = value & 0x0000007F;
+        break;
+    case AV_BUF_DITHER_CONFIG:
+        s->avbufm_registers[offset] = value & 0x000007FF;
+        break;
+    case AV_BUF_DITHER_CONFIG_MAX:
+    case AV_BUF_DITHER_CONFIG_MIN:
+        s->avbufm_registers[offset] = value & 0x00000FFF;
+        break;
+    case AV_BUF_PATTERN_GEN_SELECT:
+        s->avbufm_registers[offset] = value & 0xFFFFFF03;
+        break;
+    case AV_BUF_AUD_VID_CLK_SOURCE:
+        s->avbufm_registers[offset] = value & 0x00000007;
+        break;
+    case AV_BUF_SRST_REG:
+        s->avbufm_registers[offset] = value & 0x00000002;
+        break;
+    case AV_BUF_AUDIO_CH_CONFIG:
+        s->avbufm_registers[offset] = value & 0x00000003;
+        break;
+    case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(0):
+    case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(1):
+    case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(2):
+    case AV_BUF_VIDEO_COMP_SCALE_FACTOR(0):
+    case AV_BUF_VIDEO_COMP_SCALE_FACTOR(1):
+    case AV_BUF_VIDEO_COMP_SCALE_FACTOR(2):
+        s->avbufm_registers[offset] = value & 0x0000FFFF;
+        break;
+    case AV_BUF_LIVE_VIDEO_COMP_SF(0):
+    case AV_BUF_LIVE_VIDEO_COMP_SF(1):
+    case AV_BUF_LIVE_VIDEO_COMP_SF(2):
+    case AV_BUF_LIVE_VID_CONFIG:
+    case AV_BUF_LIVE_GFX_COMP_SF(0):
+    case AV_BUF_LIVE_GFX_COMP_SF(1):
+    case AV_BUF_LIVE_GFX_COMP_SF(2):
+    case AV_BUF_LIVE_GFX_CONFIG:
+    case AV_BUF_NON_LIVE_LATENCY:
+    case AV_BUF_STC_CONTROL:
+    case AV_BUF_STC_INIT_VALUE0:
+    case AV_BUF_STC_INIT_VALUE1:
+    case AV_BUF_STC_ADJ:
+    case AV_BUF_STC_VIDEO_VSYNC_TS_REG0:
+    case AV_BUF_STC_VIDEO_VSYNC_TS_REG1:
+    case AV_BUF_STC_EXT_VSYNC_TS_REG0:
+    case AV_BUF_STC_EXT_VSYNC_TS_REG1:
+    case AV_BUF_STC_CUSTOM_EVENT_TS_REG0:
+    case AV_BUF_STC_CUSTOM_EVENT_TS_REG1:
+    case AV_BUF_STC_CUSTOM_EVENT2_TS_REG0:
+    case AV_BUF_STC_CUSTOM_EVENT2_TS_REG1:
+    case AV_BUF_STC_SNAPSHOT0:
+    case AV_BUF_STC_SNAPSHOT1:
+    case AV_BUF_HCOUNT_VCOUNT_INT0:
+    case AV_BUF_HCOUNT_VCOUNT_INT1:
+        qemu_log_mask(LOG_UNIMP, "avbufm: unimplmented");
+        break;
+    default:
+        s->avbufm_registers[offset] = value;
+        break;
+    }
+}
+
+static uint64_t xlnx_dp_avbufm_read(void *opaque, hwaddr offset,
+                                    unsigned size)
+{
+    XlnxDPState *s = XLNX_DP(opaque);
+
+    offset = offset >> 2;
+    return s->avbufm_registers[offset];
+}
+
+static const MemoryRegionOps avbufm_ops = {
+    .read = xlnx_dp_avbufm_read,
+    .write = xlnx_dp_avbufm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+/*
+ * This is a global alpha blending using pixman.
+ * Both graphic and video planes are multiplied with the global alpha
+ * coefficient and added.
+ */
+static inline void xlnx_dp_blend_surface(XlnxDPState *s)
+{
+    pixman_fixed_t alpha1[] = { pixman_double_to_fixed(1),
+                                pixman_double_to_fixed(1),
+                                pixman_double_to_fixed(1.0) };
+    pixman_fixed_t alpha2[] = { pixman_double_to_fixed(1),
+                                pixman_double_to_fixed(1),
+                                pixman_double_to_fixed(1.0) };
+
+    if ((surface_width(s->g_plane.surface)
+         != surface_width(s->v_plane.surface)) ||
+        (surface_height(s->g_plane.surface)
+         != surface_height(s->v_plane.surface))) {
+        return;
+    }
+
+    alpha1[2] = pixman_double_to_fixed((double)(xlnx_dp_global_alpha_value(s))
+                                       / 256.0);
+    alpha2[2] = pixman_double_to_fixed((255.0
+                                    - (double)xlnx_dp_global_alpha_value(s))
+                                       / 256.0);
+
+    pixman_image_set_filter(s->g_plane.surface->image,
+                            PIXMAN_FILTER_CONVOLUTION, alpha1, 3);
+    pixman_image_composite(PIXMAN_OP_SRC, s->g_plane.surface->image, 0,
+                           s->bout_plane.surface->image, 0, 0, 0, 0, 0, 0,
+                           surface_width(s->g_plane.surface),
+                           surface_height(s->g_plane.surface));
+    pixman_image_set_filter(s->v_plane.surface->image,
+                            PIXMAN_FILTER_CONVOLUTION, alpha2, 3);
+    pixman_image_composite(PIXMAN_OP_ADD, s->v_plane.surface->image, 0,
+                           s->bout_plane.surface->image, 0, 0, 0, 0, 0, 0,
+                           surface_width(s->g_plane.surface),
+                           surface_height(s->g_plane.surface));
+}
+
+static void xlnx_dp_update_display(void *opaque)
+{
+    XlnxDPState *s = XLNX_DP(opaque);
+
+    if ((s->core_registers[DP_TRANSMITTER_ENABLE] & 0x01) == 0) {
+        return;
+    }
+
+    s->core_registers[DP_INT_STATUS] |= (1 << 13);
+    xlnx_dp_update_irq(s);
+
+    xlnx_dpdma_trigger_vsync_irq(s->dpdma);
+
+    /*
+     * Trigger the DMA channel.
+     */
+    if (!xlnx_dpdma_start_operation(s->dpdma, 3, false)) {
+        /*
+         * An error occured don't do anything with the data..
+         * Trigger an underflow interrupt.
+         */
+        s->core_registers[DP_INT_STATUS] |= (1 << 21);
+        xlnx_dp_update_irq(s);
+        return;
+    }
+
+    if (xlnx_dp_global_alpha_enabled(s)) {
+        if (!xlnx_dpdma_start_operation(s->dpdma, 0, false)) {
+            s->core_registers[DP_INT_STATUS] |= (1 << 21);
+            xlnx_dp_update_irq(s);
+            return;
+        }
+        xlnx_dp_blend_surface(s);
+    }
+
+    /*
+     * XXX: We might want to update only what changed.
+     */
+    dpy_gfx_update(s->console, 0, 0, surface_width(s->g_plane.surface),
+                                     surface_height(s->g_plane.surface));
+}
+
+static const GraphicHwOps xlnx_dp_gfx_ops = {
+    .gfx_update  = xlnx_dp_update_display,
+};
+
+static void xlnx_dp_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    XlnxDPState *s = XLNX_DP(obj);
+
+    memory_region_init(&s->container, obj, TYPE_XLNX_DP, 0xC050);
+
+    memory_region_init_io(&s->core_iomem, obj, &dp_ops, s, TYPE_XLNX_DP
+                          ".core", 0x3AF);
+    memory_region_add_subregion(&s->container, 0x0000, &s->core_iomem);
+
+    memory_region_init_io(&s->vblend_iomem, obj, &vblend_ops, s, TYPE_XLNX_DP
+                          ".v_blend", 0x1DF);
+    memory_region_add_subregion(&s->container, 0xA000, &s->vblend_iomem);
+
+    memory_region_init_io(&s->avbufm_iomem, obj, &avbufm_ops, s, TYPE_XLNX_DP
+                          ".av_buffer_manager", 0x238);
+    memory_region_add_subregion(&s->container, 0xB000, &s->avbufm_iomem);
+
+    memory_region_init_io(&s->audio_iomem, obj, &audio_ops, s, TYPE_XLNX_DP
+                          ".audio", sizeof(s->audio_registers));
+    memory_region_add_subregion(&s->container, 0xC000, &s->audio_iomem);
+
+    sysbus_init_mmio(sbd, &s->container);
+    sysbus_init_irq(sbd, &s->irq);
+
+    object_property_add_link(obj, "dpdma", TYPE_XLNX_DPDMA,
+                             (Object **) &s->dpdma,
+                             xlnx_dp_set_dpdma,
+                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
+                             &error_abort);
+
+    /*
+     * Initialize AUX Bus.
+     */
+    s->aux_bus = aux_init_bus(DEVICE(obj), "aux");
+
+    /*
+     * Initialize DPCD and EDID..
+     */
+    s->dpcd = DPCD(aux_create_slave(s->aux_bus, "dpcd", 0x00000));
+    s->edid = I2CDDC(qdev_create(BUS(aux_get_i2c_bus(s->aux_bus)), "i2c-ddc"));
+    i2c_set_slave_address(I2C_SLAVE(s->edid), 0x50);
+
+    fifo8_create(&s->rx_fifo, 16);
+    fifo8_create(&s->tx_fifo, 16);
+}
+
+static void xlnx_dp_realize(DeviceState *dev, Error **errp)
+{
+    XlnxDPState *s = XLNX_DP(dev);
+    DisplaySurface *surface;
+    struct audsettings as;
+
+    s->console = graphic_console_init(dev, 0, &xlnx_dp_gfx_ops, s);
+    surface = qemu_console_surface(s->console);
+    xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL,
+                                      surface_data(surface));
+
+    as.freq = 44100;
+    as.nchannels = 2;
+    as.fmt = AUD_FMT_S16;
+    as.endianness = 0;
+
+    AUD_register_card("xlnx_dp.audio", &s->aud_card);
+
+    s->amixer_output_stream = AUD_open_out(&s->aud_card,
+                                           s->amixer_output_stream,
+                                           "xlnx_dp.audio.out",
+                                           s,
+                                           xlnx_dp_audio_callback,
+                                           &as);
+    AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255);
+    xlnx_dp_audio_activate(s);
+}
+
+static void xlnx_dp_reset(DeviceState *dev)
+{
+    XlnxDPState *s = XLNX_DP(dev);
+
+    memset(s->core_registers, 0, sizeof(s->core_registers));
+    s->core_registers[DP_VERSION_REGISTER] = 0x04010000;
+    s->core_registers[DP_CORE_ID] = 0x01020000;
+    s->core_registers[DP_REPLY_STATUS] = 0x00000010;
+    s->core_registers[DP_MSA_TRANSFER_UNIT_SIZE] = 0x00000040;
+    s->core_registers[DP_INIT_WAIT] = 0x00000020;
+    s->core_registers[DP_PHY_RESET] = 0x00010003;
+    s->core_registers[DP_INT_MASK] = 0xFFFFF03F;
+    s->core_registers[DP_PHY_STATUS] = 0x00000043;
+    s->core_registers[DP_INTERRUPT_SIGNAL_STATE] = 0x00000001;
+
+    s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(0)] = 0x00001000;
+    s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(4)] = 0x00001000;
+    s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(8)] = 0x00001000;
+    s->vblend_registers[V_BLEND_IN1CSC_COEFF(0)] = 0x00001000;
+    s->vblend_registers[V_BLEND_IN1CSC_COEFF(4)] = 0x00001000;
+    s->vblend_registers[V_BLEND_IN1CSC_COEFF(8)] = 0x00001000;
+    s->vblend_registers[V_BLEND_IN2CSC_COEFF(0)] = 0x00001000;
+    s->vblend_registers[V_BLEND_IN2CSC_COEFF(4)] = 0x00001000;
+    s->vblend_registers[V_BLEND_IN2CSC_COEFF(8)] = 0x00001000;
+
+    s->avbufm_registers[AV_BUF_NON_LIVE_LATENCY] = 0x00000180;
+    s->avbufm_registers[AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT] = 0x00000008;
+    s->avbufm_registers[AV_BUF_DITHER_CONFIG_MAX] = 0x00000FFF;
+    s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(0)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(1)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(2)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(0)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(1)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(2)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(0)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(1)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(2)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(0)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(1)] = 0x00010101;
+    s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(2)] = 0x00010101;
+
+    memset(s->audio_registers, 0, sizeof(s->audio_registers));
+    s->byte_left = 0;
+
+    xlnx_dp_aux_clear_rx_fifo(s);
+    xlnx_dp_change_graphic_fmt(s);
+    xlnx_dp_update_irq(s);
+}
+
+static void xlnx_dp_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = xlnx_dp_realize;
+    dc->vmsd = &vmstate_dp;
+    dc->reset = xlnx_dp_reset;
+}
+
+static const TypeInfo xlnx_dp_info = {
+    .name          = TYPE_XLNX_DP,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(XlnxDPState),
+    .instance_init = xlnx_dp_init,
+    .class_init    = xlnx_dp_class_init,
+};
+
+static void xlnx_dp_register_types(void)
+{
+    type_register_static(&xlnx_dp_info);
+}
+
+type_init(xlnx_dp_register_types)
diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs
index a1abbcf..8b0823e 100644
--- a/hw/dma/Makefile.objs
+++ b/hw/dma/Makefile.objs
@@ -8,6 +8,7 @@
 common-obj-$(CONFIG_ETRAXFS) += etraxfs_dma.o
 common-obj-$(CONFIG_STP2000) += sparc32_dma.o
 common-obj-$(CONFIG_SUN4M) += sun4m_iommu.o
+obj-$(CONFIG_XLNX_ZYNQMP) += xlnx_dpdma.o
 
 obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
 obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c
index 2306abc..634a432 100644
--- a/hw/dma/pxa2xx_dma.c
+++ b/hw/dma/pxa2xx_dma.c
@@ -12,6 +12,7 @@
 #include "hw/hw.h"
 #include "hw/arm/pxa.h"
 #include "hw/sysbus.h"
+#include "qapi/error.h"
 
 #define PXA255_DMA_NUM_CHANNELS 16
 #define PXA27X_DMA_NUM_CHANNELS 32
@@ -450,31 +451,36 @@
     }
 }
 
-static int pxa2xx_dma_init(SysBusDevice *sbd)
+static void pxa2xx_dma_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
+    DeviceState *dev = DEVICE(obj);
+    PXA2xxDMAState *s = PXA2XX_DMA(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    memset(s->req, 0, sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
+
+    qdev_init_gpio_in(dev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
+
+    memory_region_init_io(&s->iomem, obj, &pxa2xx_dma_ops, s,
+                          "pxa2xx.dma", 0x00010000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+}
+
+static void pxa2xx_dma_realize(DeviceState *dev, Error **errp)
+{
     PXA2xxDMAState *s = PXA2XX_DMA(dev);
     int i;
 
     if (s->channels <= 0) {
-        return -1;
+        error_setg(errp, "channels value invalid");
+        return;
     }
 
     s->chan = g_new0(PXA2xxDMAChannel, s->channels);
 
     for (i = 0; i < s->channels; i ++)
         s->chan[i].state = DCSR_STOPINTR;
-
-    memset(s->req, 0, sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
-
-    qdev_init_gpio_in(dev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
-
-    memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_dma_ops, s,
-                          "pxa2xx.dma", 0x00010000);
-    sysbus_init_mmio(sbd, &s->iomem);
-    sysbus_init_irq(sbd, &s->irq);
-
-    return 0;
 }
 
 DeviceState *pxa27x_dma_init(hwaddr base, qemu_irq irq)
@@ -553,18 +559,18 @@
 static void pxa2xx_dma_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = pxa2xx_dma_init;
     dc->desc = "PXA2xx DMA controller";
     dc->vmsd = &vmstate_pxa2xx_dma;
     dc->props = pxa2xx_dma_properties;
+    dc->realize = pxa2xx_dma_realize;
 }
 
 static const TypeInfo pxa2xx_dma_info = {
     .name          = TYPE_PXA2XX_DMA,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PXA2xxDMAState),
+    .instance_init = pxa2xx_dma_init,
     .class_init    = pxa2xx_dma_class_init,
 };
 
diff --git a/hw/dma/xlnx_dpdma.c b/hw/dma/xlnx_dpdma.c
new file mode 100644
index 0000000..8ceb21d
--- /dev/null
+++ b/hw/dma/xlnx_dpdma.c
@@ -0,0 +1,786 @@
+/*
+ * xlnx_dpdma.c
+ *
+ *  Copyright (C) 2015 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.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 "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/dma/xlnx_dpdma.h"
+
+#ifndef DEBUG_DPDMA
+#define DEBUG_DPDMA 0
+#endif
+
+#define DPRINTF(fmt, ...) do {                                                 \
+    if (DEBUG_DPDMA) {                                                         \
+        qemu_log("xlnx_dpdma: " fmt , ## __VA_ARGS__);                         \
+    }                                                                          \
+} while (0);
+
+/*
+ * Registers offset for DPDMA.
+ */
+#define DPDMA_ERR_CTRL                        (0x0000)
+#define DPDMA_ISR                             (0x0004 >> 2)
+#define DPDMA_IMR                             (0x0008 >> 2)
+#define DPDMA_IEN                             (0x000C >> 2)
+#define DPDMA_IDS                             (0x0010 >> 2)
+#define DPDMA_EISR                            (0x0014 >> 2)
+#define DPDMA_EIMR                            (0x0018 >> 2)
+#define DPDMA_EIEN                            (0x001C >> 2)
+#define DPDMA_EIDS                            (0x0020 >> 2)
+#define DPDMA_CNTL                            (0x0100 >> 2)
+
+#define DPDMA_GBL                             (0x0104 >> 2)
+#define DPDMA_GBL_TRG_CH(n)                   (1 << n)
+#define DPDMA_GBL_RTRG_CH(n)                  (1 << 6 << n)
+
+#define DPDMA_ALC0_CNTL                       (0x0108 >> 2)
+#define DPDMA_ALC0_STATUS                     (0x010C >> 2)
+#define DPDMA_ALC0_MAX                        (0x0110 >> 2)
+#define DPDMA_ALC0_MIN                        (0x0114 >> 2)
+#define DPDMA_ALC0_ACC                        (0x0118 >> 2)
+#define DPDMA_ALC0_ACC_TRAN                   (0x011C >> 2)
+#define DPDMA_ALC1_CNTL                       (0x0120 >> 2)
+#define DPDMA_ALC1_STATUS                     (0x0124 >> 2)
+#define DPDMA_ALC1_MAX                        (0x0128 >> 2)
+#define DPDMA_ALC1_MIN                        (0x012C >> 2)
+#define DPDMA_ALC1_ACC                        (0x0130 >> 2)
+#define DPDMA_ALC1_ACC_TRAN                   (0x0134 >> 2)
+
+#define DPDMA_DSCR_STRT_ADDRE_CH(n)           ((0x0200 + n * 0x100) >> 2)
+#define DPDMA_DSCR_STRT_ADDR_CH(n)            ((0x0204 + n * 0x100) >> 2)
+#define DPDMA_DSCR_NEXT_ADDRE_CH(n)           ((0x0208 + n * 0x100) >> 2)
+#define DPDMA_DSCR_NEXT_ADDR_CH(n)            ((0x020C + n * 0x100) >> 2)
+#define DPDMA_PYLD_CUR_ADDRE_CH(n)            ((0x0210 + n * 0x100) >> 2)
+#define DPDMA_PYLD_CUR_ADDR_CH(n)             ((0x0214 + n * 0x100) >> 2)
+
+#define DPDMA_CNTL_CH(n)                      ((0x0218 + n * 0x100) >> 2)
+#define DPDMA_CNTL_CH_EN                      (1)
+#define DPDMA_CNTL_CH_PAUSED                  (1 << 1)
+
+#define DPDMA_STATUS_CH(n)                    ((0x021C + n * 0x100) >> 2)
+#define DPDMA_STATUS_BURST_TYPE               (1 << 4)
+#define DPDMA_STATUS_MODE                     (1 << 5)
+#define DPDMA_STATUS_EN_CRC                   (1 << 6)
+#define DPDMA_STATUS_LAST_DSCR                (1 << 7)
+#define DPDMA_STATUS_LDSCR_FRAME              (1 << 8)
+#define DPDMA_STATUS_IGNR_DONE                (1 << 9)
+#define DPDMA_STATUS_DSCR_DONE                (1 << 10)
+#define DPDMA_STATUS_EN_DSCR_UP               (1 << 11)
+#define DPDMA_STATUS_EN_DSCR_INTR             (1 << 12)
+#define DPDMA_STATUS_PREAMBLE_OFF             (13)
+
+#define DPDMA_VDO_CH(n)                       ((0x0220 + n * 0x100) >> 2)
+#define DPDMA_PYLD_SZ_CH(n)                   ((0x0224 + n * 0x100) >> 2)
+#define DPDMA_DSCR_ID_CH(n)                   ((0x0228 + n * 0x100) >> 2)
+
+/*
+ * Descriptor control field.
+ */
+#define CONTROL_PREAMBLE_VALUE                0xA5
+
+#define DSCR_CTRL_PREAMBLE                    0xFF
+#define DSCR_CTRL_EN_DSCR_DONE_INTR           (1 << 8)
+#define DSCR_CTRL_EN_DSCR_UPDATE              (1 << 9)
+#define DSCR_CTRL_IGNORE_DONE                 (1 << 10)
+#define DSCR_CTRL_AXI_BURST_TYPE              (1 << 11)
+#define DSCR_CTRL_AXCACHE                     (0x0F << 12)
+#define DSCR_CTRL_AXPROT                      (0x2 << 16)
+#define DSCR_CTRL_DESCRIPTOR_MODE             (1 << 18)
+#define DSCR_CTRL_LAST_DESCRIPTOR             (1 << 19)
+#define DSCR_CTRL_ENABLE_CRC                  (1 << 20)
+#define DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME    (1 << 21)
+
+/*
+ * Descriptor timestamp field.
+ */
+#define STATUS_DONE                           (1 << 31)
+
+#define DPDMA_FRAG_MAX_SZ                     (4096)
+
+enum DPDMABurstType {
+    DPDMA_INCR = 0,
+    DPDMA_FIXED = 1
+};
+
+enum DPDMAMode {
+    DPDMA_CONTIGOUS = 0,
+    DPDMA_FRAGMENTED = 1
+};
+
+struct DPDMADescriptor {
+    uint32_t control;
+    uint32_t descriptor_id;
+    /* transfer size in byte. */
+    uint32_t xfer_size;
+    uint32_t line_size_stride;
+    uint32_t timestamp_lsb;
+    uint32_t timestamp_msb;
+    /* contains extension for both descriptor and source. */
+    uint32_t address_extension;
+    uint32_t next_descriptor;
+    uint32_t source_address;
+    uint32_t address_extension_23;
+    uint32_t address_extension_45;
+    uint32_t source_address2;
+    uint32_t source_address3;
+    uint32_t source_address4;
+    uint32_t source_address5;
+    uint32_t crc;
+};
+
+typedef enum DPDMABurstType DPDMABurstType;
+typedef enum DPDMAMode DPDMAMode;
+typedef struct DPDMADescriptor DPDMADescriptor;
+
+static bool xlnx_dpdma_desc_is_last(DPDMADescriptor *desc)
+{
+    return ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR) != 0);
+}
+
+static bool xlnx_dpdma_desc_is_last_of_frame(DPDMADescriptor *desc)
+{
+    return ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME) != 0);
+}
+
+static uint64_t xlnx_dpdma_desc_get_source_address(DPDMADescriptor *desc,
+                                                     uint8_t frag)
+{
+    uint64_t addr = 0;
+    assert(frag < 5);
+
+    switch (frag) {
+    case 0:
+        addr = desc->source_address
+            + (extract32(desc->address_extension, 16, 12) << 20);
+        break;
+    case 1:
+        addr = desc->source_address2
+            + (extract32(desc->address_extension_23, 0, 12) << 8);
+        break;
+    case 2:
+        addr = desc->source_address3
+            + (extract32(desc->address_extension_23, 16, 12) << 20);
+        break;
+    case 3:
+        addr = desc->source_address4
+            + (extract32(desc->address_extension_45, 0, 12) << 8);
+        break;
+    case 4:
+        addr = desc->source_address5
+            + (extract32(desc->address_extension_45, 16, 12) << 20);
+        break;
+    default:
+        addr = 0;
+        break;
+    }
+
+    return addr;
+}
+
+static uint32_t xlnx_dpdma_desc_get_transfer_size(DPDMADescriptor *desc)
+{
+    return desc->xfer_size;
+}
+
+static uint32_t xlnx_dpdma_desc_get_line_size(DPDMADescriptor *desc)
+{
+    return extract32(desc->line_size_stride, 0, 18);
+}
+
+static uint32_t xlnx_dpdma_desc_get_line_stride(DPDMADescriptor *desc)
+{
+    return extract32(desc->line_size_stride, 18, 14) * 16;
+}
+
+static inline bool xlnx_dpdma_desc_crc_enabled(DPDMADescriptor *desc)
+{
+    return (desc->control & DSCR_CTRL_ENABLE_CRC) != 0;
+}
+
+static inline bool xlnx_dpdma_desc_check_crc(DPDMADescriptor *desc)
+{
+    uint32_t *p = (uint32_t *)desc;
+    uint32_t crc = 0;
+    uint8_t i;
+
+    /*
+     * CRC is calculated on the whole descriptor except the last 32bits word
+     * using 32bits addition.
+     */
+    for (i = 0; i < 15; i++) {
+        crc += p[i];
+    }
+
+    return crc == desc->crc;
+}
+
+static inline bool xlnx_dpdma_desc_completion_interrupt(DPDMADescriptor *desc)
+{
+    return (desc->control & DSCR_CTRL_EN_DSCR_DONE_INTR) != 0;
+}
+
+static inline bool xlnx_dpdma_desc_is_valid(DPDMADescriptor *desc)
+{
+    return (desc->control & DSCR_CTRL_PREAMBLE) == CONTROL_PREAMBLE_VALUE;
+}
+
+static inline bool xlnx_dpdma_desc_is_contiguous(DPDMADescriptor *desc)
+{
+    return (desc->control & DSCR_CTRL_DESCRIPTOR_MODE) == 0;
+}
+
+static inline bool xlnx_dpdma_desc_update_enabled(DPDMADescriptor *desc)
+{
+    return (desc->control & DSCR_CTRL_EN_DSCR_UPDATE) != 0;
+}
+
+static inline void xlnx_dpdma_desc_set_done(DPDMADescriptor *desc)
+{
+    desc->timestamp_msb |= STATUS_DONE;
+}
+
+static inline bool xlnx_dpdma_desc_is_already_done(DPDMADescriptor *desc)
+{
+    return (desc->timestamp_msb & STATUS_DONE) != 0;
+}
+
+static inline bool xlnx_dpdma_desc_ignore_done_bit(DPDMADescriptor *desc)
+{
+    return (desc->control & DSCR_CTRL_IGNORE_DONE) != 0;
+}
+
+static const VMStateDescription vmstate_xlnx_dpdma = {
+    .name = TYPE_XLNX_DPDMA,
+    .version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(registers, XlnxDPDMAState,
+                             XLNX_DPDMA_REG_ARRAY_SIZE),
+        VMSTATE_BOOL_ARRAY(operation_finished, XlnxDPDMAState, 6),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xlnx_dpdma_update_irq(XlnxDPDMAState *s)
+{
+    bool flags;
+
+    flags = ((s->registers[DPDMA_ISR] & (~s->registers[DPDMA_IMR]))
+          || (s->registers[DPDMA_EISR] & (~s->registers[DPDMA_EIMR])));
+    qemu_set_irq(s->irq, flags);
+}
+
+static uint64_t xlnx_dpdma_descriptor_start_address(XlnxDPDMAState *s,
+                                                      uint8_t channel)
+{
+    return (s->registers[DPDMA_DSCR_STRT_ADDRE_CH(channel)] << 16)
+          + s->registers[DPDMA_DSCR_STRT_ADDR_CH(channel)];
+}
+
+static uint64_t xlnx_dpdma_descriptor_next_address(XlnxDPDMAState *s,
+                                                     uint8_t channel)
+{
+    return ((uint64_t)s->registers[DPDMA_DSCR_NEXT_ADDRE_CH(channel)] << 32)
+           + s->registers[DPDMA_DSCR_NEXT_ADDR_CH(channel)];
+}
+
+static bool xlnx_dpdma_is_channel_enabled(XlnxDPDMAState *s,
+                                            uint8_t channel)
+{
+    return (s->registers[DPDMA_CNTL_CH(channel)] & DPDMA_CNTL_CH_EN) != 0;
+}
+
+static bool xlnx_dpdma_is_channel_paused(XlnxDPDMAState *s,
+                                           uint8_t channel)
+{
+    return (s->registers[DPDMA_CNTL_CH(channel)] & DPDMA_CNTL_CH_PAUSED) != 0;
+}
+
+static inline bool xlnx_dpdma_is_channel_retriggered(XlnxDPDMAState *s,
+                                                       uint8_t channel)
+{
+    /* Clear the retriggered bit after reading it. */
+    bool channel_is_retriggered = s->registers[DPDMA_GBL]
+                                & DPDMA_GBL_RTRG_CH(channel);
+    s->registers[DPDMA_GBL] &= ~DPDMA_GBL_RTRG_CH(channel);
+    return channel_is_retriggered;
+}
+
+static inline bool xlnx_dpdma_is_channel_triggered(XlnxDPDMAState *s,
+                                                     uint8_t channel)
+{
+    return s->registers[DPDMA_GBL] & DPDMA_GBL_TRG_CH(channel);
+}
+
+static void xlnx_dpdma_update_desc_info(XlnxDPDMAState *s, uint8_t channel,
+                                          DPDMADescriptor *desc)
+{
+    s->registers[DPDMA_DSCR_NEXT_ADDRE_CH(channel)] =
+                                extract32(desc->address_extension, 0, 16);
+    s->registers[DPDMA_DSCR_NEXT_ADDR_CH(channel)] = desc->next_descriptor;
+    s->registers[DPDMA_PYLD_CUR_ADDRE_CH(channel)] =
+                                extract32(desc->address_extension, 16, 16);
+    s->registers[DPDMA_PYLD_CUR_ADDR_CH(channel)] = desc->source_address;
+    s->registers[DPDMA_VDO_CH(channel)] =
+                                extract32(desc->line_size_stride, 18, 14)
+                                + (extract32(desc->line_size_stride, 0, 18)
+                                  << 14);
+    s->registers[DPDMA_PYLD_SZ_CH(channel)] = desc->xfer_size;
+    s->registers[DPDMA_DSCR_ID_CH(channel)] = desc->descriptor_id;
+
+    /* Compute the status register with the descriptor information. */
+    s->registers[DPDMA_STATUS_CH(channel)] =
+                                extract32(desc->control, 0, 8) << 13;
+    if ((desc->control & DSCR_CTRL_EN_DSCR_DONE_INTR) != 0) {
+        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_DSCR_INTR;
+    }
+    if ((desc->control & DSCR_CTRL_EN_DSCR_UPDATE) != 0) {
+        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_DSCR_UP;
+    }
+    if ((desc->timestamp_msb & STATUS_DONE) != 0) {
+        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_DSCR_DONE;
+    }
+    if ((desc->control & DSCR_CTRL_IGNORE_DONE) != 0) {
+        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_IGNR_DONE;
+    }
+    if ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME) != 0) {
+        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_LDSCR_FRAME;
+    }
+    if ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR) != 0) {
+        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_LAST_DSCR;
+    }
+    if ((desc->control & DSCR_CTRL_ENABLE_CRC) != 0) {
+        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_CRC;
+    }
+    if ((desc->control & DSCR_CTRL_DESCRIPTOR_MODE) != 0) {
+        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_MODE;
+    }
+    if ((desc->control & DSCR_CTRL_AXI_BURST_TYPE) != 0) {
+        s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_BURST_TYPE;
+    }
+}
+
+static void xlnx_dpdma_dump_descriptor(DPDMADescriptor *desc)
+{
+    if (DEBUG_DPDMA) {
+        qemu_log("DUMP DESCRIPTOR:\n");
+        qemu_hexdump((char *)desc, stdout, "", sizeof(DPDMADescriptor));
+    }
+}
+
+static uint64_t xlnx_dpdma_read(void *opaque, hwaddr offset,
+                                unsigned size)
+{
+    XlnxDPDMAState *s = XLNX_DPDMA(opaque);
+
+    DPRINTF("read @%" HWADDR_PRIx "\n", offset);
+    offset = offset >> 2;
+
+    switch (offset) {
+    /*
+     * Trying to read a write only register.
+     */
+    case DPDMA_GBL:
+        return 0;
+    default:
+        assert(offset <= (0xFFC >> 2));
+        return s->registers[offset];
+    }
+    return 0;
+}
+
+static void xlnx_dpdma_write(void *opaque, hwaddr offset,
+                               uint64_t value, unsigned size)
+{
+    XlnxDPDMAState *s = XLNX_DPDMA(opaque);
+
+    DPRINTF("write @%" HWADDR_PRIx " = %" PRIx64 "\n", offset, value);
+    offset = offset >> 2;
+
+    switch (offset) {
+    case DPDMA_ISR:
+        s->registers[DPDMA_ISR] &= ~value;
+        xlnx_dpdma_update_irq(s);
+        break;
+    case DPDMA_IEN:
+        s->registers[DPDMA_IMR] &= ~value;
+        break;
+    case DPDMA_IDS:
+        s->registers[DPDMA_IMR] |= value;
+        break;
+    case DPDMA_EISR:
+        s->registers[DPDMA_EISR] &= ~value;
+        xlnx_dpdma_update_irq(s);
+        break;
+    case DPDMA_EIEN:
+        s->registers[DPDMA_EIMR] &= ~value;
+        break;
+    case DPDMA_EIDS:
+        s->registers[DPDMA_EIMR] |= value;
+        break;
+    case DPDMA_IMR:
+    case DPDMA_EIMR:
+    case DPDMA_DSCR_NEXT_ADDRE_CH(0):
+    case DPDMA_DSCR_NEXT_ADDRE_CH(1):
+    case DPDMA_DSCR_NEXT_ADDRE_CH(2):
+    case DPDMA_DSCR_NEXT_ADDRE_CH(3):
+    case DPDMA_DSCR_NEXT_ADDRE_CH(4):
+    case DPDMA_DSCR_NEXT_ADDRE_CH(5):
+    case DPDMA_DSCR_NEXT_ADDR_CH(0):
+    case DPDMA_DSCR_NEXT_ADDR_CH(1):
+    case DPDMA_DSCR_NEXT_ADDR_CH(2):
+    case DPDMA_DSCR_NEXT_ADDR_CH(3):
+    case DPDMA_DSCR_NEXT_ADDR_CH(4):
+    case DPDMA_DSCR_NEXT_ADDR_CH(5):
+    case DPDMA_PYLD_CUR_ADDRE_CH(0):
+    case DPDMA_PYLD_CUR_ADDRE_CH(1):
+    case DPDMA_PYLD_CUR_ADDRE_CH(2):
+    case DPDMA_PYLD_CUR_ADDRE_CH(3):
+    case DPDMA_PYLD_CUR_ADDRE_CH(4):
+    case DPDMA_PYLD_CUR_ADDRE_CH(5):
+    case DPDMA_PYLD_CUR_ADDR_CH(0):
+    case DPDMA_PYLD_CUR_ADDR_CH(1):
+    case DPDMA_PYLD_CUR_ADDR_CH(2):
+    case DPDMA_PYLD_CUR_ADDR_CH(3):
+    case DPDMA_PYLD_CUR_ADDR_CH(4):
+    case DPDMA_PYLD_CUR_ADDR_CH(5):
+    case DPDMA_STATUS_CH(0):
+    case DPDMA_STATUS_CH(1):
+    case DPDMA_STATUS_CH(2):
+    case DPDMA_STATUS_CH(3):
+    case DPDMA_STATUS_CH(4):
+    case DPDMA_STATUS_CH(5):
+    case DPDMA_VDO_CH(0):
+    case DPDMA_VDO_CH(1):
+    case DPDMA_VDO_CH(2):
+    case DPDMA_VDO_CH(3):
+    case DPDMA_VDO_CH(4):
+    case DPDMA_VDO_CH(5):
+    case DPDMA_PYLD_SZ_CH(0):
+    case DPDMA_PYLD_SZ_CH(1):
+    case DPDMA_PYLD_SZ_CH(2):
+    case DPDMA_PYLD_SZ_CH(3):
+    case DPDMA_PYLD_SZ_CH(4):
+    case DPDMA_PYLD_SZ_CH(5):
+    case DPDMA_DSCR_ID_CH(0):
+    case DPDMA_DSCR_ID_CH(1):
+    case DPDMA_DSCR_ID_CH(2):
+    case DPDMA_DSCR_ID_CH(3):
+    case DPDMA_DSCR_ID_CH(4):
+    case DPDMA_DSCR_ID_CH(5):
+        /*
+         * Trying to write to a read only register..
+         */
+        break;
+    case DPDMA_GBL:
+        /*
+         * This is a write only register so it's read as zero in the read
+         * callback.
+         * We store the value anyway so we can know if the channel is
+         * enabled.
+         */
+        s->registers[offset] |= value & 0x00000FFF;
+        break;
+    case DPDMA_DSCR_STRT_ADDRE_CH(0):
+    case DPDMA_DSCR_STRT_ADDRE_CH(1):
+    case DPDMA_DSCR_STRT_ADDRE_CH(2):
+    case DPDMA_DSCR_STRT_ADDRE_CH(3):
+    case DPDMA_DSCR_STRT_ADDRE_CH(4):
+    case DPDMA_DSCR_STRT_ADDRE_CH(5):
+        value &= 0x0000FFFF;
+        s->registers[offset] = value;
+        break;
+    case DPDMA_CNTL_CH(0):
+        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(0);
+        value &= 0x3FFFFFFF;
+        s->registers[offset] = value;
+        break;
+    case DPDMA_CNTL_CH(1):
+        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(1);
+        value &= 0x3FFFFFFF;
+        s->registers[offset] = value;
+        break;
+    case DPDMA_CNTL_CH(2):
+        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(2);
+        value &= 0x3FFFFFFF;
+        s->registers[offset] = value;
+        break;
+    case DPDMA_CNTL_CH(3):
+        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(3);
+        value &= 0x3FFFFFFF;
+        s->registers[offset] = value;
+        break;
+    case DPDMA_CNTL_CH(4):
+        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(4);
+        value &= 0x3FFFFFFF;
+        s->registers[offset] = value;
+        break;
+    case DPDMA_CNTL_CH(5):
+        s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(5);
+        value &= 0x3FFFFFFF;
+        s->registers[offset] = value;
+        break;
+    default:
+        assert(offset <= (0xFFC >> 2));
+        s->registers[offset] = value;
+        break;
+    }
+}
+
+static const MemoryRegionOps dma_ops = {
+    .read = xlnx_dpdma_read,
+    .write = xlnx_dpdma_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void xlnx_dpdma_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    XlnxDPDMAState *s = XLNX_DPDMA(obj);
+
+    memory_region_init_io(&s->iomem, obj, &dma_ops, s,
+                          TYPE_XLNX_DPDMA, 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+}
+
+static void xlnx_dpdma_reset(DeviceState *dev)
+{
+    XlnxDPDMAState *s = XLNX_DPDMA(dev);
+    size_t i;
+
+    memset(s->registers, 0, sizeof(s->registers));
+    s->registers[DPDMA_IMR] =  0x07FFFFFF;
+    s->registers[DPDMA_EIMR] = 0xFFFFFFFF;
+    s->registers[DPDMA_ALC0_MIN] = 0x0000FFFF;
+    s->registers[DPDMA_ALC1_MIN] = 0x0000FFFF;
+
+    for (i = 0; i < 6; i++) {
+        s->data[i] = NULL;
+        s->operation_finished[i] = true;
+    }
+}
+
+static void xlnx_dpdma_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->vmsd = &vmstate_xlnx_dpdma;
+    dc->reset = xlnx_dpdma_reset;
+}
+
+static const TypeInfo xlnx_dpdma_info = {
+    .name          = TYPE_XLNX_DPDMA,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(XlnxDPDMAState),
+    .instance_init = xlnx_dpdma_init,
+    .class_init    = xlnx_dpdma_class_init,
+};
+
+static void xlnx_dpdma_register_types(void)
+{
+    type_register_static(&xlnx_dpdma_info);
+}
+
+size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel,
+                                    bool one_desc)
+{
+    uint64_t desc_addr;
+    uint64_t source_addr[6];
+    DPDMADescriptor desc;
+    bool done = false;
+    size_t ptr = 0;
+
+    assert(channel <= 5);
+
+    DPRINTF("start dpdma channel 0x%" PRIX8 "\n", channel);
+
+    if (!xlnx_dpdma_is_channel_triggered(s, channel)) {
+        DPRINTF("Channel isn't triggered..\n");
+        return 0;
+    }
+
+    if (!xlnx_dpdma_is_channel_enabled(s, channel)) {
+        DPRINTF("Channel isn't enabled..\n");
+        return 0;
+    }
+
+    if (xlnx_dpdma_is_channel_paused(s, channel)) {
+        DPRINTF("Channel is paused..\n");
+        return 0;
+    }
+
+    do {
+        if ((s->operation_finished[channel])
+          || xlnx_dpdma_is_channel_retriggered(s, channel)) {
+            desc_addr = xlnx_dpdma_descriptor_start_address(s, channel);
+            s->operation_finished[channel] = false;
+        } else {
+            desc_addr = xlnx_dpdma_descriptor_next_address(s, channel);
+        }
+
+        if (dma_memory_read(&address_space_memory, desc_addr, &desc,
+                            sizeof(DPDMADescriptor))) {
+            s->registers[DPDMA_EISR] |= ((1 << 1) << channel);
+            xlnx_dpdma_update_irq(s);
+            s->operation_finished[channel] = true;
+            DPRINTF("Can't get the descriptor.\n");
+            break;
+        }
+
+        xlnx_dpdma_update_desc_info(s, channel, &desc);
+
+#ifdef DEBUG_DPDMA
+        xlnx_dpdma_dump_descriptor(&desc);
+#endif
+
+        DPRINTF("location of the descriptor: %" PRIx64 "\n", desc_addr);
+        if (!xlnx_dpdma_desc_is_valid(&desc)) {
+            s->registers[DPDMA_EISR] |= ((1 << 7) << channel);
+            xlnx_dpdma_update_irq(s);
+            s->operation_finished[channel] = true;
+            DPRINTF("Invalid descriptor..\n");
+            break;
+        }
+
+        if (xlnx_dpdma_desc_crc_enabled(&desc)
+            && !xlnx_dpdma_desc_check_crc(&desc)) {
+            s->registers[DPDMA_EISR] |= ((1 << 13) << channel);
+            xlnx_dpdma_update_irq(s);
+            s->operation_finished[channel] = true;
+            DPRINTF("Bad CRC for descriptor..\n");
+            break;
+        }
+
+        if (xlnx_dpdma_desc_is_already_done(&desc)
+            && !xlnx_dpdma_desc_ignore_done_bit(&desc)) {
+            /* We are trying to process an already processed descriptor. */
+            s->registers[DPDMA_EISR] |= ((1 << 25) << channel);
+            xlnx_dpdma_update_irq(s);
+            s->operation_finished[channel] = true;
+            DPRINTF("Already processed descriptor..\n");
+            break;
+        }
+
+        done = xlnx_dpdma_desc_is_last(&desc)
+             || xlnx_dpdma_desc_is_last_of_frame(&desc);
+
+        s->operation_finished[channel] = done;
+        if (s->data[channel]) {
+            int64_t transfer_len = xlnx_dpdma_desc_get_transfer_size(&desc);
+            uint32_t line_size = xlnx_dpdma_desc_get_line_size(&desc);
+            uint32_t line_stride = xlnx_dpdma_desc_get_line_stride(&desc);
+            if (xlnx_dpdma_desc_is_contiguous(&desc)) {
+                source_addr[0] = xlnx_dpdma_desc_get_source_address(&desc, 0);
+                while (transfer_len != 0) {
+                    if (dma_memory_read(&address_space_memory,
+                                        source_addr[0],
+                                        &s->data[channel][ptr],
+                                        line_size)) {
+                        s->registers[DPDMA_ISR] |= ((1 << 12) << channel);
+                        xlnx_dpdma_update_irq(s);
+                        DPRINTF("Can't get data.\n");
+                        break;
+                    }
+                    ptr += line_size;
+                    transfer_len -= line_size;
+                    source_addr[0] += line_stride;
+                }
+            } else {
+                DPRINTF("Source address:\n");
+                int frag;
+                for (frag = 0; frag < 5; frag++) {
+                    source_addr[frag] =
+                          xlnx_dpdma_desc_get_source_address(&desc, frag);
+                    DPRINTF("Fragment %u: %" PRIx64 "\n", frag + 1,
+                            source_addr[frag]);
+                }
+
+                frag = 0;
+                while ((transfer_len < 0) && (frag < 5)) {
+                    size_t fragment_len = DPDMA_FRAG_MAX_SZ
+                                    - (source_addr[frag] % DPDMA_FRAG_MAX_SZ);
+
+                    if (dma_memory_read(&address_space_memory,
+                                        source_addr[frag],
+                                        &(s->data[channel][ptr]),
+                                        fragment_len)) {
+                        s->registers[DPDMA_ISR] |= ((1 << 12) << channel);
+                        xlnx_dpdma_update_irq(s);
+                        DPRINTF("Can't get data.\n");
+                        break;
+                    }
+                    ptr += fragment_len;
+                    transfer_len -= fragment_len;
+                    frag += 1;
+                }
+            }
+        }
+
+        if (xlnx_dpdma_desc_update_enabled(&desc)) {
+            /* The descriptor need to be updated when it's completed. */
+            DPRINTF("update the descriptor with the done flag set.\n");
+            xlnx_dpdma_desc_set_done(&desc);
+            dma_memory_write(&address_space_memory, desc_addr, &desc,
+                             sizeof(DPDMADescriptor));
+        }
+
+        if (xlnx_dpdma_desc_completion_interrupt(&desc)) {
+            DPRINTF("completion interrupt enabled!\n");
+            s->registers[DPDMA_ISR] |= (1 << channel);
+            xlnx_dpdma_update_irq(s);
+        }
+
+    } while (!done && !one_desc);
+
+    return ptr;
+}
+
+void xlnx_dpdma_set_host_data_location(XlnxDPDMAState *s, uint8_t channel,
+                                         void *p)
+{
+    if (!s) {
+        qemu_log_mask(LOG_UNIMP, "DPDMA client not attached to valid DPDMA"
+                      " instance\n");
+        return;
+    }
+
+    assert(channel <= 5);
+    s->data[channel] = p;
+}
+
+void xlnx_dpdma_trigger_vsync_irq(XlnxDPDMAState *s)
+{
+    s->registers[DPDMA_ISR] |= (1 << 27);
+    xlnx_dpdma_update_irq(s);
+}
+
+type_init(xlnx_dpdma_register_types)
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
index 9b1b004..dabef4a 100644
--- a/hw/gpio/omap_gpio.c
+++ b/hw/gpio/omap_gpio.c
@@ -23,6 +23,7 @@
 #include "hw/arm/omap.h"
 #include "hw/sysbus.h"
 #include "qemu/error-report.h"
+#include "qapi/error.h"
 
 struct omap_gpio_s {
     qemu_irq irq;
@@ -678,48 +679,46 @@
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static int omap_gpio_init(SysBusDevice *sbd)
+static void omap_gpio_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
-    struct omap_gpif_s *s = OMAP1_GPIO(dev);
+    DeviceState *dev = DEVICE(obj);
+    struct omap_gpif_s *s = OMAP1_GPIO(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
-    if (!s->clk) {
-        error_report("omap-gpio: clk not connected");
-        return -1;
-    }
     qdev_init_gpio_in(dev, omap_gpio_set, 16);
     qdev_init_gpio_out(dev, s->omap1.handler, 16);
     sysbus_init_irq(sbd, &s->omap1.irq);
-    memory_region_init_io(&s->iomem, OBJECT(s), &omap_gpio_ops, &s->omap1,
+    memory_region_init_io(&s->iomem, obj, &omap_gpio_ops, &s->omap1,
                           "omap.gpio", 0x1000);
     sysbus_init_mmio(sbd, &s->iomem);
-    return 0;
 }
 
-static int omap2_gpio_init(SysBusDevice *sbd)
+static void omap_gpio_realize(DeviceState *dev, Error **errp)
 {
-    DeviceState *dev = DEVICE(sbd);
+    struct omap_gpif_s *s = OMAP1_GPIO(dev);
+
+    if (!s->clk) {
+        error_setg(errp, "omap-gpio: clk not connected");
+    }
+}
+
+static void omap2_gpio_realize(DeviceState *dev, Error **errp)
+{
     struct omap2_gpif_s *s = OMAP2_GPIO(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     int i;
 
     if (!s->iclk) {
-        error_report("omap2-gpio: iclk not connected");
-        return -1;
+        error_setg(errp, "omap2-gpio: iclk not connected");
+        return;
     }
 
     s->modulecount = s->mpu_model < omap2430 ? 4
-                   : s->mpu_model < omap3430 ? 5
-                   : 6;
-
-    for (i = 0; i < s->modulecount; i++) {
-        if (!s->fclk[i]) {
-            error_report("omap2-gpio: fclk%d not connected", i);
-            return -1;
-        }
-    }
+        : s->mpu_model < omap3430 ? 5
+        : 6;
 
     if (s->mpu_model < omap3430) {
-        memory_region_init_io(&s->iomem, OBJECT(s), &omap2_gpif_top_ops, s,
+        memory_region_init_io(&s->iomem, OBJECT(dev), &omap2_gpif_top_ops, s,
                               "omap2.gpio", 0x1000);
         sysbus_init_mmio(sbd, &s->iomem);
     }
@@ -732,17 +731,20 @@
     for (i = 0; i < s->modulecount; i++) {
         struct omap2_gpio_s *m = &s->modules[i];
 
+        if (!s->fclk[i]) {
+            error_setg(errp, "omap2-gpio: fclk%d not connected", i);
+            return;
+        }
+
         m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
         m->handler = &s->handler[i * 32];
         sysbus_init_irq(sbd, &m->irq[0]); /* mpu irq */
         sysbus_init_irq(sbd, &m->irq[1]); /* dsp irq */
         sysbus_init_irq(sbd, &m->wkup);
-        memory_region_init_io(&m->iomem, OBJECT(s), &omap2_gpio_module_ops, m,
+        memory_region_init_io(&m->iomem, OBJECT(dev), &omap2_gpio_module_ops, m,
                               "omap.gpio-module", 0x1000);
         sysbus_init_mmio(sbd, &m->iomem);
     }
-
-    return 0;
 }
 
 /* Using qdev pointer properties for the clocks is not ideal.
@@ -766,9 +768,8 @@
 static void omap_gpio_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = omap_gpio_init;
+    dc->realize = omap_gpio_realize;
     dc->reset = omap_gpif_reset;
     dc->props = omap_gpio_properties;
     /* Reason: pointer property "clk" */
@@ -779,6 +780,7 @@
     .name          = TYPE_OMAP1_GPIO,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct omap_gpif_s),
+    .instance_init = omap_gpio_init,
     .class_init    = omap_gpio_class_init,
 };
 
@@ -797,9 +799,8 @@
 static void omap2_gpio_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = omap2_gpio_init;
+    dc->realize = omap2_gpio_realize;
     dc->reset = omap2_gpif_reset;
     dc->props = omap2_gpio_properties;
     /* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index 44faeb2..4ae2aa1 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -341,20 +341,6 @@
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static int pl061_initfn(SysBusDevice *sbd)
-{
-    DeviceState *dev = DEVICE(sbd);
-    PL061State *s = PL061(dev);
-
-    memory_region_init_io(&s->iomem, OBJECT(s), &pl061_ops, s, "pl061", 0x1000);
-    sysbus_init_mmio(sbd, &s->iomem);
-    sysbus_init_irq(sbd, &s->irq);
-    qdev_init_gpio_in(dev, pl061_set_irq, 8);
-    qdev_init_gpio_out(dev, s->out, 8);
-
-    return 0;
-}
-
 static void pl061_luminary_init(Object *obj)
 {
     PL061State *s = PL061(obj);
@@ -366,17 +352,23 @@
 static void pl061_init(Object *obj)
 {
     PL061State *s = PL061(obj);
+    DeviceState *dev = DEVICE(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
     s->id = pl061_id;
     s->rsvd_start = 0x424;
+
+    memory_region_init_io(&s->iomem, obj, &pl061_ops, s, "pl061", 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+    qdev_init_gpio_in(dev, pl061_set_irq, 8);
+    qdev_init_gpio_out(dev, s->out, 8);
 }
 
 static void pl061_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = pl061_initfn;
     dc->vmsd = &vmstate_pl061;
     dc->reset = &pl061_reset;
 }
diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index 555da28..15865e1 100644
--- a/hw/gpio/zaurus.c
+++ b/hw/gpio/zaurus.c
@@ -167,19 +167,18 @@
         s->gpio_level &= ~(1 << line);
 }
 
-static int scoop_init(SysBusDevice *sbd)
+static void scoop_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
-    ScoopInfo *s = SCOOP(dev);
+    DeviceState *dev = DEVICE(obj);
+    ScoopInfo *s = SCOOP(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
     s->status = 0x02;
     qdev_init_gpio_out(dev, s->handler, 16);
     qdev_init_gpio_in(dev, scoop_gpio_set, 16);
-    memory_region_init_io(&s->iomem, OBJECT(s), &scoop_ops, s, "scoop", 0x1000);
+    memory_region_init_io(&s->iomem, obj, &scoop_ops, s, "scoop", 0x1000);
 
     sysbus_init_mmio(sbd, &s->iomem);
-
-    return 0;
 }
 
 static int scoop_post_load(void *opaque, int version_id)
@@ -239,9 +238,7 @@
 static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = scoop_init;
     dc->desc = "Scoop2 Sharp custom ASIC";
     dc->vmsd = &vmstate_scoop_regs;
 }
@@ -250,6 +247,7 @@
     .name          = TYPE_SCOOP,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(ScoopInfo),
+    .instance_init = scoop_init,
     .class_init    = scoop_sysbus_class_init,
 };
 
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index 1fd54ed..a081b8e 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -1,4 +1,5 @@
 common-obj-y += core.o smbus.o smbus_eeprom.o
+common-obj-$(CONFIG_DDC) += i2c-ddc.o
 common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
 common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o
 common-obj-$(CONFIG_APM) += pm_smbus.o
diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c
index 6ed2060..d3a2989 100644
--- a/hw/i2c/bitbang_i2c.c
+++ b/hw/i2c/bitbang_i2c.c
@@ -210,13 +210,14 @@
     }
 }
 
-static int gpio_i2c_init(SysBusDevice *sbd)
+static void gpio_i2c_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
-    GPIOI2CState *s = GPIO_I2C(dev);
+    DeviceState *dev = DEVICE(obj);
+    GPIOI2CState *s = GPIO_I2C(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
     I2CBus *bus;
 
-    memory_region_init(&s->dummy_iomem, OBJECT(s), "gpio_i2c", 0);
+    memory_region_init(&s->dummy_iomem, obj, "gpio_i2c", 0);
     sysbus_init_mmio(sbd, &s->dummy_iomem);
 
     bus = i2c_init_bus(dev, "i2c");
@@ -224,16 +225,12 @@
 
     qdev_init_gpio_in(dev, bitbang_i2c_gpio_set, 2);
     qdev_init_gpio_out(dev, &s->out, 1);
-
-    return 0;
 }
 
 static void gpio_i2c_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = gpio_i2c_init;
     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
     dc->desc = "Virtual GPIO to I2C bridge";
 }
@@ -242,6 +239,7 @@
     .name          = TYPE_GPIO_I2C,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(GPIOI2CState),
+    .instance_init = gpio_i2c_init,
     .class_init    = gpio_i2c_class_init,
 };
 
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index ba22104..abb3efb 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -10,12 +10,19 @@
 #include "qemu/osdep.h"
 #include "hw/i2c/i2c.h"
 
+typedef struct I2CNode I2CNode;
+
+struct I2CNode {
+    I2CSlave *elt;
+    QLIST_ENTRY(I2CNode) next;
+};
+
 struct I2CBus
 {
     BusState qbus;
-    I2CSlave *current_dev;
-    I2CSlave *dev;
+    QLIST_HEAD(, I2CNode) current_devs;
     uint8_t saved_address;
+    bool broadcast;
 };
 
 static Property i2c_props[] = {
@@ -36,17 +43,12 @@
 {
     I2CBus *bus = opaque;
 
-    bus->saved_address = bus->current_dev ? bus->current_dev->address : -1;
-}
-
-static int i2c_bus_post_load(void *opaque, int version_id)
-{
-    I2CBus *bus = opaque;
-
-    /* The bus is loaded before attached devices, so load and save the
-       current device id.  Devices will check themselves as loaded.  */
-    bus->current_dev = NULL;
-    return 0;
+    bus->saved_address = -1;
+    if (!QLIST_EMPTY(&bus->current_devs)) {
+        if (!bus->broadcast) {
+            bus->saved_address = QLIST_FIRST(&bus->current_devs)->elt->address;
+        }
+    }
 }
 
 static const VMStateDescription vmstate_i2c_bus = {
@@ -54,9 +56,9 @@
     .version_id = 1,
     .minimum_version_id = 1,
     .pre_save = i2c_bus_pre_save,
-    .post_load = i2c_bus_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_UINT8(saved_address, I2CBus),
+        VMSTATE_BOOL(broadcast, I2CBus),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -67,6 +69,7 @@
     I2CBus *bus;
 
     bus = I2C_BUS(qbus_create(TYPE_I2C_BUS, parent, name));
+    QLIST_INIT(&bus->current_devs);
     vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
     return bus;
 }
@@ -79,7 +82,7 @@
 /* Return nonzero if bus is busy.  */
 int i2c_bus_busy(I2CBus *bus)
 {
-    return bus->current_dev != NULL;
+    return !QLIST_EMPTY(&bus->current_devs);
 }
 
 /* Returns non-zero if the address is not valid.  */
@@ -87,95 +90,127 @@
 int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv)
 {
     BusChild *kid;
-    I2CSlave *slave = NULL;
     I2CSlaveClass *sc;
+    I2CNode *node;
+
+    if (address == 0x00) {
+        /*
+         * This is a broadcast, the current_devs will be all the devices of the
+         * bus.
+         */
+        bus->broadcast = true;
+    }
 
     QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
         DeviceState *qdev = kid->child;
         I2CSlave *candidate = I2C_SLAVE(qdev);
-        if (candidate->address == address) {
-            slave = candidate;
-            break;
+        if ((candidate->address == address) || (bus->broadcast)) {
+            node = g_malloc(sizeof(struct I2CNode));
+            node->elt = candidate;
+            QLIST_INSERT_HEAD(&bus->current_devs, node, next);
+            if (!bus->broadcast) {
+                break;
+            }
         }
     }
 
-    if (!slave) {
+    if (QLIST_EMPTY(&bus->current_devs)) {
         return 1;
     }
 
-    sc = I2C_SLAVE_GET_CLASS(slave);
-    /* If the bus is already busy, assume this is a repeated
-       start condition.  */
-    bus->current_dev = slave;
-    if (sc->event) {
-        sc->event(slave, recv ? I2C_START_RECV : I2C_START_SEND);
+    QLIST_FOREACH(node, &bus->current_devs, next) {
+        sc = I2C_SLAVE_GET_CLASS(node->elt);
+        /* If the bus is already busy, assume this is a repeated
+           start condition.  */
+        if (sc->event) {
+            sc->event(node->elt, recv ? I2C_START_RECV : I2C_START_SEND);
+        }
     }
     return 0;
 }
 
 void i2c_end_transfer(I2CBus *bus)
 {
-    I2CSlave *dev = bus->current_dev;
     I2CSlaveClass *sc;
+    I2CNode *node, *next;
 
-    if (!dev) {
+    if (QLIST_EMPTY(&bus->current_devs)) {
         return;
     }
 
-    sc = I2C_SLAVE_GET_CLASS(dev);
-    if (sc->event) {
-        sc->event(dev, I2C_FINISH);
+    QLIST_FOREACH_SAFE(node, &bus->current_devs, next, next) {
+        sc = I2C_SLAVE_GET_CLASS(node->elt);
+        if (sc->event) {
+            sc->event(node->elt, I2C_FINISH);
+        }
+        QLIST_REMOVE(node, next);
+        g_free(node);
     }
+    bus->broadcast = false;
+}
 
-    bus->current_dev = NULL;
+int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
+{
+    I2CSlaveClass *sc;
+    I2CNode *node;
+    int ret = 0;
+
+    if (send) {
+        QLIST_FOREACH(node, &bus->current_devs, next) {
+            sc = I2C_SLAVE_GET_CLASS(node->elt);
+            if (sc->send) {
+                ret = ret || sc->send(node->elt, *data);
+            } else {
+                ret = -1;
+            }
+        }
+        return ret ? -1 : 0;
+    } else {
+        if ((QLIST_EMPTY(&bus->current_devs)) || (bus->broadcast)) {
+            return -1;
+        }
+
+        sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
+        if (sc->recv) {
+            ret = sc->recv(QLIST_FIRST(&bus->current_devs)->elt);
+            if (ret < 0) {
+                return ret;
+            } else {
+                *data = ret;
+                return 0;
+            }
+        }
+        return -1;
+    }
 }
 
 int i2c_send(I2CBus *bus, uint8_t data)
 {
-    I2CSlave *dev = bus->current_dev;
-    I2CSlaveClass *sc;
-
-    if (!dev) {
-        return -1;
-    }
-
-    sc = I2C_SLAVE_GET_CLASS(dev);
-    if (sc->send) {
-        return sc->send(dev, data);
-    }
-
-    return -1;
+    return i2c_send_recv(bus, &data, true);
 }
 
 int i2c_recv(I2CBus *bus)
 {
-    I2CSlave *dev = bus->current_dev;
-    I2CSlaveClass *sc;
+    uint8_t data;
+    int ret = i2c_send_recv(bus, &data, false);
 
-    if (!dev) {
-        return -1;
-    }
-
-    sc = I2C_SLAVE_GET_CLASS(dev);
-    if (sc->recv) {
-        return sc->recv(dev);
-    }
-
-    return -1;
+    return ret < 0 ? ret : data;
 }
 
 void i2c_nack(I2CBus *bus)
 {
-    I2CSlave *dev = bus->current_dev;
     I2CSlaveClass *sc;
+    I2CNode *node;
 
-    if (!dev) {
+    if (QLIST_EMPTY(&bus->current_devs)) {
         return;
     }
 
-    sc = I2C_SLAVE_GET_CLASS(dev);
-    if (sc->event) {
-        sc->event(dev, I2C_NACK);
+    QLIST_FOREACH(node, &bus->current_devs, next) {
+        sc = I2C_SLAVE_GET_CLASS(node->elt);
+        if (sc->event) {
+            sc->event(node->elt, I2C_NACK);
+        }
     }
 }
 
@@ -183,9 +218,13 @@
 {
     I2CSlave *dev = opaque;
     I2CBus *bus;
+    I2CNode *node;
+
     bus = I2C_BUS(qdev_get_parent_bus(DEVICE(dev)));
-    if (bus->saved_address == dev->address) {
-        bus->current_dev = dev;
+    if ((bus->saved_address == dev->address) || (bus->broadcast)) {
+        node = g_malloc(sizeof(struct I2CNode));
+        node->elt = dev;
+        QLIST_INSERT_HEAD(&bus->current_devs, node, next);
     }
     return 0;
 }
diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c
index 8c2a2c1..c96fa7d 100644
--- a/hw/i2c/exynos4210_i2c.c
+++ b/hw/i2c/exynos4210_i2c.c
@@ -299,33 +299,32 @@
     s->scl_free = true;
 }
 
-static int exynos4210_i2c_realize(SysBusDevice *sbd)
+static void exynos4210_i2c_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
-    Exynos4210I2CState *s = EXYNOS4_I2C(dev);
+    DeviceState *dev = DEVICE(obj);
+    Exynos4210I2CState *s = EXYNOS4_I2C(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
-    memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_i2c_ops, s,
+    memory_region_init_io(&s->iomem, obj, &exynos4210_i2c_ops, s,
                           TYPE_EXYNOS4_I2C, EXYNOS4_I2C_MEM_SIZE);
     sysbus_init_mmio(sbd, &s->iomem);
     sysbus_init_irq(sbd, &s->irq);
     s->bus = i2c_init_bus(dev, "i2c");
-    return 0;
 }
 
 static void exynos4210_i2c_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *sbdc = SYS_BUS_DEVICE_CLASS(klass);
 
     dc->vmsd = &exynos4210_i2c_vmstate;
     dc->reset = exynos4210_i2c_reset;
-    sbdc->init = exynos4210_i2c_realize;
 }
 
 static const TypeInfo exynos4210_i2c_type_info = {
     .name = TYPE_EXYNOS4_I2C,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210I2CState),
+    .instance_init = exynos4210_i2c_init,
     .class_init = exynos4210_i2c_class_init,
 };
 
diff --git a/hw/i2c/i2c-ddc.c b/hw/i2c/i2c-ddc.c
new file mode 100644
index 0000000..1227212
--- /dev/null
+++ b/hw/i2c/i2c-ddc.c
@@ -0,0 +1,308 @@
+/* A simple I2C slave for returning monitor EDID data via DDC.
+ *
+ * Copyright (c) 2011 Linaro Limited
+ * Written by Peter Maydell
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  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 "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/i2c/i2c.h"
+#include "hw/i2c/i2c-ddc.h"
+
+#ifndef DEBUG_I2CDDC
+#define DEBUG_I2CDDC 0
+#endif
+
+#define DPRINTF(fmt, ...) do {                                                 \
+    if (DEBUG_I2CDDC) {                                                        \
+        qemu_log("i2c-ddc: " fmt , ## __VA_ARGS__);                            \
+    }                                                                          \
+} while (0);
+
+/* Structure defining a monitor's characteristics in a
+ * readable format: this should be passed to build_edid_blob()
+ * to convert it into the 128 byte binary EDID blob.
+ * Not all bits of the EDID are customisable here.
+ */
+struct EDIDData {
+    char manuf_id[3]; /* three upper case letters */
+    uint16_t product_id;
+    uint32_t serial_no;
+    uint8_t manuf_week;
+    int manuf_year;
+    uint8_t h_cm;
+    uint8_t v_cm;
+    uint8_t gamma;
+    char monitor_name[14];
+    char serial_no_string[14];
+    /* Range limits */
+    uint8_t vmin; /* Hz */
+    uint8_t vmax; /* Hz */
+    uint8_t hmin; /* kHz */
+    uint8_t hmax; /* kHz */
+    uint8_t pixclock; /* MHz / 10 */
+    uint8_t timing_data[18];
+};
+
+typedef struct EDIDData EDIDData;
+
+/* EDID data for a simple LCD monitor */
+static const EDIDData lcd_edid = {
+    /* The manuf_id ought really to be an assigned EISA ID */
+    .manuf_id = "QMU",
+    .product_id = 0,
+    .serial_no = 1,
+    .manuf_week = 1,
+    .manuf_year = 2011,
+    .h_cm = 40,
+    .v_cm = 30,
+    .gamma = 0x78,
+    .monitor_name = "QEMU monitor",
+    .serial_no_string = "1",
+    .vmin = 40,
+    .vmax = 120,
+    .hmin = 30,
+    .hmax = 100,
+    .pixclock = 18,
+    .timing_data = {
+        /* Borrowed from a 21" LCD */
+        0x48, 0x3f, 0x40, 0x30, 0x62, 0xb0, 0x32, 0x40, 0x40,
+        0xc0, 0x13, 0x00, 0x98, 0x32, 0x11, 0x00, 0x00, 0x1e
+    }
+};
+
+static uint8_t manuf_char_to_int(char c)
+{
+    return (c - 'A') & 0x1f;
+}
+
+static void write_ascii_descriptor_block(uint8_t *descblob, uint8_t blocktype,
+                                         const char *string)
+{
+    /* Write an EDID Descriptor Block of the "ascii string" type */
+    int i;
+    descblob[0] = descblob[1] = descblob[2] = descblob[4] = 0;
+    descblob[3] = blocktype;
+    /* The rest is 13 bytes of ASCII; if less then the rest must
+     * be filled with newline then spaces
+     */
+    for (i = 5; i < 19; i++) {
+        descblob[i] = string[i - 5];
+        if (!descblob[i]) {
+            break;
+        }
+    }
+    if (i < 19) {
+        descblob[i++] = '\n';
+    }
+    for ( ; i < 19; i++) {
+        descblob[i] = ' ';
+    }
+}
+
+static void write_range_limits_descriptor(const EDIDData *edid,
+                                          uint8_t *descblob)
+{
+    int i;
+    descblob[0] = descblob[1] = descblob[2] = descblob[4] = 0;
+    descblob[3] = 0xfd;
+    descblob[5] = edid->vmin;
+    descblob[6] = edid->vmax;
+    descblob[7] = edid->hmin;
+    descblob[8] = edid->hmax;
+    descblob[9] = edid->pixclock;
+    descblob[10] = 0;
+    descblob[11] = 0xa;
+    for (i = 12; i < 19; i++) {
+        descblob[i] = 0x20;
+    }
+}
+
+static void build_edid_blob(const EDIDData *edid, uint8_t *blob)
+{
+    /* Write an EDID 1.3 format blob (128 bytes) based
+     * on the EDIDData structure.
+     */
+    int i;
+    uint8_t cksum;
+
+    /* 00-07 : header */
+    blob[0] = blob[7] = 0;
+    for (i = 1 ; i < 7; i++) {
+        blob[i] = 0xff;
+    }
+    /* 08-09 : manufacturer ID */
+    blob[8] = (manuf_char_to_int(edid->manuf_id[0]) << 2)
+        | (manuf_char_to_int(edid->manuf_id[1]) >> 3);
+    blob[9] = (manuf_char_to_int(edid->manuf_id[1]) << 5)
+        | manuf_char_to_int(edid->manuf_id[2]);
+    /* 10-11 : product ID code */
+    blob[10] = edid->product_id;
+    blob[11] = edid->product_id >> 8;
+    blob[12] = edid->serial_no;
+    blob[13] = edid->serial_no >> 8;
+    blob[14] = edid->serial_no >> 16;
+    blob[15] = edid->serial_no >> 24;
+    /* 16 : week of manufacture */
+    blob[16] = edid->manuf_week;
+    /* 17 : year of manufacture - 1990 */
+    blob[17] = edid->manuf_year - 1990;
+    /* 18, 19 : EDID version and revision */
+    blob[18] = 1;
+    blob[19] = 3;
+    /* 20 - 24 : basic display parameters */
+    /* We are always a digital display */
+    blob[20] = 0x80;
+    /* 21, 22 : max h/v size in cm */
+    blob[21] = edid->h_cm;
+    blob[22] = edid->v_cm;
+    /* 23 : gamma (divide by 100 then add 1 for actual value) */
+    blob[23] = edid->gamma;
+    /* 24 feature support: no power management, RGB, preferred timing mode,
+     * standard colour space
+     */
+    blob[24] = 0x0e;
+    /* 25 - 34 : chromaticity coordinates. These are the
+     * standard sRGB chromaticity values
+     */
+    blob[25] = 0xee;
+    blob[26] = 0x91;
+    blob[27] = 0xa3;
+    blob[28] = 0x54;
+    blob[29] = 0x4c;
+    blob[30] = 0x99;
+    blob[31] = 0x26;
+    blob[32] = 0x0f;
+    blob[33] = 0x50;
+    blob[34] = 0x54;
+    /* 35, 36 : Established timings: claim to support everything */
+    blob[35] = blob[36] = 0xff;
+    /* 37 : manufacturer's reserved timing: none */
+    blob[37] = 0;
+    /* 38 - 53 : standard timing identification
+     * don't claim anything beyond what the 'established timings'
+     * already provide. Unused slots must be (0x1, 0x1)
+     */
+    for (i = 38; i < 54; i++) {
+        blob[i] = 0x1;
+    }
+    /* 54 - 71 : descriptor block 1 : must be preferred timing data */
+    memcpy(blob + 54, edid->timing_data, 18);
+    /* 72 - 89, 90 - 107, 108 - 125 : descriptor block 2, 3, 4
+     * Order not important, but we must have a monitor name and a
+     * range limits descriptor.
+     */
+    write_range_limits_descriptor(edid, blob + 72);
+    write_ascii_descriptor_block(blob + 90, 0xfc, edid->monitor_name);
+    write_ascii_descriptor_block(blob + 108, 0xff, edid->serial_no_string);
+
+    /* 126 : extension flag */
+    blob[126] = 0;
+
+    cksum = 0;
+    for (i = 0; i < 127; i++) {
+        cksum += blob[i];
+    }
+    /* 127 : checksum */
+    blob[127] = -cksum;
+    if (DEBUG_I2CDDC) {
+        qemu_hexdump((char *)blob, stdout, "", 128);
+    }
+}
+
+static void i2c_ddc_reset(DeviceState *ds)
+{
+    I2CDDCState *s = I2CDDC(ds);
+
+    s->firstbyte = false;
+    s->reg = 0;
+}
+
+static void i2c_ddc_event(I2CSlave *i2c, enum i2c_event event)
+{
+    I2CDDCState *s = I2CDDC(i2c);
+
+    if (event == I2C_START_SEND) {
+        s->firstbyte = true;
+    }
+}
+
+static int i2c_ddc_rx(I2CSlave *i2c)
+{
+    I2CDDCState *s = I2CDDC(i2c);
+
+    int value;
+    value = s->edid_blob[s->reg];
+    s->reg++;
+    return value;
+}
+
+static int i2c_ddc_tx(I2CSlave *i2c, uint8_t data)
+{
+    I2CDDCState *s = I2CDDC(i2c);
+    if (s->firstbyte) {
+        s->reg = data;
+        s->firstbyte = false;
+        DPRINTF("[EDID] Written new pointer: %u\n", data);
+        return 1;
+    }
+
+    /* Ignore all writes */
+    s->reg++;
+    return 1;
+}
+
+static void i2c_ddc_init(Object *obj)
+{
+    I2CDDCState *s = I2CDDC(obj);
+    build_edid_blob(&lcd_edid, s->edid_blob);
+}
+
+static const VMStateDescription vmstate_i2c_ddc = {
+    .name = TYPE_I2CDDC,
+    .version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_BOOL(firstbyte, I2CDDCState),
+        VMSTATE_UINT8(reg, I2CDDCState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void i2c_ddc_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
+
+    dc->reset = i2c_ddc_reset;
+    dc->vmsd = &vmstate_i2c_ddc;
+    isc->event = i2c_ddc_event;
+    isc->recv = i2c_ddc_rx;
+    isc->send = i2c_ddc_tx;
+}
+
+static TypeInfo i2c_ddc_info = {
+    .name = TYPE_I2CDDC,
+    .parent = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(I2CDDCState),
+    .instance_init = i2c_ddc_init,
+    .class_init = i2c_ddc_class_init
+};
+
+static void ddc_register_devices(void)
+{
+    type_register_static(&i2c_ddc_info);
+}
+
+type_init(ddc_register_devices);
diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c
index 67fbbff..f7c92ea 100644
--- a/hw/i2c/omap_i2c.c
+++ b/hw/i2c/omap_i2c.c
@@ -22,6 +22,7 @@
 #include "hw/arm/omap.h"
 #include "hw/sysbus.h"
 #include "qemu/error-report.h"
+#include "qapi/error.h"
 
 #define TYPE_OMAP_I2C "omap_i2c"
 #define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
@@ -445,29 +446,35 @@
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static int omap_i2c_init(SysBusDevice *sbd)
+static void omap_i2c_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
-    OMAPI2CState *s = OMAP_I2C(dev);
-
-    if (!s->fclk) {
-        error_report("omap_i2c: fclk not connected");
-        return -1;
-    }
-    if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
-        /* Note that OMAP1 doesn't have a separate interface clock */
-        error_report("omap_i2c: iclk not connected");
-        return -1;
-    }
+    DeviceState *dev = DEVICE(obj);
+    OMAPI2CState *s = OMAP_I2C(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
     sysbus_init_irq(sbd, &s->irq);
     sysbus_init_irq(sbd, &s->drq[0]);
     sysbus_init_irq(sbd, &s->drq[1]);
-    memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c",
-                          (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
     sysbus_init_mmio(sbd, &s->iomem);
     s->bus = i2c_init_bus(dev, NULL);
-    return 0;
+}
+
+static void omap_i2c_realize(DeviceState *dev, Error **errp)
+{
+    OMAPI2CState *s = OMAP_I2C(dev);
+
+    memory_region_init_io(&s->iomem, OBJECT(dev), &omap_i2c_ops, s, "omap.i2c",
+                          (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
+
+    if (!s->fclk) {
+        error_setg(errp, "omap_i2c: fclk not connected");
+        return;
+    }
+    if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
+        /* Note that OMAP1 doesn't have a separate interface clock */
+        error_setg(errp, "omap_i2c: iclk not connected");
+        return;
+    }
 }
 
 static Property omap_i2c_properties[] = {
@@ -480,18 +487,19 @@
 static void omap_i2c_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-    k->init = omap_i2c_init;
+
     dc->props = omap_i2c_properties;
     dc->reset = omap_i2c_reset;
     /* Reason: pointer properties "iclk", "fclk" */
     dc->cannot_instantiate_with_device_add_yet = true;
+    dc->realize = omap_i2c_realize;
 }
 
 static const TypeInfo omap_i2c_info = {
     .name = TYPE_OMAP_I2C,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(OMAPI2CState),
+    .instance_init = omap_i2c_init,
     .class_init = omap_i2c_class_init,
 };
 
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
index 0bce524..da9f298 100644
--- a/hw/i2c/versatile_i2c.c
+++ b/hw/i2c/versatile_i2c.c
@@ -79,32 +79,25 @@
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static int versatile_i2c_init(SysBusDevice *sbd)
+static void versatile_i2c_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
-    VersatileI2CState *s = VERSATILE_I2C(dev);
+    DeviceState *dev = DEVICE(obj);
+    VersatileI2CState *s = VERSATILE_I2C(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
     I2CBus *bus;
 
     bus = i2c_init_bus(dev, "i2c");
     s->bitbang = bitbang_i2c_init(bus);
-    memory_region_init_io(&s->iomem, OBJECT(s), &versatile_i2c_ops, s,
+    memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s,
                           "versatile_i2c", 0x1000);
     sysbus_init_mmio(sbd, &s->iomem);
-    return 0;
-}
-
-static void versatile_i2c_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = versatile_i2c_init;
 }
 
 static const TypeInfo versatile_i2c_info = {
     .name          = TYPE_VERSATILE_I2C,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(VersatileI2CState),
-    .class_init    = versatile_i2c_class_init,
+    .instance_init = versatile_i2c_init,
 };
 
 static void versatile_i2c_register_types(void)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 14dd0cc..82c7c0a 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -262,7 +262,7 @@
 
     pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
 
-    if (pcmc->pci_enabled && usb_enabled()) {
+    if (pcmc->pci_enabled && machine_usb(machine)) {
         pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
     }
 
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 04aae89..31a6a59 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -234,7 +234,7 @@
     ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports);
     ahci_ide_create_devs(ahci, hd);
 
-    if (usb_enabled()) {
+    if (machine_usb(machine)) {
         /* Should we create 6 UHCI according to ich9 spec? */
         ehci_create_ich9_with_companions(host_bus, 0x1d);
     }
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 78c10a0..fa57352 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -66,8 +66,7 @@
     DBDMA_io *io = opaque;
     MACIOIDEState *m = io->opaque;
     IDEState *s = idebus_active_if(&m->bus);
-    dma_addr_t dma_addr, dma_len;
-    void *mem;
+    dma_addr_t dma_addr;
     int64_t sector_num;
     int nsector;
     uint64_t align = BDRV_SECTOR_SIZE;
@@ -84,9 +83,10 @@
                   sector_num, nsector);
 
     dma_addr = io->addr;
-    dma_len = io->len;
-    mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
-                         DMA_DIRECTION_FROM_DEVICE);
+    io->dir = DMA_DIRECTION_FROM_DEVICE;
+    io->dma_len = io->len;
+    io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len,
+                                 io->dir);
 
     if (offset & (align - 1)) {
         head_bytes = offset & (align - 1);
@@ -100,7 +100,7 @@
         offset = offset & ~(align - 1);
     }
 
-    qemu_iovec_add(&io->iov, mem, io->len);
+    qemu_iovec_add(&io->iov, io->dma_mem, io->len);
 
     if ((offset + bytes) & (align - 1)) {
         tail_bytes = (offset + bytes) & (align - 1);
@@ -130,8 +130,7 @@
     DBDMA_io *io = opaque;
     MACIOIDEState *m = io->opaque;
     IDEState *s = idebus_active_if(&m->bus);
-    dma_addr_t dma_addr, dma_len;
-    void *mem;
+    dma_addr_t dma_addr;
     int64_t sector_num;
     int nsector;
     uint64_t align = BDRV_SECTOR_SIZE;
@@ -149,9 +148,10 @@
                   sector_num, nsector);
 
     dma_addr = io->addr;
-    dma_len = io->len;
-    mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
-                         DMA_DIRECTION_TO_DEVICE);
+    io->dir = DMA_DIRECTION_TO_DEVICE;
+    io->dma_len = io->len;
+    io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len,
+                                 io->dir);
 
     if (offset & (align - 1)) {
         head_bytes = offset & (align - 1);
@@ -163,7 +163,7 @@
         blk_pread(s->blk, (sector_num << 9), &io->head_remainder, align);
 
         qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes);
-        qemu_iovec_add(&io->iov, mem, io->len);
+        qemu_iovec_add(&io->iov, io->dma_mem, io->len);
 
         bytes += offset & (align - 1);
         offset = offset & ~(align - 1);
@@ -181,7 +181,7 @@
         blk_pread(s->blk, (sector_num << 9), &io->tail_remainder, align);
 
         if (!unaligned_head) {
-            qemu_iovec_add(&io->iov, mem, io->len);
+            qemu_iovec_add(&io->iov, io->dma_mem, io->len);
         }
 
         qemu_iovec_add(&io->iov, &io->tail_remainder + tail_bytes,
@@ -193,7 +193,7 @@
     }
 
     if (!unaligned_head && !unaligned_tail) {
-        qemu_iovec_add(&io->iov, mem, io->len);
+        qemu_iovec_add(&io->iov, io->dma_mem, io->len);
     }
 
     s->io_buffer_size -= io->len;
@@ -214,18 +214,18 @@
     DBDMA_io *io = opaque;
     MACIOIDEState *m = io->opaque;
     IDEState *s = idebus_active_if(&m->bus);
-    dma_addr_t dma_addr, dma_len;
-    void *mem;
+    dma_addr_t dma_addr;
 
     qemu_iovec_destroy(&io->iov);
     qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1);
 
     dma_addr = io->addr;
-    dma_len = io->len;
-    mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
-                         DMA_DIRECTION_TO_DEVICE);
+    io->dir = DMA_DIRECTION_TO_DEVICE;
+    io->dma_len = io->len;
+    io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len,
+                                 io->dir);
 
-    qemu_iovec_add(&io->iov, mem, io->len);
+    qemu_iovec_add(&io->iov, io->dma_mem, io->len);
     s->io_buffer_size -= io->len;
     s->io_buffer_index += io->len;
     io->len = 0;
@@ -285,6 +285,9 @@
     return;
 
 done:
+    dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
+                     io->dir, io->dma_len);
+
     if (ret < 0) {
         block_acct_failed(blk_get_stats(s->blk), &s->acct);
     } else {
@@ -351,6 +354,9 @@
     return;
 
 done:
+    dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
+                     io->dir, io->dma_len);
+
     if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
         if (ret < 0) {
             block_acct_failed(blk_get_stats(s->blk), &s->acct);
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index bc75fa7..6ab29ef 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -67,6 +67,13 @@
 {
 }
 
+static int qemu_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
+                           uint16_t subchannel_nr)
+{
+    /* Fixme TCG */
+    return -ENOSYS;
+}
+
 static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
 {
     S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
@@ -75,6 +82,7 @@
     fsc->io_adapter_map = qemu_s390_io_adapter_map;
     fsc->add_adapter_routes = qemu_s390_add_adapter_routes;
     fsc->release_adapter_routes = qemu_s390_release_adapter_routes;
+    fsc->clear_io_irq = qemu_s390_clear_io_flic;
 }
 
 static const TypeInfo qemu_s390_flic_info = {
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index eed6325..680857f 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -30,6 +30,7 @@
     S390FLICState parent_obj;
 
     uint32_t fd;
+    bool clear_io_supported;
 } KVMS390FLICState;
 
 DeviceState *s390_flic_kvm_create(void)
@@ -130,6 +131,24 @@
     return flic_enqueue_irqs(irq, sizeof(*irq), flic);
 }
 
+static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
+                           uint16_t subchannel_nr)
+{
+    KVMS390FLICState *flic = KVM_S390_FLIC(fs);
+    int rc;
+    uint32_t sid = subchannel_id << 16 | subchannel_nr;
+    struct kvm_device_attr attr = {
+        .group = KVM_DEV_FLIC_CLEAR_IO_IRQ,
+        .addr = (uint64_t) &sid,
+        .attr = sizeof(sid),
+    };
+    if (unlikely(!flic->clear_io_supported)) {
+        return -ENOSYS;
+    }
+    rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
+    return rc ? -errno : 0;
+}
+
 /**
  * __get_all_irqs - store all pending irqs in buffer
  * @flic: pointer to flic device state
@@ -358,6 +377,7 @@
 {
     KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
     struct kvm_create_device cd = {0};
+    struct kvm_device_attr test_attr = {0};
     int ret;
 
     flic_state->fd = -1;
@@ -374,6 +394,11 @@
     }
     flic_state->fd = cd.fd;
 
+    /* Check clear_io_irq support */
+    test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ;
+    flic_state->clear_io_supported = !ioctl(flic_state->fd,
+                                            KVM_HAS_DEVICE_ATTR, test_attr);
+
     /* Register savevm handler for floating interrupts */
     register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
                     kvm_flic_load, (void *) flic_state);
@@ -420,6 +445,7 @@
     fsc->io_adapter_map = kvm_s390_io_adapter_map;
     fsc->add_adapter_routes = kvm_s390_add_adapter_routes;
     fsc->release_adapter_routes = kvm_s390_release_adapter_routes;
+    fsc->clear_io_irq = kvm_s390_clear_io_flic;
 }
 
 static const TypeInfo kvm_s390_flic_info = {
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index bc0dd2c..ffb49c1 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -51,3 +51,4 @@
 obj-$(CONFIG_PVPANIC) += pvpanic.o
 obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
+obj-$(CONFIG_AUX) += aux.o
diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c
index 4442227..66a0787 100644
--- a/hw/misc/arm_l2x0.c
+++ b/hw/misc/arm_l2x0.c
@@ -159,14 +159,14 @@
     .endianness = DEVICE_NATIVE_ENDIAN,
  };
 
-static int l2x0_priv_init(SysBusDevice *dev)
+static void l2x0_priv_init(Object *obj)
 {
-    L2x0State *s = ARM_L2X0(dev);
+    L2x0State *s = ARM_L2X0(obj);
+    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
 
-    memory_region_init_io(&s->iomem, OBJECT(dev), &l2x0_mem_ops, s,
+    memory_region_init_io(&s->iomem, obj, &l2x0_mem_ops, s,
                           "l2x0_cc", 0x1000);
     sysbus_init_mmio(dev, &s->iomem);
-    return 0;
 }
 
 static Property l2x0_properties[] = {
@@ -176,10 +176,8 @@
 
 static void l2x0_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = l2x0_priv_init;
     dc->vmsd = &vmstate_l2x0;
     dc->props = l2x0_properties;
     dc->reset = l2x0_priv_reset;
@@ -189,6 +187,7 @@
     .name = TYPE_ARM_L2X0,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(L2x0State),
+    .instance_init = l2x0_priv_init,
     .class_init = l2x0_class_init,
 };
 
diff --git a/hw/misc/aux.c b/hw/misc/aux.c
new file mode 100644
index 0000000..25d7712
--- /dev/null
+++ b/hw/misc/aux.c
@@ -0,0 +1,292 @@
+/*
+ * aux.c
+ *
+ *  Copyright 2015 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.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/>.
+ *
+ */
+
+/*
+ * This is an implementation of the AUX bus for VESA Display Port v1.1a.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/misc/aux.h"
+#include "hw/i2c/i2c.h"
+#include "monitor/monitor.h"
+
+#ifndef DEBUG_AUX
+#define DEBUG_AUX 0
+#endif
+
+#define DPRINTF(fmt, ...) do {                                                 \
+    if (DEBUG_AUX) {                                                           \
+        qemu_log("aux: " fmt , ## __VA_ARGS__);                                \
+    }                                                                          \
+} while (0);
+
+#define TYPE_AUXTOI2C "aux-to-i2c-bridge"
+#define AUXTOI2C(obj) OBJECT_CHECK(AUXTOI2CState, (obj), TYPE_AUXTOI2C)
+
+static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent);
+static inline I2CBus *aux_bridge_get_i2c_bus(AUXTOI2CState *bridge);
+
+/* aux-bus implementation (internal not public) */
+static void aux_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    /* AUXSlave has an MMIO so we need to change the way we print information
+     * in monitor.
+     */
+    k->print_dev = aux_slave_dev_print;
+}
+
+AUXBus *aux_init_bus(DeviceState *parent, const char *name)
+{
+    AUXBus *bus;
+
+    bus = AUX_BUS(qbus_create(TYPE_AUX_BUS, parent, name));
+    bus->bridge = AUXTOI2C(qdev_create(BUS(bus), TYPE_AUXTOI2C));
+
+    /* Memory related. */
+    bus->aux_io = g_malloc(sizeof(*bus->aux_io));
+    memory_region_init(bus->aux_io, OBJECT(bus), "aux-io", (1 << 20));
+    address_space_init(&bus->aux_addr_space, bus->aux_io, "aux-io");
+    return bus;
+}
+
+static void aux_bus_map_device(AUXBus *bus, AUXSlave *dev, hwaddr addr)
+{
+    memory_region_add_subregion(bus->aux_io, addr, dev->mmio);
+}
+
+static bool aux_bus_is_bridge(AUXBus *bus, DeviceState *dev)
+{
+    return (dev == DEVICE(bus->bridge));
+}
+
+I2CBus *aux_get_i2c_bus(AUXBus *bus)
+{
+    return aux_bridge_get_i2c_bus(bus->bridge);
+}
+
+AUXReply aux_request(AUXBus *bus, AUXCommand cmd, uint32_t address,
+                      uint8_t len, uint8_t *data)
+{
+    AUXReply ret = AUX_NACK;
+    I2CBus *i2c_bus = aux_get_i2c_bus(bus);
+    size_t i;
+    bool is_write = false;
+
+    DPRINTF("request at address 0x%" PRIX32 ", command %u, len %u\n", address,
+            cmd, len);
+
+    switch (cmd) {
+    /*
+     * Forward the request on the AUX bus..
+     */
+    case WRITE_AUX:
+    case READ_AUX:
+        is_write = cmd == READ_AUX ? false : true;
+        for (i = 0; i < len; i++) {
+            if (!address_space_rw(&bus->aux_addr_space, address++,
+                                  MEMTXATTRS_UNSPECIFIED, data++, 1,
+                                  is_write)) {
+                ret = AUX_I2C_ACK;
+            } else {
+                ret = AUX_NACK;
+                break;
+            }
+        }
+        break;
+    /*
+     * Classic I2C transactions..
+     */
+    case READ_I2C:
+    case WRITE_I2C:
+        is_write = cmd == READ_I2C ? false : true;
+        if (i2c_bus_busy(i2c_bus)) {
+            i2c_end_transfer(i2c_bus);
+        }
+
+        if (i2c_start_transfer(i2c_bus, address, is_write)) {
+            ret = AUX_I2C_NACK;
+            break;
+        }
+
+        ret = AUX_I2C_ACK;
+        while (len > 0) {
+            if (i2c_send_recv(i2c_bus, data++, is_write) < 0) {
+                ret = AUX_I2C_NACK;
+                break;
+            }
+            len--;
+        }
+        i2c_end_transfer(i2c_bus);
+        break;
+    /*
+     * I2C MOT transactions.
+     *
+     * Here we send a start when:
+     *  - We didn't start transaction yet.
+     *  - We had a READ and we do a WRITE.
+     *  - We changed the address.
+     */
+    case WRITE_I2C_MOT:
+    case READ_I2C_MOT:
+        is_write = cmd == READ_I2C_MOT ? false : true;
+        if (!i2c_bus_busy(i2c_bus)) {
+            /*
+             * No transactions started..
+             */
+            if (i2c_start_transfer(i2c_bus, address, is_write)) {
+                ret = AUX_I2C_NACK;
+                break;
+            }
+        } else if ((address != bus->last_i2c_address) ||
+                   (bus->last_transaction != cmd)) {
+            /*
+             * Transaction started but we need to restart..
+             */
+            i2c_end_transfer(i2c_bus);
+            if (i2c_start_transfer(i2c_bus, address, is_write)) {
+                ret = AUX_I2C_NACK;
+                break;
+            }
+        }
+
+        while (len > 0) {
+            if (i2c_send_recv(i2c_bus, data++, is_write) < 0) {
+                ret = AUX_I2C_NACK;
+                i2c_end_transfer(i2c_bus);
+                break;
+            }
+            len--;
+        }
+        bus->last_transaction = cmd;
+        bus->last_i2c_address = address;
+        ret = AUX_I2C_ACK;
+        break;
+    default:
+        DPRINTF("Not implemented!\n");
+        return AUX_NACK;
+    }
+
+    DPRINTF("reply: %u\n", ret);
+    return ret;
+}
+
+static const TypeInfo aux_bus_info = {
+    .name = TYPE_AUX_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(AUXBus),
+    .class_init = aux_bus_class_init
+};
+
+/* aux-i2c implementation (internal not public) */
+struct AUXTOI2CState {
+    /*< private >*/
+    DeviceState parent_obj;
+
+    /*< public >*/
+    I2CBus *i2c_bus;
+};
+
+static void aux_bridge_init(Object *obj)
+{
+    AUXTOI2CState *s = AUXTOI2C(obj);
+
+    s->i2c_bus = i2c_init_bus(DEVICE(obj), "aux-i2c");
+}
+
+static inline I2CBus *aux_bridge_get_i2c_bus(AUXTOI2CState *bridge)
+{
+    return bridge->i2c_bus;
+}
+
+static const TypeInfo aux_to_i2c_type_info = {
+    .name = TYPE_AUXTOI2C,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(AUXTOI2CState),
+    .instance_init = aux_bridge_init
+};
+
+/* aux-slave implementation */
+static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent)
+{
+    AUXBus *bus = AUX_BUS(qdev_get_parent_bus(dev));
+    AUXSlave *s;
+
+    /* Don't print anything if the device is I2C "bridge". */
+    if (aux_bus_is_bridge(bus, dev)) {
+        return;
+    }
+
+    s = AUX_SLAVE(dev);
+
+    monitor_printf(mon, "%*smemory " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
+                   indent, "",
+                   object_property_get_int(OBJECT(s->mmio), "addr", NULL),
+                   memory_region_size(s->mmio));
+}
+
+DeviceState *aux_create_slave(AUXBus *bus, const char *type, uint32_t addr)
+{
+    DeviceState *dev;
+
+    dev = DEVICE(object_new(type));
+    assert(dev);
+    qdev_set_parent_bus(dev, &bus->qbus);
+    qdev_init_nofail(dev);
+    aux_bus_map_device(AUX_BUS(qdev_get_parent_bus(dev)), AUX_SLAVE(dev), addr);
+    return dev;
+}
+
+void aux_init_mmio(AUXSlave *aux_slave, MemoryRegion *mmio)
+{
+    assert(!aux_slave->mmio);
+    aux_slave->mmio = mmio;
+}
+
+static void aux_slave_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *k = DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_MISC, k->categories);
+    k->bus_type = TYPE_AUX_BUS;
+}
+
+static const TypeInfo aux_slave_type_info = {
+    .name = TYPE_AUX_SLAVE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(AUXSlave),
+    .abstract = true,
+    .class_init = aux_slave_class_init,
+};
+
+static void aux_register_types(void)
+{
+    type_register_static(&aux_bus_info);
+    type_register_static(&aux_slave_type_info);
+    type_register_static(&aux_to_i2c_type_info);
+}
+
+type_init(aux_register_types)
diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
index 889abad..e30dbc7 100644
--- a/hw/misc/exynos4210_pmu.c
+++ b/hw/misc/exynos4210_pmu.c
@@ -457,15 +457,15 @@
     }
 }
 
-static int exynos4210_pmu_init(SysBusDevice *dev)
+static void exynos4210_pmu_init(Object *obj)
 {
-    Exynos4210PmuState *s = EXYNOS4210_PMU(dev);
+    Exynos4210PmuState *s = EXYNOS4210_PMU(obj);
+    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
 
     /* memory mapping */
-    memory_region_init_io(&s->iomem, OBJECT(dev), &exynos4210_pmu_ops, s,
+    memory_region_init_io(&s->iomem, obj, &exynos4210_pmu_ops, s,
                           "exynos4210.pmu", EXYNOS4210_PMU_REGS_MEM_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
-    return 0;
 }
 
 static const VMStateDescription exynos4210_pmu_vmstate = {
@@ -481,9 +481,7 @@
 static void exynos4210_pmu_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = exynos4210_pmu_init;
     dc->reset = exynos4210_pmu_reset;
     dc->vmsd = &exynos4210_pmu_vmstate;
 }
@@ -492,6 +490,7 @@
     .name          = TYPE_EXYNOS4210_PMU,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210PmuState),
+    .instance_init = exynos4210_pmu_init,
     .class_init    = exynos4210_pmu_class_init,
 };
 
diff --git a/hw/misc/mst_fpga.c b/hw/misc/mst_fpga.c
index 48d7dfb..a10f049 100644
--- a/hw/misc/mst_fpga.c
+++ b/hw/misc/mst_fpga.c
@@ -200,10 +200,11 @@
 	return 0;
 }
 
-static int mst_fpga_init(SysBusDevice *sbd)
+static void mst_fpga_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
-    mst_irq_state *s = MAINSTONE_FPGA(dev);
+    DeviceState *dev = DEVICE(obj);
+    mst_irq_state *s = MAINSTONE_FPGA(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
     s->pcmcia0 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
     s->pcmcia1 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
@@ -213,10 +214,9 @@
     /* alloc the external 16 irqs */
     qdev_init_gpio_in(dev, mst_fpga_set_irq, MST_NUM_IRQS);
 
-    memory_region_init_io(&s->iomem, OBJECT(s), &mst_fpga_ops, s,
+    memory_region_init_io(&s->iomem, obj, &mst_fpga_ops, s,
                           "fpga", 0x00100000);
     sysbus_init_mmio(sbd, &s->iomem);
-    return 0;
 }
 
 static VMStateDescription vmstate_mst_fpga_regs = {
@@ -245,9 +245,7 @@
 static void mst_fpga_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = mst_fpga_init;
     dc->desc = "Mainstone II FPGA";
     dc->vmsd = &vmstate_mst_fpga_regs;
 }
@@ -256,6 +254,7 @@
     .name          = TYPE_MAINSTONE_FPGA,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(mst_irq_state),
+    .instance_init = mst_fpga_init,
     .class_init    = mst_fpga_class_init,
 };
 
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index a9bb1c2..4479487 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -309,7 +309,7 @@
     dev = qdev_create(adb_bus, TYPE_ADB_MOUSE);
     qdev_init_nofail(dev);
 
-    if (usb_enabled()) {
+    if (machine_usb(machine)) {
         pci_create_simple(pci_bus, -1, "pci-ohci");
     }
 
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 07ffe72..054af1e 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -649,7 +649,7 @@
     memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr);
 #endif
 
-    if (usb_enabled()) {
+    if (machine_usb(machine)) {
         pci_create_simple(pci_bus, -1, "pci-ohci");
     }
 
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 0636642..9a4a803 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -762,14 +762,17 @@
     int ret, i, offset;
     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
     uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
-    uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size;
+    uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size;
+    uint32_t nr_lmbs = (spapr->hotplug_memory.base +
+                       memory_region_size(&spapr->hotplug_memory.mr)) /
+                       lmb_size;
     uint32_t *int_buf, *cur_index, buf_len;
     int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
 
     /*
-     * Don't create the node if there are no DR LMBs.
+     * Don't create the node if there is no hotpluggable memory
      */
-    if (!nr_lmbs) {
+    if (machine->ram_size == machine->maxram_size) {
         return 0;
     }
 
@@ -803,26 +806,40 @@
     int_buf[0] = cpu_to_be32(nr_lmbs);
     cur_index++;
     for (i = 0; i < nr_lmbs; i++) {
-        sPAPRDRConnector *drc;
-        sPAPRDRConnectorClass *drck;
-        uint64_t addr = i * lmb_size + spapr->hotplug_memory.base;;
+        uint64_t addr = i * lmb_size;
         uint32_t *dynamic_memory = cur_index;
 
-        drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
-                                       addr/lmb_size);
-        g_assert(drc);
-        drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+        if (i >= hotplug_lmb_start) {
+            sPAPRDRConnector *drc;
+            sPAPRDRConnectorClass *drck;
 
-        dynamic_memory[0] = cpu_to_be32(addr >> 32);
-        dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
-        dynamic_memory[2] = cpu_to_be32(drck->get_index(drc));
-        dynamic_memory[3] = cpu_to_be32(0); /* reserved */
-        dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL));
-        if (addr < machine->ram_size ||
-                    memory_region_present(get_system_memory(), addr)) {
-            dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED);
+            drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i);
+            g_assert(drc);
+            drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+
+            dynamic_memory[0] = cpu_to_be32(addr >> 32);
+            dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
+            dynamic_memory[2] = cpu_to_be32(drck->get_index(drc));
+            dynamic_memory[3] = cpu_to_be32(0); /* reserved */
+            dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL));
+            if (memory_region_present(get_system_memory(), addr)) {
+                dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED);
+            } else {
+                dynamic_memory[5] = cpu_to_be32(0);
+            }
         } else {
-            dynamic_memory[5] = cpu_to_be32(0);
+            /*
+             * LMB information for RMA, boot time RAM and gap b/n RAM and
+             * hotplug memory region -- all these are marked as reserved
+             * and as having no valid DRC.
+             */
+            dynamic_memory[0] = cpu_to_be32(addr >> 32);
+            dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
+            dynamic_memory[2] = cpu_to_be32(0);
+            dynamic_memory[3] = cpu_to_be32(0); /* reserved */
+            dynamic_memory[4] = cpu_to_be32(-1);
+            dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED |
+                                            SPAPR_LMB_FLAGS_DRC_INVALID);
         }
 
         cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE;
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 9a3f4ec..2ba5cbd 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -922,6 +922,41 @@
     ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \
     ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0)
 
+static void cas_handle_compat_cpu(PowerPCCPUClass *pcc, uint32_t pvr,
+                                  unsigned max_lvl, unsigned *compat_lvl,
+                                  unsigned *cpu_version)
+{
+    unsigned lvl = get_compat_level(pvr);
+    bool is205, is206, is207;
+
+    if (!lvl) {
+        return;
+    }
+
+    /* If it is a logical PVR, try to determine the highest level */
+    is205 = (pcc->pcr_supported & PCR_COMPAT_2_05) &&
+            (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
+    is206 = (pcc->pcr_supported & PCR_COMPAT_2_06) &&
+            ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
+             (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
+    is207 = (pcc->pcr_supported & PCR_COMPAT_2_07) &&
+            (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_07));
+
+    if (is205 || is206 || is207) {
+        if (!max_lvl) {
+            /* User did not set the level, choose the highest */
+            if (*compat_lvl <= lvl) {
+                *compat_lvl = lvl;
+                *cpu_version = pvr;
+            }
+        } else if (max_lvl >= lvl) {
+            /* User chose the level, don't set higher than this */
+            *compat_lvl = lvl;
+            *cpu_version = pvr;
+        }
+    }
+}
+
 #define OV5_DRCONF_MEMORY 0x20
 
 static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
@@ -931,7 +966,7 @@
 {
     target_ulong list = ppc64_phys_to_real(args[0]);
     target_ulong ov_table, ov5;
-    PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_);
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu_);
     CPUState *cs;
     bool cpu_match = false, cpu_update = true, memory_update = false;
     unsigned old_cpu_version = cpu_->cpu_version;
@@ -958,29 +993,7 @@
             cpu_match = true;
             cpu_version = cpu_->cpu_version;
         } else if (!cpu_match) {
-            /* If it is a logical PVR, try to determine the highest level */
-            unsigned lvl = get_compat_level(pvr);
-            if (lvl) {
-                bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) &&
-                     (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
-                bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) &&
-                    ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
-                    (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
-
-                if (is205 || is206) {
-                    if (!max_lvl) {
-                        /* User did not set the level, choose the highest */
-                        if (compat_lvl <= lvl) {
-                            compat_lvl = lvl;
-                            cpu_version = pvr;
-                        }
-                    } else if (max_lvl >= lvl) {
-                        /* User chose the level, don't set higher than this */
-                        compat_lvl = lvl;
-                        cpu_version = pvr;
-                    }
-                }
-            }
+            cas_handle_compat_cpu(pcc, pvr, max_lvl, &compat_lvl, &cpu_version);
         }
         /* Terminator record */
         if (~pvr_mask & pvr) {
@@ -990,7 +1003,7 @@
 
     /* Parsing finished */
     trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match,
-                        cpu_version, pcc_->pcr_mask);
+                        cpu_version, pcc->pcr_mask);
 
     /* Update CPUs */
     if (old_cpu_version != cpu_version) {
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 1675a19..7666881 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -10,6 +10,8 @@
  */
 
 #include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
 #include <hw/qdev.h>
 #include "qemu/bitops.h"
 #include "exec/address-spaces.h"
@@ -192,12 +194,46 @@
     return ret;
 }
 
-uint16_t css_build_subchannel_id(SubchDev *sch)
+static void css_clear_io_interrupt(uint16_t subchannel_id,
+                                   uint16_t subchannel_nr)
+{
+    Error *err = NULL;
+    static bool no_clear_irq;
+    S390FLICState *fs = s390_get_flic();
+    S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+    int r;
+
+    if (unlikely(no_clear_irq)) {
+        return;
+    }
+    r = fsc->clear_io_irq(fs, subchannel_id, subchannel_nr);
+    switch (r) {
+    case 0:
+        break;
+    case -ENOSYS:
+        no_clear_irq = true;
+        /*
+        * Ignore unavailability, as the user can't do anything
+        * about it anyway.
+        */
+        break;
+    default:
+        error_setg_errno(&err, -r, "unexpected error condition");
+        error_propagate(&error_abort, err);
+    }
+}
+
+static inline uint16_t css_do_build_subchannel_id(uint8_t cssid, uint8_t ssid)
 {
     if (channel_subsys.max_cssid > 0) {
-        return (sch->cssid << 8) | (1 << 3) | (sch->ssid << 1) | 1;
+        return (cssid << 8) | (1 << 3) | (ssid << 1) | 1;
     }
-    return (sch->ssid << 1) | 1;
+    return (ssid << 1) | 1;
+}
+
+uint16_t css_build_subchannel_id(SubchDev *sch)
+{
+    return css_do_build_subchannel_id(sch->cssid, sch->ssid);
 }
 
 static void css_inject_io_interrupt(SubchDev *sch)
@@ -1429,6 +1465,8 @@
         css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0,
                       (guest_cssid << 8) | (ssid << 4));
     }
+    /* RW_ERC_IPI --> clear pending interrupts */
+    css_clear_io_interrupt(css_do_build_subchannel_id(cssid, ssid), schid);
 }
 
 void css_generate_chp_crws(uint8_t cssid, uint8_t chpid)
@@ -1644,3 +1682,83 @@
     channel_subsys.max_cssid = 0;
     channel_subsys.max_ssid = 0;
 }
+
+static void get_css_devid(Object *obj, Visitor *v, const char *name,
+                          void *opaque, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    CssDevId *dev_id = qdev_get_prop_ptr(dev, prop);
+    char buffer[] = "xx.x.xxxx";
+    char *p = buffer;
+    int r;
+
+    if (dev_id->valid) {
+
+        r = snprintf(buffer, sizeof(buffer), "%02x.%1x.%04x", dev_id->cssid,
+                     dev_id->ssid, dev_id->devid);
+        assert(r == sizeof(buffer) - 1);
+
+        /* drop leading zero */
+        if (dev_id->cssid <= 0xf) {
+            p++;
+        }
+    } else {
+        snprintf(buffer, sizeof(buffer), "<unset>");
+    }
+
+    visit_type_str(v, name, &p, errp);
+}
+
+/*
+ * parse <cssid>.<ssid>.<devid> and assert valid range for cssid/ssid
+ */
+static void set_css_devid(Object *obj, Visitor *v, const char *name,
+                          void *opaque, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    CssDevId *dev_id = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
+    char *str;
+    int num, n1, n2;
+    unsigned int cssid, ssid, devid;
+
+    if (dev->realized) {
+        qdev_prop_set_after_realize(dev, name, errp);
+        return;
+    }
+
+    visit_type_str(v, name, &str, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    num = sscanf(str, "%2x.%1x%n.%4x%n", &cssid, &ssid, &n1, &devid, &n2);
+    if (num != 3 || (n2 - n1) != 5 || strlen(str) != n2) {
+        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+        goto out;
+    }
+    if ((cssid > MAX_CSSID) || (ssid > MAX_SSID)) {
+        error_setg(errp, "Invalid cssid or ssid: cssid %x, ssid %x",
+                   cssid, ssid);
+        goto out;
+    }
+
+    dev_id->cssid = cssid;
+    dev_id->ssid = ssid;
+    dev_id->devid = devid;
+    dev_id->valid = true;
+
+out:
+    g_free(str);
+}
+
+PropertyInfo css_devid_propinfo = {
+    .name = "str",
+    .description = "Identifier of an I/O device in the channel "
+                   "subsystem, example: fe.1.23ab",
+    .get = get_css_devid,
+    .set = set_css_devid,
+};
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 95ff5e3..e257ca5 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -204,7 +204,7 @@
     mc->no_parallel = 1;
     mc->no_sdcard = 1;
     mc->use_sclp = 1;
-    mc->max_cpus = 255;
+    mc->max_cpus = 248;
     mc->get_hotplug_handler = s390_get_hotplug_handler;
     hc->plug = s390_machine_device_plug;
     nc->nmi_monitor_handler = s390_nmi;
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 2b68e5e..2192be8 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -737,14 +737,9 @@
 
 static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
 {
-    unsigned int cssid = 0;
-    unsigned int ssid = 0;
     unsigned int schid;
-    unsigned int devno;
-    bool have_devno = false;
     bool found = false;
     SubchDev *sch;
-    int num;
     Error *err = NULL;
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
 
@@ -763,54 +758,44 @@
      * Use a device number if provided. Otherwise, fall back to subchannel
      * number.
      */
-    if (dev->bus_id) {
-        num = sscanf(dev->bus_id, "%x.%x.%04x", &cssid, &ssid, &devno);
-        if (num == 3) {
-            if ((cssid > MAX_CSSID) || (ssid > MAX_SSID)) {
-                error_setg(errp, "Invalid cssid or ssid: cssid %x, ssid %x",
-                           cssid, ssid);
-                goto out_err;
-            }
-            /* Enforce use of virtual cssid. */
-            if (cssid != VIRTUAL_CSSID) {
-                error_setg(errp, "cssid %x not valid for virtio devices",
-                           cssid);
-                goto out_err;
-            }
-            if (css_devno_used(cssid, ssid, devno)) {
-                error_setg(errp, "Device %x.%x.%04x already exists",
-                           cssid, ssid, devno);
-                goto out_err;
-            }
-            sch->cssid = cssid;
-            sch->ssid = ssid;
-            sch->devno = devno;
-            have_devno = true;
-        } else {
-            error_setg(errp, "Malformed devno parameter '%s'", dev->bus_id);
+    if (dev->bus_id.valid) {
+        /* Enforce use of virtual cssid. */
+        if (dev->bus_id.cssid != VIRTUAL_CSSID) {
+            error_setg(errp, "cssid %x not valid for virtio devices",
+                       dev->bus_id.cssid);
             goto out_err;
         }
-    }
+        if (css_devno_used(dev->bus_id.cssid, dev->bus_id.ssid,
+                           dev->bus_id.devid)) {
+                error_setg(errp, "Device %x.%x.%04x already exists",
+                           dev->bus_id.cssid, dev->bus_id.ssid,
+                           dev->bus_id.devid);
+                goto out_err;
+        }
+        sch->cssid = dev->bus_id.cssid;
+        sch->ssid = dev->bus_id.ssid;
+        sch->devno = dev->bus_id.devid;
 
-    /* Find the next free id. */
-    if (have_devno) {
+        /* Find the next free id. */
         for (schid = 0; schid <= MAX_SCHID; schid++) {
-            if (!css_find_subch(1, cssid, ssid, schid)) {
+            if (!css_find_subch(1, sch->cssid, sch->ssid, schid)) {
                 sch->schid = schid;
-                css_subch_assign(cssid, ssid, schid, devno, sch);
+                css_subch_assign(sch->cssid, sch->ssid, sch->schid,
+                                 sch->devno, sch);
                 found = true;
                 break;
             }
         }
         if (!found) {
             error_setg(errp, "No free subchannel found for %x.%x.%04x",
-                       cssid, ssid, devno);
+                       sch->cssid, sch->ssid, sch->devno);
             goto out_err;
         }
-        trace_virtio_ccw_new_device(cssid, ssid, schid, devno,
-                                    "user-configured");
+        trace_virtio_ccw_new_device(sch->cssid, sch->ssid, sch->schid,
+                                    sch->devno, "user-configured");
     } else {
-        cssid = VIRTUAL_CSSID;
+        unsigned int cssid = VIRTUAL_CSSID, ssid, devno;
+
         for (ssid = 0; ssid <= MAX_SSID; ssid++) {
             for (schid = 0; schid <= MAX_SCHID; schid++) {
                 if (!css_find_subch(1, cssid, ssid, schid)) {
@@ -868,7 +853,7 @@
     }
     if (err) {
         error_propagate(errp, err);
-        css_subch_assign(cssid, ssid, schid, devno, NULL);
+        css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
         goto out_err;
     }
 
@@ -1106,6 +1091,7 @@
         ind_old = *ind_addr;
         ind_new = ind_old | to_be_set;
     } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old);
+    trace_virtio_ccw_set_ind(ind_loc, ind_old, ind_new);
     cpu_physical_memory_unmap(ind_addr, len, 1, len);
 
     return ind_old;
@@ -1516,7 +1502,7 @@
 /**************** Virtio-ccw Bus Device Descriptions *******************/
 
 static Property virtio_ccw_net_properties[] = {
-    DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+    DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1545,7 +1531,7 @@
 };
 
 static Property virtio_ccw_blk_properties[] = {
-    DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+    DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1574,7 +1560,7 @@
 };
 
 static Property virtio_ccw_serial_properties[] = {
-    DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+    DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1603,7 +1589,7 @@
 };
 
 static Property virtio_ccw_balloon_properties[] = {
-    DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+    DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1632,7 +1618,7 @@
 };
 
 static Property virtio_ccw_scsi_properties[] = {
-    DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+    DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1662,7 +1648,7 @@
 
 #ifdef CONFIG_VHOST_SCSI
 static Property vhost_ccw_scsi_properties[] = {
-    DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+    DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
     DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
                        VIRTIO_CCW_MAX_REV),
     DEFINE_PROP_END_OF_LIST(),
@@ -1700,7 +1686,7 @@
 }
 
 static Property virtio_ccw_rng_properties[] = {
-    DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+    DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1856,7 +1842,7 @@
 
 #ifdef CONFIG_VIRTFS
 static Property virtio_ccw_9p_properties[] = {
-    DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+    DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
             VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 86b9edb..0bfb5d9 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -80,7 +80,7 @@
 struct VirtioCcwDevice {
     DeviceState parent_obj;
     SubchDev *sch;
-    char *bus_id;
+    CssDevId bus_id;
     int revision;
     uint32_t max_rev;
     VirtioBusState bus;
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index eb783c6..82c63a4 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -13,6 +13,7 @@
 #include "hw/sysbus.h"
 #include "hw/sd/sd.h"
 #include "qemu/log.h"
+#include "qapi/error.h"
 
 //#define DEBUG_PL181 1
 
@@ -481,43 +482,48 @@
     sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
 }
 
-static int pl181_init(SysBusDevice *sbd)
+static void pl181_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
-    PL181State *s = PL181(dev);
-    DriveInfo *dinfo;
+    DeviceState *dev = DEVICE(obj);
+    PL181State *s = PL181(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
-    memory_region_init_io(&s->iomem, OBJECT(s), &pl181_ops, s, "pl181", 0x1000);
+    memory_region_init_io(&s->iomem, obj, &pl181_ops, s, "pl181", 0x1000);
     sysbus_init_mmio(sbd, &s->iomem);
     sysbus_init_irq(sbd, &s->irq[0]);
     sysbus_init_irq(sbd, &s->irq[1]);
     qdev_init_gpio_out(dev, s->cardstatus, 2);
+}
+
+static void pl181_realize(DeviceState *dev, Error **errp)
+{
+    PL181State *s = PL181(dev);
+    DriveInfo *dinfo;
+
     /* FIXME use a qdev drive property instead of drive_get_next() */
     dinfo = drive_get_next(IF_SD);
     s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
     if (s->card == NULL) {
-        return -1;
+        error_setg(errp, "sd_init failed");
     }
-
-    return 0;
 }
 
 static void pl181_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
     DeviceClass *k = DEVICE_CLASS(klass);
 
-    sdc->init = pl181_init;
     k->vmsd = &vmstate_pl181;
     k->reset = pl181_reset;
     /* Reason: init() method uses drive_get_next() */
     k->cannot_instantiate_with_device_add_yet = true;
+    k->realize = pl181_realize;
 }
 
 static const TypeInfo pl181_info = {
     .name          = TYPE_PL181,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PL181State),
+    .instance_init = pl181_init,
     .class_init    = pl181_class_init,
 };
 
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 74306b5..5c18198 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -670,48 +670,49 @@
     /* general oids (table 4-1) */
     /* mandatory */
     case OID_GEN_SUPPORTED_LIST:
-        for (i = 0; i < ARRAY_SIZE(oid_supported_list); i++)
-            ((le32 *) outbuf)[i] = cpu_to_le32(oid_supported_list[i]);
+        for (i = 0; i < ARRAY_SIZE(oid_supported_list); i++) {
+            stl_le_p(outbuf + (i * sizeof(le32)), oid_supported_list[i]);
+        }
         return sizeof(oid_supported_list);
 
     /* mandatory */
     case OID_GEN_HARDWARE_STATUS:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_MEDIA_SUPPORTED:
-        *((le32 *) outbuf) = cpu_to_le32(s->medium);
+        stl_le_p(outbuf, s->medium);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_MEDIA_IN_USE:
-        *((le32 *) outbuf) = cpu_to_le32(s->medium);
+        stl_le_p(outbuf, s->medium);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_MAXIMUM_FRAME_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
+        stl_le_p(outbuf, ETH_FRAME_LEN);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_LINK_SPEED:
-        *((le32 *) outbuf) = cpu_to_le32(s->speed);
+        stl_le_p(outbuf, s->speed);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_TRANSMIT_BLOCK_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
+        stl_le_p(outbuf, ETH_FRAME_LEN);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_RECEIVE_BLOCK_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
+        stl_le_p(outbuf, ETH_FRAME_LEN);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_VENDOR_ID:
-        *((le32 *) outbuf) = cpu_to_le32(s->vendorid);
+        stl_le_p(outbuf, s->vendorid);
         return sizeof(le32);
 
     /* mandatory */
@@ -720,58 +721,57 @@
         return strlen((char *)outbuf) + 1;
 
     case OID_GEN_VENDOR_DRIVER_VERSION:
-        *((le32 *) outbuf) = cpu_to_le32(1);
+        stl_le_p(outbuf, 1);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_CURRENT_PACKET_FILTER:
-        *((le32 *) outbuf) = cpu_to_le32(s->filter);
+        stl_le_p(outbuf, s->filter);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_MAXIMUM_TOTAL_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
+        stl_le_p(outbuf, RNDIS_MAX_TOTAL_SIZE);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_MEDIA_CONNECT_STATUS:
-        *((le32 *) outbuf) = cpu_to_le32(s->media_state);
+        stl_le_p(outbuf, s->media_state);
         return sizeof(le32);
 
     case OID_GEN_PHYSICAL_MEDIUM:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     case OID_GEN_MAC_OPTIONS:
-        *((le32 *) outbuf) = cpu_to_le32(
-                        NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
-                        NDIS_MAC_OPTION_FULL_DUPLEX);
+        stl_le_p(outbuf, NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+                 NDIS_MAC_OPTION_FULL_DUPLEX);
         return sizeof(le32);
 
     /* statistics OIDs (table 4-2) */
     /* mandatory */
     case OID_GEN_XMIT_OK:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_RCV_OK:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_XMIT_ERROR:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_RCV_ERROR:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     /* mandatory */
     case OID_GEN_RCV_NO_BUFFER:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     /* ieee802.3 OIDs (table 4-3) */
@@ -787,12 +787,12 @@
 
     /* mandatory */
     case OID_802_3_MULTICAST_LIST:
-        *((le32 *) outbuf) = cpu_to_le32(0xe0000000);
+        stl_le_p(outbuf, 0xe0000000);
         return sizeof(le32);
 
     /* mandatory */
     case OID_802_3_MAXIMUM_LIST_SIZE:
-        *((le32 *) outbuf) = cpu_to_le32(1);
+        stl_le_p(outbuf, 1);
         return sizeof(le32);
 
     case OID_802_3_MAC_OPTIONS:
@@ -801,17 +801,17 @@
     /* ieee802.3 statistics OIDs (table 4-4) */
     /* mandatory */
     case OID_802_3_RCV_ERROR_ALIGNMENT:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     /* mandatory */
     case OID_802_3_XMIT_ONE_COLLISION:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     /* mandatory */
     case OID_802_3_XMIT_MORE_COLLISIONS:
-        *((le32 *) outbuf) = cpu_to_le32(0);
+        stl_le_p(outbuf, 0);
         return sizeof(le32);
 
     default:
@@ -826,7 +826,7 @@
 {
     switch (oid) {
     case OID_GEN_CURRENT_PACKET_FILTER:
-        s->filter = le32_to_cpup((le32 *) inbuf);
+        s->filter = ldl_le_p(inbuf);
         if (s->filter) {
             s->rndis_state = RNDIS_DATA_INITIALIZED;
         } else {
@@ -1026,10 +1026,7 @@
 
 static int rndis_parse(USBNetState *s, uint8_t *data, int length)
 {
-    uint32_t msg_type;
-    le32 *tmp = (le32 *) data;
-
-    msg_type = le32_to_cpup(tmp);
+    uint32_t msg_type = ldl_le_p(data);
 
     switch (msg_type) {
     case RNDIS_INITIALIZE_MSG:
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 8b774f4..da59c29 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -81,6 +81,7 @@
     uint32_t                         iso_urb_frames;
     uint32_t                         options;
     uint32_t                         loglevel;
+    bool                             needs_autoscan;
 
     /* state */
     QTAILQ_ENTRY(USBHostDevice)      next;
@@ -974,9 +975,32 @@
     }
 }
 
+static libusb_device *usb_host_find_ref(int bus, int addr)
+{
+    libusb_device **devs = NULL;
+    libusb_device *ret = NULL;
+    int i, n;
+
+    if (usb_host_init() != 0) {
+        return NULL;
+    }
+    n = libusb_get_device_list(ctx, &devs);
+    for (i = 0; i < n; i++) {
+        if (libusb_get_bus_number(devs[i]) == bus &&
+            libusb_get_device_address(devs[i]) == addr) {
+            ret = libusb_ref_device(devs[i]);
+            break;
+        }
+    }
+    libusb_free_device_list(devs, 1);
+    return ret;
+}
+
 static void usb_host_realize(USBDevice *udev, Error **errp)
 {
     USBHostDevice *s = USB_HOST_DEVICE(udev);
+    libusb_device *ldev;
+    int rc;
 
     if (s->match.vendor_id > 0xffff) {
         error_setg(errp, "vendorid out of range");
@@ -997,11 +1021,33 @@
     QTAILQ_INIT(&s->requests);
     QTAILQ_INIT(&s->isorings);
 
+    if (s->match.addr && s->match.bus_num &&
+        !s->match.vendor_id &&
+        !s->match.product_id &&
+        !s->match.port) {
+        s->needs_autoscan = false;
+        ldev = usb_host_find_ref(s->match.bus_num,
+                                 s->match.addr);
+        if (!ldev) {
+            error_setg(errp, "failed to find host usb device %d:%d",
+                       s->match.bus_num, s->match.addr);
+            return;
+        }
+        rc = usb_host_open(s, ldev);
+        libusb_unref_device(ldev);
+        if (rc < 0) {
+            error_setg(errp, "failed to open host usb device %d:%d",
+                       s->match.bus_num, s->match.addr);
+            return;
+        }
+    } else {
+        s->needs_autoscan = true;
+        QTAILQ_INSERT_TAIL(&hostdevs, s, next);
+        usb_host_auto_check(NULL);
+    }
+
     s->exit.notify = usb_host_exit_notifier;
     qemu_add_exit_notifier(&s->exit);
-
-    QTAILQ_INSERT_TAIL(&hostdevs, s, next);
-    usb_host_auto_check(NULL);
 }
 
 static void usb_host_instance_init(Object *obj)
@@ -1019,7 +1065,9 @@
     USBHostDevice *s = USB_HOST_DEVICE(udev);
 
     qemu_remove_exit_notifier(&s->exit);
-    QTAILQ_REMOVE(&hostdevs, s, next);
+    if (s->needs_autoscan) {
+        QTAILQ_REMOVE(&hostdevs, s, next);
+    }
     usb_host_close(s);
 }
 
diff --git a/include/elf.h b/include/elf.h
index 28d448b..8533b2a 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -477,6 +477,19 @@
 #define PPC_FEATURE_TRUE_LE             0x00000002
 #define PPC_FEATURE_PPC_LE              0x00000001
 
+/* Bits present in AT_HWCAP2 for PowerPC.  */
+
+#define PPC_FEATURE2_ARCH_2_07          0x80000000
+#define PPC_FEATURE2_HAS_HTM            0x40000000
+#define PPC_FEATURE2_HAS_DSCR           0x20000000
+#define PPC_FEATURE2_HAS_EBB            0x10000000
+#define PPC_FEATURE2_HAS_ISEL           0x08000000
+#define PPC_FEATURE2_HAS_TAR            0x04000000
+#define PPC_FEATURE2_HAS_VEC_CRYPTO     0x02000000
+#define PPC_FEATURE2_HTM_NOSC           0x01000000
+#define PPC_FEATURE2_ARCH_3_00          0x00800000
+#define PPC_FEATURE2_HAS_IEEE128        0x00400000
+
 /* Bits present in AT_HWCAP for Sparc.  */
 
 #define HWCAP_SPARC_FLUSH               0x00000001
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 82703d2..9650193 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -41,6 +41,10 @@
 #define ARCH_TIMER_NS_EL1_IRQ 14
 #define ARCH_TIMER_NS_EL2_IRQ 10
 
+#define VIRTUAL_PMU_IRQ 7
+
+#define PPI(irq) ((irq) + 16)
+
 enum {
     VIRT_FLASH,
     VIRT_MEM,
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 68f6eb0..c2931bf 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -26,6 +26,8 @@
 #include "hw/ide/ahci.h"
 #include "hw/sd/sdhci.h"
 #include "hw/ssi/xilinx_spips.h"
+#include "hw/dma/xlnx_dpdma.h"
+#include "hw/display/xlnx_dp.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
 #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
@@ -81,6 +83,8 @@
     SysbusAHCIState sata;
     SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
     XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
+    XlnxDPState dp;
+    XlnxDPDMAState dpdma;
 
     char *boot_cpu;
     ARMCPU *boot_cpu_ptr;
diff --git a/include/hw/display/dpcd.h b/include/hw/display/dpcd.h
new file mode 100644
index 0000000..274dc2e
--- /dev/null
+++ b/include/hw/display/dpcd.h
@@ -0,0 +1,105 @@
+/*
+ * dpcd.h
+ *
+ *  Copyright (C)2015 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.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/>.
+ *
+ */
+
+#ifndef DPCD_H
+#define DPCD_H
+
+typedef struct DPCDState DPCDState;
+
+#define TYPE_DPCD "dpcd"
+#define DPCD(obj) OBJECT_CHECK(DPCDState, (obj), TYPE_DPCD)
+
+/* DCPD Revision. */
+#define DPCD_REVISION                           0x00
+#define DPCD_REV_1_0                            0x10
+#define DPCD_REV_1_1                            0x11
+
+/* DCPD Max Link Rate. */
+#define DPCD_MAX_LINK_RATE                      0x01
+#define DPCD_1_62GBPS                           0x06
+#define DPCD_2_7GBPS                            0x0A
+#define DPCD_5_4GBPS                            0x14
+
+#define DPCD_MAX_LANE_COUNT                     0x02
+#define DPCD_ONE_LANE                           0x01
+#define DPCD_TWO_LANES                          0x02
+#define DPCD_FOUR_LANES                         0x04
+
+/* DCPD Max down spread. */
+#define DPCD_UP_TO_0_5                          0x01
+#define DPCD_NO_AUX_HANDSHAKE_LINK_TRAINING     0x40
+
+/* DCPD Downstream port type. */
+#define DPCD_DISPLAY_PORT                       0x00
+#define DPCD_ANALOG                             0x02
+#define DPCD_DVI_HDMI                           0x04
+#define DPCD_OTHER                              0x06
+
+/* DPCD Format conversion. */
+#define DPCD_FORMAT_CONVERSION                  0x08
+
+/* Main link channel coding. */
+#define DPCD_ANSI_8B_10B                        0x01
+
+/* Down stream port count. */
+#define DPCD_OUI_SUPPORTED                      0x80
+
+/* Receiver port capability. */
+#define DPCD_RECEIVE_PORT0_CAP_0                0x08
+#define DPCD_RECEIVE_PORT0_CAP_1                0x09
+#define DPCD_EDID_PRESENT                       0x02
+#define DPCD_ASSOCIATED_TO_PRECEDING_PORT       0x04
+
+/* Down stream port capability. */
+#define DPCD_CAP_DISPLAY_PORT                   0x000
+#define DPCD_CAP_ANALOG_VGA                     0x001
+#define DPCD_CAP_DVI                            0x002
+#define DPCD_CAP_HDMI                           0x003
+#define DPCD_CAP_OTHER                          0x100
+
+#define DPCD_LANE0_1_STATUS                     0x202
+#define DPCD_LANE0_CR_DONE                      (1 << 0)
+#define DPCD_LANE0_CHANNEL_EQ_DONE              (1 << 1)
+#define DPCD_LANE0_SYMBOL_LOCKED                (1 << 2)
+#define DPCD_LANE1_CR_DONE                      (1 << 4)
+#define DPCD_LANE1_CHANNEL_EQ_DONE              (1 << 5)
+#define DPCD_LANE1_SYMBOL_LOCKED                (1 << 6)
+
+#define DPCD_LANE2_3_STATUS                     0x203
+#define DPCD_LANE2_CR_DONE                      (1 << 0)
+#define DPCD_LANE2_CHANNEL_EQ_DONE              (1 << 1)
+#define DPCD_LANE2_SYMBOL_LOCKED                (1 << 2)
+#define DPCD_LANE3_CR_DONE                      (1 << 4)
+#define DPCD_LANE3_CHANNEL_EQ_DONE              (1 << 5)
+#define DPCD_LANE3_SYMBOL_LOCKED                (1 << 6)
+
+#define DPCD_LANE_ALIGN_STATUS_UPDATED          0x204
+#define DPCD_INTERLANE_ALIGN_DONE               0x01
+#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED     0x40
+#define DPCD_LINK_STATUS_UPDATED                0x80
+
+#define DPCD_SINK_STATUS                        0x205
+#define DPCD_RECEIVE_PORT_0_STATUS              0x01
+
+#endif /* !DPCD_H */
diff --git a/include/hw/display/xlnx_dp.h b/include/hw/display/xlnx_dp.h
new file mode 100644
index 0000000..d3a03f1
--- /dev/null
+++ b/include/hw/display/xlnx_dp.h
@@ -0,0 +1,109 @@
+/*
+ * xlnx_dp.h
+ *
+ *  Copyright (C) 2015 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.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 "hw/sysbus.h"
+#include "ui/console.h"
+#include "hw/misc/aux.h"
+#include "hw/i2c/i2c.h"
+#include "hw/display/dpcd.h"
+#include "hw/i2c/i2c-ddc.h"
+#include "qemu/fifo8.h"
+#include "hw/dma/xlnx_dpdma.h"
+#include "audio/audio.h"
+
+#ifndef XLNX_DP_H
+#define XLNX_DP_H
+
+#define AUD_CHBUF_MAX_DEPTH                 32768
+#define MAX_QEMU_BUFFER_SIZE                4096
+
+#define DP_CORE_REG_ARRAY_SIZE              (0x3AF >> 2)
+#define DP_AVBUF_REG_ARRAY_SIZE             (0x238 >> 2)
+#define DP_VBLEND_REG_ARRAY_SIZE            (0x1DF >> 2)
+#define DP_AUDIO_REG_ARRAY_SIZE             (0x50 >> 2)
+
+struct PixmanPlane {
+    pixman_format_code_t format;
+    DisplaySurface *surface;
+};
+
+typedef struct XlnxDPState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /* < public >*/
+    MemoryRegion container;
+
+    uint32_t core_registers[DP_CORE_REG_ARRAY_SIZE];
+    MemoryRegion core_iomem;
+
+    uint32_t avbufm_registers[DP_AVBUF_REG_ARRAY_SIZE];
+    MemoryRegion avbufm_iomem;
+
+    uint32_t vblend_registers[DP_VBLEND_REG_ARRAY_SIZE];
+    MemoryRegion vblend_iomem;
+
+    uint32_t audio_registers[DP_AUDIO_REG_ARRAY_SIZE];
+    MemoryRegion audio_iomem;
+
+    QemuConsole *console;
+
+    /*
+     * This is the planes used to display in console. When the blending is
+     * enabled bout_plane is displayed in console else it's g_plane.
+     */
+    struct PixmanPlane g_plane;
+    struct PixmanPlane v_plane;
+    struct PixmanPlane bout_plane;
+
+    QEMUSoundCard aud_card;
+    SWVoiceOut *amixer_output_stream;
+    int16_t audio_buffer_0[AUD_CHBUF_MAX_DEPTH];
+    int16_t audio_buffer_1[AUD_CHBUF_MAX_DEPTH];
+    size_t audio_data_available[2];
+    int64_t temp_buffer[AUD_CHBUF_MAX_DEPTH];
+    int16_t out_buffer[AUD_CHBUF_MAX_DEPTH];
+    size_t byte_left; /* byte available in out_buffer. */
+    size_t data_ptr;  /* next byte to be sent to QEMU. */
+
+    /* Associated DPDMA controller. */
+    XlnxDPDMAState *dpdma;
+
+    qemu_irq irq;
+
+    AUXBus *aux_bus;
+    Fifo8 rx_fifo;
+    Fifo8 tx_fifo;
+
+    /*
+     * XXX: This should be in an other module.
+     */
+    DPCDState *dpcd;
+    I2CDDCState *edid;
+} XlnxDPState;
+
+#define TYPE_XLNX_DP "xlnx.v-dp"
+#define XLNX_DP(obj) OBJECT_CHECK(XlnxDPState, (obj), TYPE_XLNX_DP)
+
+#endif /* !XLNX_DP_H */
diff --git a/include/hw/dma/xlnx_dpdma.h b/include/hw/dma/xlnx_dpdma.h
new file mode 100644
index 0000000..ae571a0
--- /dev/null
+++ b/include/hw/dma/xlnx_dpdma.h
@@ -0,0 +1,85 @@
+/*
+ * xlnx_dpdma.h
+ *
+ *  Copyright (C) 2015 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.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/>.
+ *
+ */
+
+#ifndef XLNX_DPDMA_H
+#define XLNX_DPDMA_H
+
+#include "hw/sysbus.h"
+#include "ui/console.h"
+#include "sysemu/dma.h"
+
+#define XLNX_DPDMA_REG_ARRAY_SIZE (0x1000 >> 2)
+
+struct XlnxDPDMAState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+    MemoryRegion iomem;
+    uint32_t registers[XLNX_DPDMA_REG_ARRAY_SIZE];
+    uint8_t *data[6];
+    bool operation_finished[6];
+    qemu_irq irq;
+};
+
+typedef struct XlnxDPDMAState XlnxDPDMAState;
+
+#define TYPE_XLNX_DPDMA "xlnx.dpdma"
+#define XLNX_DPDMA(obj) OBJECT_CHECK(XlnxDPDMAState, (obj), TYPE_XLNX_DPDMA)
+
+/*
+ * xlnx_dpdma_start_operation: Start the operation on the specified channel. The
+ *                             DPDMA gets the current descriptor and retrieves
+ *                             data to the buffer specified by
+ *                             dpdma_set_host_data_location().
+ *
+ * Returns The number of bytes transfered by the DPDMA or 0 if an error occured.
+ *
+ * @s The DPDMA state.
+ * @channel The channel to start.
+ */
+size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel,
+                                  bool one_desc);
+
+/*
+ * xlnx_dpdma_set_host_data_location: Set the location in the host memory where
+ *                                    to store the data out from the dma
+ *                                    channel.
+ *
+ * @s The DPDMA state.
+ * @channel The channel associated to the pointer.
+ * @p The buffer where to store the data.
+ */
+/* XXX: add a maximum size arg and send an interrupt in case of overflow. */
+void xlnx_dpdma_set_host_data_location(XlnxDPDMAState *s, uint8_t channel,
+                                       void *p);
+
+/*
+ * xlnx_dpdma_trigger_vsync_irq: Trigger a VSYNC IRQ when the display is
+ *                               updated.
+ *
+ * @s The DPDMA state.
+ */
+void xlnx_dpdma_trigger_vsync_irq(XlnxDPDMAState *s);
+
+#endif /* !XLNX_DPDMA_H */
diff --git a/include/hw/i2c/i2c-ddc.h b/include/hw/i2c/i2c-ddc.h
new file mode 100644
index 0000000..cb8e62d
--- /dev/null
+++ b/include/hw/i2c/i2c-ddc.h
@@ -0,0 +1,38 @@
+/* A simple I2C slave for returning monitor EDID data via DDC.
+ *
+ * Copyright (c) 2011 Linaro Limited
+ * Written by Peter Maydell
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  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/>.
+ */
+
+#ifndef I2C_DDC
+#define I2C_DDC
+
+/* A simple I2C slave which just returns the contents of its EDID blob. */
+
+struct I2CDDCState {
+    /*< private >*/
+    I2CSlave i2c;
+    /*< public >*/
+    bool firstbyte;
+    uint8_t reg;
+    uint8_t edid_blob[128];
+};
+
+typedef struct I2CDDCState I2CDDCState;
+
+#define TYPE_I2CDDC "i2c-ddc"
+#define I2CDDC(obj) OBJECT_CHECK(I2CDDCState, (obj), TYPE_I2CDDC)
+
+#endif /* !I2C_DDC */
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index 4986ebc..c4085aa 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -56,6 +56,7 @@
 int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv);
 void i2c_end_transfer(I2CBus *bus);
 void i2c_nack(I2CBus *bus);
+int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send);
 int i2c_send(I2CBus *bus, uint8_t data);
 int i2c_recv(I2CBus *bus);
 
diff --git a/include/hw/misc/aux.h b/include/hw/misc/aux.h
new file mode 100644
index 0000000..759c3bf
--- /dev/null
+++ b/include/hw/misc/aux.h
@@ -0,0 +1,128 @@
+/*
+ * aux.h
+ *
+ *  Copyright (C)2014 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.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/>.
+ *
+ */
+
+#ifndef QEMU_AUX_H
+#define QEMU_AUX_H
+
+#include "hw/qdev.h"
+
+typedef struct AUXBus AUXBus;
+typedef struct AUXSlave AUXSlave;
+typedef enum AUXCommand AUXCommand;
+typedef enum AUXReply AUXReply;
+typedef struct AUXTOI2CState AUXTOI2CState;
+
+enum AUXCommand {
+    WRITE_I2C = 0,
+    READ_I2C = 1,
+    WRITE_I2C_STATUS = 2,
+    WRITE_I2C_MOT = 4,
+    READ_I2C_MOT = 5,
+    WRITE_AUX = 8,
+    READ_AUX = 9
+};
+
+enum AUXReply {
+    AUX_I2C_ACK = 0,
+    AUX_NACK = 1,
+    AUX_DEFER = 2,
+    AUX_I2C_NACK = 4,
+    AUX_I2C_DEFER = 8
+};
+
+#define TYPE_AUX_BUS "aux-bus"
+#define AUX_BUS(obj) OBJECT_CHECK(AUXBus, (obj), TYPE_AUX_BUS)
+
+struct AUXBus {
+    /* < private > */
+    BusState qbus;
+
+    /* < public > */
+    AUXSlave *current_dev;
+    AUXSlave *dev;
+    uint32_t last_i2c_address;
+    AUXCommand last_transaction;
+
+    AUXTOI2CState *bridge;
+
+    MemoryRegion *aux_io;
+    AddressSpace aux_addr_space;
+};
+
+#define TYPE_AUX_SLAVE "aux-slave"
+#define AUX_SLAVE(obj) \
+     OBJECT_CHECK(AUXSlave, (obj), TYPE_AUX_SLAVE)
+
+struct AUXSlave {
+    /* < private > */
+    DeviceState parent_obj;
+
+    /* < public > */
+    MemoryRegion *mmio;
+};
+
+/**
+ * aux_init_bus: Initialize an AUX bus.
+ *
+ * Returns the new AUX bus created.
+ *
+ * @parent The device where this bus is located.
+ * @name The name of the bus.
+ */
+AUXBus *aux_init_bus(DeviceState *parent, const char *name);
+
+/*
+ * aux_request: Make a request on the bus.
+ *
+ * Returns the reply of the request.
+ *
+ * @bus Ths bus where the request happen.
+ * @cmd The command requested.
+ * @address The 20bits address of the slave.
+ * @len The length of the read or write.
+ * @data The data array which will be filled or read during transfer.
+ */
+AUXReply aux_request(AUXBus *bus, AUXCommand cmd, uint32_t address,
+                              uint8_t len, uint8_t *data);
+
+/*
+ * aux_get_i2c_bus: Get the i2c bus for I2C over AUX command.
+ *
+ * Returns the i2c bus associated to this AUX bus.
+ *
+ * @bus The AUX bus.
+ */
+I2CBus *aux_get_i2c_bus(AUXBus *bus);
+
+/*
+ * aux_init_mmio: Init an mmio for an AUX slave.
+ *
+ * @aux_slave The AUX slave.
+ * @mmio The mmio to be registered.
+ */
+void aux_init_mmio(AUXSlave *aux_slave, MemoryRegion *mmio);
+
+DeviceState *aux_create_slave(AUXBus *bus, const char *name, uint32_t addr);
+
+#endif /* !QEMU_AUX_H */
diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h
index 0cce4e8..d15a6cc 100644
--- a/include/hw/ppc/mac_dbdma.h
+++ b/include/hw/ppc/mac_dbdma.h
@@ -24,6 +24,7 @@
 
 #include "exec/memory.h"
 #include "qemu/iov.h"
+#include "sysemu/dma.h"
 
 typedef struct DBDMA_io DBDMA_io;
 
@@ -44,6 +45,10 @@
     uint8_t head_remainder[0x200];
     uint8_t tail_remainder[0x200];
     QEMUIOVector iov;
+    /* DMA request */
+    void *dma_mem;
+    dma_addr_t dma_len;
+    DMADirection dir;
 };
 
 /*
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 971df3d..3ac85c0 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -620,9 +620,11 @@
 #define SPAPR_DR_LMB_LIST_ENTRY_SIZE 6
 
 /*
- * This flag value defines the LMB as assigned in ibm,dynamic-memory
- * property under ibm,dynamic-reconfiguration-memory node.
+ * Defines for flag value in ibm,dynamic-memory property under
+ * ibm,dynamic-reconfiguration-memory node.
  */
 #define SPAPR_LMB_FLAGS_ASSIGNED 0x00000008
+#define SPAPR_LMB_FLAGS_DRC_INVALID 0x00000020
+#define SPAPR_LMB_FLAGS_RESERVED 0x00000080
 
 #endif /* !defined (__HW_SPAPR_H__) */
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index 98b2e2c..38f4d77 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -151,5 +151,22 @@
 int css_do_rchp(uint8_t cssid, uint8_t chpid);
 bool css_present(uint8_t cssid);
 #endif
+/*
+ * Identify a device within the channel subsystem.
+ * Note that this can be used to identify either the subchannel or
+ * the attached I/O device, as there's always one I/O device per
+ * subchannel.
+ */
+typedef struct CssDevId {
+    uint8_t cssid;
+    uint8_t ssid;
+    uint16_t devid;
+    bool valid;
+} CssDevId;
+
+extern PropertyInfo css_devid_propinfo;
+
+#define DEFINE_PROP_CSS_DEV_ID(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, css_devid_propinfo, CssDevId)
 
 #endif
diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
index 200e7e9..1dac2ee 100644
--- a/include/hw/s390x/s390_flic.h
+++ b/include/hw/s390x/s390_flic.h
@@ -49,6 +49,8 @@
                           bool do_map);
     int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes);
     void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes);
+    int (*clear_io_irq)(S390FLICState *fs, uint16_t subchannel_id,
+                        uint16_t subchannel_nr);
 } S390FLICStateClass;
 
 #define TYPE_KVM_S390_FLIC "s390-flic-kvm"
diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h
index 1becea8..4040951 100644
--- a/include/standard-headers/linux/pci_regs.h
+++ b/include/standard-headers/linux/pci_regs.h
@@ -670,7 +670,8 @@
 #define PCI_EXT_CAP_ID_SECPCI	0x19	/* Secondary PCIe Capability */
 #define PCI_EXT_CAP_ID_PMUX	0x1A	/* Protocol Multiplexing */
 #define PCI_EXT_CAP_ID_PASID	0x1B	/* Process Address Space ID */
-#define PCI_EXT_CAP_ID_MAX	PCI_EXT_CAP_ID_PASID
+#define PCI_EXT_CAP_ID_DPC	0x1D	/* Downstream Port Containment */
+#define PCI_EXT_CAP_ID_MAX	PCI_EXT_CAP_ID_DPC
 
 #define PCI_EXT_CAP_DSN_SIZEOF	12
 #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
@@ -946,4 +947,21 @@
 #define PCI_TPH_CAP_ST_SHIFT	16	/* st table shift */
 #define PCI_TPH_BASE_SIZEOF	12	/* size with no st table */
 
+/* Downstream Port Containment */
+#define PCI_EXP_DPC_CAP			4	/* DPC Capability */
+#define  PCI_EXP_DPC_CAP_RP_EXT		0x20	/* Root Port Extensions for DPC */
+#define  PCI_EXP_DPC_CAP_POISONED_TLP	0x40	/* Poisoned TLP Egress Blocking Supported */
+#define  PCI_EXP_DPC_CAP_SW_TRIGGER	0x80	/* Software Triggering Supported */
+#define  PCI_EXP_DPC_CAP_DL_ACTIVE	0x1000	/* ERR_COR signal on DL_Active supported */
+
+#define PCI_EXP_DPC_CTL			6	/* DPC control */
+#define  PCI_EXP_DPC_CTL_EN_NONFATAL 	0x02	/* Enable trigger on ERR_NONFATAL message */
+#define  PCI_EXP_DPC_CTL_INT_EN 	0x08	/* DPC Interrupt Enable */
+
+#define PCI_EXP_DPC_STATUS		8	/* DPC Status */
+#define  PCI_EXP_DPC_STATUS_TRIGGER	0x01	/* Trigger Status */
+#define  PCI_EXP_DPC_STATUS_INTERRUPT	0x08	/* Interrupt Status */
+
+#define PCI_EXP_DPC_SOURCE_ID		10	/* DPC Source Identifier */
+
 #endif /* LINUX_PCI_REGS_H */
diff --git a/include/standard-headers/linux/virtio_config.h b/include/standard-headers/linux/virtio_config.h
index bcc445b..b30d0cb 100644
--- a/include/standard-headers/linux/virtio_config.h
+++ b/include/standard-headers/linux/virtio_config.h
@@ -40,6 +40,8 @@
 #define VIRTIO_CONFIG_S_DRIVER_OK	4
 /* Driver has finished configuring features */
 #define VIRTIO_CONFIG_S_FEATURES_OK	8
+/* Device entered invalid state, driver must reset it */
+#define VIRTIO_CONFIG_S_NEEDS_RESET	0x40
 /* We've given up on this device. */
 #define VIRTIO_CONFIG_S_FAILED		0x80
 
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 9428141..7313673 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -233,7 +233,6 @@
 QemuOpts *qemu_get_machine_opts(void);
 
 bool defaults_enabled(void);
-bool usb_enabled(void);
 
 extern QemuOptsList qemu_legacy_drive_opts;
 extern QemuOptsList qemu_common_drive_opts;
diff --git a/linux-headers/asm-arm/unistd.h b/linux-headers/asm-arm/unistd.h
index 3f6f727..ceb5450 100644
--- a/linux-headers/asm-arm/unistd.h
+++ b/linux-headers/asm-arm/unistd.h
@@ -418,6 +418,8 @@
 #define __NR_membarrier			(__NR_SYSCALL_BASE+389)
 #define __NR_mlock2			(__NR_SYSCALL_BASE+390)
 #define __NR_copy_file_range		(__NR_SYSCALL_BASE+391)
+#define __NR_preadv2			(__NR_SYSCALL_BASE+392)
+#define __NR_pwritev2			(__NR_SYSCALL_BASE+393)
 
 /*
  * The following SWIs are ARM private.
diff --git a/linux-headers/asm-arm64/unistd.h b/linux-headers/asm-arm64/unistd.h
index 1caadc2..043d17a 100644
--- a/linux-headers/asm-arm64/unistd.h
+++ b/linux-headers/asm-arm64/unistd.h
@@ -13,4 +13,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#define __ARCH_WANT_RENAMEAT
+
 #include <asm-generic/unistd.h>
diff --git a/linux-headers/asm-powerpc/unistd.h b/linux-headers/asm-powerpc/unistd.h
index cd92d98..1e66eba 100644
--- a/linux-headers/asm-powerpc/unistd.h
+++ b/linux-headers/asm-powerpc/unistd.h
@@ -390,5 +390,7 @@
 #define __NR_membarrier		365
 #define __NR_mlock2		378
 #define __NR_copy_file_range	379
+#define __NR_preadv2		380
+#define __NR_pwritev2		381
 
 #endif /* _ASM_POWERPC_UNISTD_H_ */
diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
index a59499b..09ae5dc 100644
--- a/linux-headers/asm-s390/kvm.h
+++ b/linux-headers/asm-s390/kvm.h
@@ -25,6 +25,7 @@
 #define KVM_DEV_FLIC_APF_DISABLE_WAIT	5
 #define KVM_DEV_FLIC_ADAPTER_REGISTER	6
 #define KVM_DEV_FLIC_ADAPTER_MODIFY	7
+#define KVM_DEV_FLIC_CLEAR_IO_IRQ	8
 /*
  * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
  * as well as up  to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
diff --git a/linux-headers/asm-s390/unistd.h b/linux-headers/asm-s390/unistd.h
index 885837e..8a404fd 100644
--- a/linux-headers/asm-s390/unistd.h
+++ b/linux-headers/asm-s390/unistd.h
@@ -311,7 +311,9 @@
 #define __NR_shutdown		373
 #define __NR_mlock2		374
 #define __NR_copy_file_range	375
-#define NR_syscalls 376
+#define __NR_preadv2		376
+#define __NR_pwritev2		377
+#define NR_syscalls 378
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
index cd54147..739c0c5 100644
--- a/linux-headers/asm-x86/kvm.h
+++ b/linux-headers/asm-x86/kvm.h
@@ -216,9 +216,9 @@
 	__u32 padding[3];
 };
 
-#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX		BIT(0)
-#define KVM_CPUID_FLAG_STATEFUL_FUNC		BIT(1)
-#define KVM_CPUID_FLAG_STATE_READ_NEXT		BIT(2)
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX		(1 << 0)
+#define KVM_CPUID_FLAG_STATEFUL_FUNC		(1 << 1)
+#define KVM_CPUID_FLAG_STATE_READ_NEXT		(1 << 2)
 
 /* for KVM_SET_CPUID2 */
 struct kvm_cpuid2 {
diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h
index 8f77ee8..0230779 100644
--- a/linux-headers/asm-x86/unistd_x32.h
+++ b/linux-headers/asm-x86/unistd_x32.h
@@ -306,7 +306,9 @@
 #define __NR_vmsplice (__X32_SYSCALL_BIT + 532)
 #define __NR_move_pages (__X32_SYSCALL_BIT + 533)
 #define __NR_preadv (__X32_SYSCALL_BIT + 534)
+#define __NR_preadv2 (__X32_SYSCALL_BIT + 534)
 #define __NR_pwritev (__X32_SYSCALL_BIT + 535)
+#define __NR_pwritev2 (__X32_SYSCALL_BIT + 535)
 #define __NR_rt_tgsigqueueinfo (__X32_SYSCALL_BIT + 536)
 #define __NR_recvmmsg (__X32_SYSCALL_BIT + 537)
 #define __NR_sendmmsg (__X32_SYSCALL_BIT + 538)
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 3bae71a..e60e21b 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -865,6 +865,7 @@
 #define KVM_CAP_SPAPR_TCE_64 125
 #define KVM_CAP_ARM_PMU_V3 126
 #define KVM_CAP_VCPU_ATTRIBUTES 127
+#define KVM_CAP_MAX_VCPU_ID 128
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 17d8051..942aa36 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -572,6 +572,8 @@
     bool powered_off;
     /* CPU has security extension */
     bool has_el3;
+    /* CPU has PMU (Performance Monitor Unit) */
+    bool has_pmu;
 
     /* CPU has memory protection unit */
     bool has_mpu;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 862e780..c9730d6 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3765,8 +3765,11 @@
       .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 2,
       .access = PL3_RW,
       /* no .writefn needed as this can't cause an ASID change;
-       * no .raw_writefn or .resetfn needed as we never use mask/base_mask
+       * we must provide a .raw_writefn and .resetfn because we handle
+       * reset and migration for the AArch32 TTBCR(S), which might be
+       * using mask and base_mask.
        */
+      .resetfn = vmsa_ttbcr_reset, .raw_writefn = vmsa_ttbcr_raw_write,
       .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[3]) },
     { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
       .type = ARM_CP_ALIAS,
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index c03e3e5..c35c676 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -522,3 +522,9 @@
 {
     return false;
 }
+
+int kvm_arm_pmu_create(CPUState *cs, int irq)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+    return 0;
+}
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index e2a34f6..2d6a310 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -382,6 +382,47 @@
     return NULL;
 }
 
+static bool kvm_arm_pmu_support_ctrl(CPUState *cs, struct kvm_device_attr *attr)
+{
+    return kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr) == 0;
+}
+
+int kvm_arm_pmu_create(CPUState *cs, int irq)
+{
+    int err;
+
+    struct kvm_device_attr attr = {
+        .group = KVM_ARM_VCPU_PMU_V3_CTRL,
+        .addr = (intptr_t)&irq,
+        .attr = KVM_ARM_VCPU_PMU_V3_IRQ,
+        .flags = 0,
+    };
+
+    if (!kvm_arm_pmu_support_ctrl(cs, &attr)) {
+        return 0;
+    }
+
+    err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, &attr);
+    if (err < 0) {
+        fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
+                strerror(-err));
+        abort();
+    }
+
+    attr.group = KVM_ARM_VCPU_PMU_V3_CTRL;
+    attr.attr = KVM_ARM_VCPU_PMU_V3_INIT;
+    attr.addr = 0;
+    attr.flags = 0;
+
+    err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, &attr);
+    if (err < 0) {
+        fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
+                strerror(-err));
+        abort();
+    }
+
+    return 1;
+}
 
 static inline void set_feature(uint64_t *features, int feature)
 {
@@ -461,6 +502,11 @@
     if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
         cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_EL1_32BIT;
     }
+    if (kvm_irqchip_in_kernel() &&
+        kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3)) {
+        cpu->has_pmu = true;
+        cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PMU_V3;
+    }
 
     /* Do KVM_ARM_VCPU_INIT ioctl */
     ret = kvm_arm_vcpu_init(cs);
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index 345233c..a419368 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -194,6 +194,8 @@
 
 int kvm_arm_vgic_probe(void);
 
+int kvm_arm_pmu_create(CPUState *cs, int irq);
+
 #else
 
 static inline int kvm_arm_vgic_probe(void)
@@ -201,6 +203,11 @@
     return 0;
 }
 
+static inline int kvm_arm_pmu_create(CPUState *cs, int irq)
+{
+    return 0;
+}
+
 #endif
 
 static inline const char *gic_class_name(void)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 6815bc1a..3e71467 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5311,6 +5311,30 @@
             op >= NEON_2RM_VRECPE_F);
 }
 
+static bool neon_2rm_is_v8_op(int op)
+{
+    /* Return true if this neon 2reg-misc op is ARMv8 and up */
+    switch (op) {
+    case NEON_2RM_VRINTN:
+    case NEON_2RM_VRINTA:
+    case NEON_2RM_VRINTM:
+    case NEON_2RM_VRINTP:
+    case NEON_2RM_VRINTZ:
+    case NEON_2RM_VRINTX:
+    case NEON_2RM_VCVTAU:
+    case NEON_2RM_VCVTAS:
+    case NEON_2RM_VCVTNU:
+    case NEON_2RM_VCVTNS:
+    case NEON_2RM_VCVTPU:
+    case NEON_2RM_VCVTPS:
+    case NEON_2RM_VCVTMU:
+    case NEON_2RM_VCVTMS:
+        return true;
+    default:
+        return false;
+    }
+}
+
 /* Each entry in this array has bit n set if the insn allows
  * size value n (otherwise it will UNDEF). Since unallocated
  * op values will have no bits set they always UNDEF.
@@ -6798,6 +6822,10 @@
                 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
                     return 1;
                 }
+                if (neon_2rm_is_v8_op(op) &&
+                    !arm_dc_feature(s, ARM_FEATURE_V8)) {
+                    return 1;
+                }
                 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
                     q && ((rm | rd) & 1)) {
                     return 1;
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 07358aa..969ecdf 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -165,7 +165,8 @@
 
     uint32_t pvr;
     bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr);
-    uint64_t pcr_mask;
+    uint64_t pcr_mask;          /* Available bits in PCR register */
+    uint64_t pcr_supported;     /* Bits for supported PowerISA versions */
     uint32_t svr;
     uint64_t insns_flags;
     uint64_t insns_flags2;
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index cb8b912..93c2dd5 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1187,7 +1187,9 @@
 
 void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 int ppc_get_compat_smt_threads(PowerPCCPU *cpu);
+#if defined(TARGET_PPC64)
 void ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version, Error **errp);
+#endif
 
 /* Time-base and decrementer management */
 #ifndef NO_CPU_IO_DEFS
@@ -2200,6 +2202,7 @@
 enum {
     PCR_COMPAT_2_05     = 1ull << (63-62),
     PCR_COMPAT_2_06     = 1ull << (63-61),
+    PCR_COMPAT_2_07     = 1ull << (63-60),
     PCR_VEC_DIS         = 1ull << (63-0), /* Vec. disable (bit NA since POWER8) */
     PCR_VSX_DIS         = 1ull << (63-1), /* VSX disable (bit NA since POWER8) */
     PCR_TM_DIS          = 1ull << (63-2), /* Trans. memory disable (POWER8) */
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 24d6032..6c15361 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -2329,6 +2329,19 @@
     return POWERPC_CPU_CLASS(oc);
 }
 
+PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
+{
+    uint32_t host_pvr = mfpvr();
+    PowerPCCPUClass *pvr_pcc;
+
+    pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
+    if (pvr_pcc == NULL) {
+        pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr);
+    }
+
+    return pvr_pcc;
+}
+
 static int kvm_ppc_register_host_cpu_type(void)
 {
     TypeInfo type_info = {
@@ -2336,14 +2349,10 @@
         .instance_init = kvmppc_host_cpu_initfn,
         .class_init = kvmppc_host_cpu_class_init,
     };
-    uint32_t host_pvr = mfpvr();
     PowerPCCPUClass *pvr_pcc;
     DeviceClass *dc;
 
-    pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
-    if (pvr_pcc == NULL) {
-        pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr);
-    }
+    pvr_pcc = kvm_ppc_get_host_cpu_class();
     if (pvr_pcc == NULL) {
         return -1;
     }
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 3b2090e..20bfb59 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -56,6 +56,7 @@
 bool kvmppc_has_cap_fixup_hcalls(void);
 int kvmppc_enable_hwrng(void);
 int kvmppc_put_books_sregs(PowerPCCPU *cpu);
+PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
 
 #else
 
@@ -252,6 +253,12 @@
 {
     abort();
 }
+
+static inline PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
+{
+    return NULL;
+}
+
 #endif
 
 #ifndef CONFIG_KVM
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index a1db500..ca894ff 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8365,7 +8365,8 @@
     dc->desc = "POWER7";
     dc->props = powerpc_servercpu_properties;
     pcc->pvr_match = ppc_pvr_match_power7;
-    pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
+    pcc->pcr_mask = PCR_VEC_DIS | PCR_VSX_DIS | PCR_COMPAT_2_05;
+    pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@@ -8445,7 +8446,8 @@
     dc->desc = "POWER8";
     dc->props = powerpc_servercpu_properties;
     pcc->pvr_match = ppc_pvr_match_power8;
-    pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
+    pcc->pcr_mask = PCR_TM_DIS | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
+    pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
     pcc->init_proc = init_proc_POWER8;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@@ -9513,28 +9515,37 @@
     return ret;
 }
 
+#ifdef TARGET_PPC64
 void ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version, Error **errp)
 {
     int ret = 0;
     CPUPPCState *env = &cpu->env;
+    PowerPCCPUClass *host_pcc;
 
     cpu->cpu_version = cpu_version;
 
     switch (cpu_version) {
     case CPU_POWERPC_LOGICAL_2_05:
-        env->spr[SPR_PCR] = PCR_COMPAT_2_05;
+        env->spr[SPR_PCR] = PCR_TM_DIS | PCR_VSX_DIS | PCR_COMPAT_2_07 |
+                            PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
         break;
     case CPU_POWERPC_LOGICAL_2_06:
-        env->spr[SPR_PCR] = PCR_COMPAT_2_06;
-        break;
     case CPU_POWERPC_LOGICAL_2_06_PLUS:
-        env->spr[SPR_PCR] = PCR_COMPAT_2_06;
+        env->spr[SPR_PCR] = PCR_TM_DIS | PCR_COMPAT_2_07 | PCR_COMPAT_2_06;
+        break;
+    case CPU_POWERPC_LOGICAL_2_07:
+        env->spr[SPR_PCR] = PCR_COMPAT_2_07;
         break;
     default:
         env->spr[SPR_PCR] = 0;
         break;
     }
 
+    host_pcc = kvm_ppc_get_host_cpu_class();
+    if (host_pcc) {
+        env->spr[SPR_PCR] &= host_pcc->pcr_mask;
+    }
+
     if (kvm_enabled()) {
         ret = kvmppc_set_compat(cpu, cpu->cpu_version);
         if (ret < 0) {
@@ -9543,6 +9554,7 @@
         }
     }
 }
+#endif
 
 static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
 {
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 8f46fd0..f108cd3 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -2071,8 +2071,9 @@
     if (io_int_word & IO_INT_WORD_AI) {
         irq.type = KVM_S390_INT_IO(1, 0, 0, 0);
     } else {
-        irq.type = ((subchannel_id & 0xff00) << 24) |
-            ((subchannel_id & 0x00060) << 22) | (subchannel_nr << 16);
+        irq.type = KVM_S390_INT_IO(0, (subchannel_id & 0xff00) >> 8,
+                                      (subchannel_id & 0x0006),
+                                      subchannel_nr);
     }
     kvm_s390_floating_interrupt(&irq);
 }
diff --git a/trace-events b/trace-events
index 421d89f..2f14205 100644
--- a/trace-events
+++ b/trace-events
@@ -1475,6 +1475,7 @@
 # hw/s390x/virtio-ccw.c
 virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) "VIRTIO-CCW: %x.%x.%04x: interpret command %x"
 virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char *devno_mode) "VIRTIO-CCW: add subchannel %x.%x.%04x, devno %04x (%s)"
+virtio_ccw_set_ind(uint64_t ind_loc, uint8_t ind_old, uint8_t ind_new) "VIRTIO-CCW: indicator at %" PRIu64 ": %x->%x"
 
 # hw/intc/s390_flic_kvm.c
 flic_create_device(int err) "flic: create device failed %d"
diff --git a/vl.c b/vl.c
index b0bcc25..45eff56 100644
--- a/vl.c
+++ b/vl.c
@@ -1072,11 +1072,6 @@
     return has_defaults;
 }
 
-bool usb_enabled(void)
-{
-    return machine_usb(current_machine);
-}
-
 #ifndef _WIN32
 static int parse_add_fd(void *opaque, QemuOpts *opts, Error **errp)
 {
@@ -1393,7 +1388,7 @@
     const char *p;
 #endif
 
-    if (!usb_enabled()) {
+    if (!machine_usb(current_machine)) {
         return -1;
     }
 
@@ -1425,7 +1420,7 @@
         return -1;
     }
 
-    if (!usb_enabled()) {
+    if (!machine_usb(current_machine)) {
         return -1;
     }
 
@@ -4501,7 +4496,7 @@
     }
 
     /* init USB devices */
-    if (usb_enabled()) {
+    if (machine_usb(current_machine)) {
         if (foreach_device_config(DEV_USB, usb_parse) < 0)
             exit(1);
     }